Add Steps streaks screen

This commit is contained in:
vanous 2022-07-23 23:37:48 +02:00
parent 4dc4a4f988
commit 23a7f2da94
19 changed files with 1130 additions and 45 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -20,11 +20,14 @@ package nodomain.freeyourgadget.gadgetbridge.activities.charts;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.fragment.app.FragmentManager;
import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.charts.PieChart;
import com.github.mikephil.charting.components.LimitLine;
@ -38,6 +41,7 @@ import com.github.mikephil.charting.data.PieData;
import com.github.mikephil.charting.data.PieDataSet;
import com.github.mikephil.charting.data.PieEntry;
import com.github.mikephil.charting.formatter.ValueFormatter;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -69,6 +73,7 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment {
private TextView mBalanceView;
private int mOffsetHours = getOffsetHours();
FloatingActionButton stepsStreaksFAB;
@Override
protected ChartsData refreshInBackground(ChartsHost chartsHost, DBHandler db, GBDevice device) {
@ -98,6 +103,21 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment {
mWeekChart.getXAxis().setValueFormatter(mcd.getWeekBeforeData().getXValueFormatter());
mBalanceView.setText(mcd.getWeekBeforeData().getBalanceMessage());
//disable the streak FAB once we move away from today
Calendar day = Calendar.getInstance();
day.setTime(getChartsHost().getEndDate());
stepsStreaksFAB.setAlpha((float) 1.0);
if (DateUtils.isToday(day.getTimeInMillis()) && enableStepStreaksFAB()){
stepsStreaksFAB.setVisibility(View.VISIBLE);
}else
{
stepsStreaksFAB.setVisibility(View.GONE);
}
}
private boolean enableStepStreaksFAB(){
return this.getClass().getSimpleName().equals("WeekStepsChartFragment");
}
@Override
@ -225,7 +245,7 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment {
View rootView = inflater.inflate(R.layout.fragment_weeksteps_chart, container, false);
int goal = getGoal();
final int goal = getGoal();
if (goal >= 0) {
mTargetValue = goal;
}
@ -237,12 +257,29 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment {
setupWeekChart();
setupTodayPieChart();
stepsStreaksFAB = rootView.findViewById(R.id.fab_steps_streaks);
if (enableStepStreaksFAB()) {
stepsStreaksFAB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stepsStreaksFAB.setAlpha((float) 0.5);
FragmentManager fm = getActivity().getSupportFragmentManager();
StepStreaksDashboard stepStreaksDashboard = StepStreaksDashboard.newInstance(getGoal(), getChartsHost().getDevice());
stepStreaksDashboard.show(fm, "steps_streaks_dashboard");
}
});
}
// refresh immediately instead of use refreshIfVisible(), for perceived performance
refresh();
return rootView;
}
private void setupTodayPieChart() {
mTodayPieChart.setBackgroundColor(BACKGROUND_COLOR);
mTodayPieChart.getDescription().setTextColor(DESCRIPTION_COLOR);

View File

@ -0,0 +1,274 @@
package nodomain.freeyourgadget.gadgetbridge.activities.charts;
import android.content.Context;
import android.os.Bundle;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentActivity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Calendar;
import java.util.Date;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.database.DBAccess;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.DailyTotals;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class StepStreaksDashboard extends DialogFragment {
protected static final Logger LOG = LoggerFactory.getLogger(StepStreaksDashboard.class);
GBDevice gbDevice;
int goal;
boolean cancelTasks = false;
private View fragmentView;
private StepsStreaks stepsStreaks = new StepsStreaks();
public StepStreaksDashboard() {
}
public static StepStreaksDashboard newInstance(int goal, GBDevice device) {
StepStreaksDashboard fragment = new StepStreaksDashboard();
Bundle args = new Bundle();
args.putInt("goal", goal);
args.putParcelable(GBDevice.EXTRA_DEVICE, device);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.steps_streaks_dashboard, container);
}
@Override
public void onStop() {
super.onStop();
cancelTasks = true;
}
@Override
public void onDestroy() {
super.onDestroy();
cancelTasks = true;
}
@Override
public void onViewCreated(final View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
goal = getArguments().getInt("goal", 0);
gbDevice = getArguments().getParcelable(GBDevice.EXTRA_DEVICE);
fragmentView = view;
if (gbDevice == null) {
throw new IllegalArgumentException("Must provide a device when invoking this activity");
}
createTaskCalculateLatestStepsStreak("Visualizing data current", getActivity(), "current").execute();
createTaskCalculateLatestStepsStreak("Visualizing data maximum", getActivity(), "maximum").execute();
}
void indicate_progress(boolean inProgress) {
ProgressBar step_streak_dashboard_loading_circle = fragmentView.findViewById(R.id.step_streak_dashboard_loading_circle);
if (inProgress) {
step_streak_dashboard_loading_circle.setAlpha(0.5f);
} else {
step_streak_dashboard_loading_circle.setAlpha(0);
}
}
void populateData() {
LinearLayout current = getView().findViewById(R.id.step_streak_current_layout);
TextView days_current = current.findViewById(R.id.step_streak_days_value);
TextView average_current = current.findViewById(R.id.step_streak_average_value);
TextView total_current = current.findViewById(R.id.step_streak_total_value);
LinearLayout maximum = getView().findViewById(R.id.step_streak_maximum_layout);
TextView days_maximum = maximum.findViewById(R.id.step_streak_days_value);
TextView average_maximum = maximum.findViewById(R.id.step_streak_average_value);
TextView total_maximum = maximum.findViewById(R.id.step_streak_total_value);
TextView date_maximum_value = maximum.findViewById(R.id.step_streak_maximum_date_value);
LinearLayout total = getView().findViewById(R.id.step_streak_total_layout);
TextView days_total = total.findViewById(R.id.step_streak_days_value);
TextView days_total_label = total.findViewById(R.id.step_streak_days_label);
TextView total_total = total.findViewById(R.id.step_streak_total_value);
if (stepsStreaks.current.days > 0) {
current.setVisibility(View.VISIBLE);
days_current.setText(Integer.toString(stepsStreaks.current.days));
average_current.setText(Integer.toString(stepsStreaks.current.steps / stepsStreaks.current.days));
total_current.setText(Integer.toString(stepsStreaks.current.steps));
}
if (stepsStreaks.maximum.days > 0) {
maximum.setVisibility(View.VISIBLE);
days_maximum.setText(Integer.toString(stepsStreaks.maximum.days));
average_maximum.setText(Integer.toString(stepsStreaks.maximum.steps / stepsStreaks.maximum.days));
total_maximum.setText(Integer.toString(stepsStreaks.maximum.steps));
date_maximum_value.setText(DateTimeUtils.formatDate(new Date(stepsStreaks.maximum.timestamp * 1000l)));
LOG.debug("petr " + stepsStreaks.total.timestamp);
}
if (stepsStreaks.total.days > 0) {
total.setVisibility(View.VISIBLE);
days_total_label.setText("Achievement\n rate");
days_total.setText(String.format("%.1f%%", (float) stepsStreaks.total.days / stepsStreaks.total.total_days * 100));
total_total.setText(Integer.toString(stepsStreaks.total.steps));
}
}
protected TaskCalculateLatestStepsStreak createTaskCalculateLatestStepsStreak(String taskName, Context context, String period) {
return new TaskCalculateLatestStepsStreak(taskName, context, period);
}
public class TaskCalculateLatestStepsStreak extends DBAccess {
String period;
public TaskCalculateLatestStepsStreak(String taskName, Context context, String period) {
super(taskName, context);
this.period = period;
}
@Override
protected void doInBackground(DBHandler db) {
switch (period) {
case "current":
calculateStreakData(db, "current", gbDevice, goal);
break;
case "maximum":
calculateStreakData(db, "totals", gbDevice, goal);
break;
}
}
@Override
protected void onPreExecute() {
indicate_progress(true);
}
@Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
FragmentActivity activity = getActivity();
if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) {
populateData();
if (period.equals("maximum")) {
indicate_progress(false);
}
} else {
LOG.info("Not filling data because activity is not available anymore");
}
}
}
private void calculateStreakData(DBHandler db, String period, GBDevice device, int goal) {
Calendar day = Calendar.getInstance();
int streak_steps = 0;
int streak_days = 0;
int timestamp = (int) (day.getTimeInMillis() / 1000);
int all_step_days = 0;
int all_streak_days = 0;
int all_steps = 0;
DailyTotals dailyTotals = new DailyTotals();
ActivitySample firstSample = dailyTotals.getFirstSample(db, device);
Calendar firstDate = Calendar.getInstance();
firstDate.setTime(new Date(firstSample.getTimestamp() * 1000l));
//NOTE: getting the first sample as a first day reference is not reliable
while (true) {
if (cancelTasks) {
GB.toast("bailing out background jobs", Toast.LENGTH_SHORT, GB.INFO);
break;
}
int steps_this_day = 0;
long[] daily_data = dailyTotals.getDailyTotalsForDevice(device, day, db);
steps_this_day = (int) daily_data[0];
if (steps_this_day > 0) {
all_step_days++;
all_steps += steps_this_day;
}
if (steps_this_day > goal) {
streak_steps += steps_this_day;
streak_days++;
all_streak_days++;
Date newDate = DateTimeUtils.shiftByDays(new Date(day.getTimeInMillis()), -1);
day.setTime(newDate);
} else if (DateUtils.isToday(day.getTimeInMillis())) {
//if goal is not reached today, we might still get our steps later
// so do not count this day but do not interrupt
Date newDate = DateTimeUtils.shiftByDays(new Date(day.getTimeInMillis()), -1);
day.setTime(newDate);
} else {
if (period.equals("current")) {
stepsStreaks.current.days = streak_days;
stepsStreaks.current.steps = streak_steps;
return;
} else if (period.equals("totals")) {
//reset max
if (streak_days > stepsStreaks.maximum.days) {
stepsStreaks.maximum.steps = streak_steps;
stepsStreaks.maximum.days = streak_days;
stepsStreaks.maximum.timestamp = timestamp;
}
stepsStreaks.total.steps = all_steps;
stepsStreaks.total.days = all_streak_days;
stepsStreaks.total.total_days = all_step_days;
streak_days = 0;
streak_steps = 0;
Date newDate = DateTimeUtils.shiftByDays(new Date(day.getTimeInMillis()), -1);
day.setTime(newDate);
timestamp = (int) (day.getTimeInMillis() / 1000);
if (day.before(firstDate) || day.get(Calendar.YEAR) < 2015) { //avoid rolling back too far
return;
}
}
}
}
}
private static class StepsStreak {
private int days = 0;
private int steps = 0;
private int timestamp;
private int total_days = 0;
}
private class StepsStreaks {
private StepsStreak current = new StepsStreak();
private StepsStreak maximum = new StepsStreak();
private StepsStreak total = new StepsStreak();
}
}

View File

@ -110,6 +110,26 @@ public abstract class AbstractSampleProvider<T extends AbstractActivitySample> i
return sample;
}
@Nullable
@Override
public T getFirstActivitySample() {
QueryBuilder<T> qb = getSampleDao().queryBuilder();
Device dbDevice = DBHelper.findDevice(getDevice(), getSession());
if (dbDevice == null) {
// no device, no sample
return null;
}
Property deviceProperty = getDeviceIdentifierSampleProperty();
qb.where(deviceProperty.eq(dbDevice.getId())).orderAsc(getTimestampSampleProperty()).limit(1);
List<T> samples = qb.build().list();
if (samples.isEmpty()) {
return null;
}
T sample = samples.get(0);
sample.setProvider(this);
return sample;
}
protected List<T> getGBActivitySamples(int timestamp_from, int timestamp_to, int activityType) {
if (getRawKindSampleProperty() == null && activityType != ActivityKind.TYPE_ALL) {
// if we do not have a raw kind property we cannot query anything else then TYPE_ALL

View File

@ -99,4 +99,12 @@ public interface SampleProvider<T extends AbstractActivitySample> {
*/
@Nullable
T getLatestActivitySample();
/**
* Returns the activity sample with the oldest timestamp. or null if none
* @return the oldest sample or null
*/
@Nullable
T getFirstActivitySample();
}

View File

@ -87,6 +87,13 @@ public class UnknownDeviceCoordinator extends AbstractDeviceCoordinator {
public AbstractActivitySample getLatestActivitySample() {
return null;
}
@Nullable
@Override
public AbstractActivitySample getFirstActivitySample() {
return null;
}
}
public UnknownDeviceCoordinator() {

View File

@ -143,9 +143,15 @@ public class DailyTotals {
return coordinator.getSampleProvider(device, db.getDaoSession());
}
protected List<? extends ActivitySample> getAllSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
SampleProvider<? extends ActivitySample> provider = getProvider(db, device);
return provider.getAllActivitySamples(tsFrom, tsTo);
}
public ActivitySample getFirstSample(DBHandler db, GBDevice device) {
SampleProvider<? extends ActivitySample> provider = getProvider(db, device);
LOG.debug("sample provider: " + provider);
return provider.getFirstActivitySample();
}
}

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#7E7E7E"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M19,5h-2V3H7v2H5C3.9,5 3,5.9 3,7v1c0,2.55 1.92,4.63 4.39,4.94c0.63,1.5 1.98,2.63 3.61,2.96V19H7v2h10v-2h-4v-3.1c1.63,-0.33 2.98,-1.46 3.61,-2.96C19.08,12.63 21,10.55 21,8V7C21,5.9 20.1,5 19,5zM5,8V7h2v3.82C5.84,10.4 5,9.3 5,8zM12,14c-1.65,0 -3,-1.35 -3,-3V5h6v6C15,12.65 13.65,14 12,14zM19,8c0,1.3 -0.84,2.4 -2,2.82V7h2V8z" />
</vector>

File diff suppressed because one or more lines are too long

View File

@ -1,37 +1,62 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity$PlaceholderFragment"
android:orientation="horizontal">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="40"
android:orientation="vertical">
<TextView
android:id="@+id/balance"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:orientation="horizontal"
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity$PlaceholderFragment">
<com.github.mikephil.charting.charts.PieChart
android:id="@+id/todaystepschart"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="40"
android:orientation="vertical">
<TextView
android:id="@+id/balance"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.github.mikephil.charting.charts.PieChart
android:id="@+id/todaystepschart"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="40" />
</LinearLayout>
<com.github.mikephil.charting.charts.BarChart
android:id="@+id/weekstepschart"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="40" />
android:layout_weight="20" />
</LinearLayout>
<com.github.mikephil.charting.charts.BarChart
android:id="@+id/weekstepschart"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="20" />
<!--<TextView-->
<!--<TextView-->
<!--android:text="Test"-->
<!--android:layout_width="fill_parent"-->
<!--android:layout_height="fill_parent"-->
<!--android:layout_weight="20" />-->
</LinearLayout>
</LinearLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_steps_streaks"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom|end"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="0dp"
android:layout_weight="0"
android:visibility="gone"
app:srcCompat="@drawable/ic_events_gold" />
</RelativeLayout>

View File

@ -1,25 +1,47 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity$PlaceholderFragment"
android:orientation="vertical">
android:layout_height="match_parent">
<TextView
android:id="@+id/balance"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity$PlaceholderFragment">
<TextView
android:id="@+id/balance"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.github.mikephil.charting.charts.PieChart
android:id="@+id/todaystepschart"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="20" />
<com.github.mikephil.charting.charts.BarChart
android:id="@+id/weekstepschart"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="20" />
</LinearLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_steps_streaks"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom|end"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="0dp"
android:visibility="gone"
app:srcCompat="@drawable/ic_events_gold" />
<com.github.mikephil.charting.charts.PieChart
android:id="@+id/todaystepschart"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="20" />
</RelativeLayout>
<com.github.mikephil.charting.charts.BarChart
android:id="@+id/weekstepschart"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="20" />
</LinearLayout>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center|top"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="Average\n steps"
android:textAllCaps="true"
android:textColor="@color/accent"
android:textStyle="bold" />
<TextView
android:id="@+id/step_streak_average_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="15000"
android:textSize="24sp" />
</LinearLayout>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/step_streak_current_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="20dp"
android:orientation="vertical"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="Ongoing"
android:textAllCaps="true"
android:textSize="24sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:gravity="bottom|center"
android:orientation="horizontal">
<include layout="@layout/steps_streak_days" />
<include layout="@layout/steps_streak_average" />
<include layout="@layout/steps_streak_total" />
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/step_streak_days_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center|top"
android:orientation="vertical">
<TextView
android:id="@+id/step_streak_days_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="Days\n"
android:textAllCaps="true"
android:textColor="@color/accent"
android:textStyle="bold" />
<TextView
android:id="@+id/step_streak_days_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="9150000"
android:textSize="24sp" />
</LinearLayout>

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/step_streak_maximum_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="20dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="Longest"
android:textAllCaps="true"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:id="@+id/step_streak_maximum_date_value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="date"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:gravity="bottom|center"
android:orientation="horizontal">
<include layout="@layout/steps_streak_days" />
<include layout="@layout/steps_streak_average" />
<include layout="@layout/steps_streak_total" />
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center|top"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="Total\n steps"
android:textAllCaps="true"
android:textColor="@color/accent"
android:textStyle="bold" />
<TextView
android:id="@+id/step_streak_total_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="9150000"
android:textSize="24sp" />
</LinearLayout>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/step_streak_total_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="0dp"
android:orientation="vertical"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="Total"
android:textAllCaps="true"
android:textSize="24sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:gravity="bottom|center"
android:orientation="horizontal">
<include layout="@layout/steps_streak_days" />
<include layout="@layout/steps_streak_total" />
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/about_background"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:gravity="center|center_vertical"
android:minWidth="1000dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="Steps streaks"
android:textAllCaps="true"
android:textSize="24sp"
android:textStyle="bold" />
<include layout="@layout/steps_streak_current_line_layout"
android:visibility="gone"/>
<include layout="@layout/steps_streak_maximum_line_layout" android:visibility="gone" />
<include layout="@layout/steps_streak_total_line_layout" android:visibility="gone" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="0dp"
android:layout_marginBottom="5dp"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="35dp"
android:layout_marginTop="39dp"
app:srcCompat="@drawable/ic_events_gold" />
<ProgressBar
android:id="@+id/step_streak_dashboard_loading_circle"
android:layout_width="171dp"
android:layout_height="171dp"
android:indeterminate="true" />
</RelativeLayout>
</LinearLayout>
</ScrollView>

View File

@ -1730,4 +1730,5 @@
<string name="connection_over_bt_classic">Connection over Bluetooth classic</string>
<string name="autoconnect_from_device_title">Connect on connection from device</string>
<string name="autoconnect_from_device_summary">Establish a connection when connection is initiated by device, like headphones</string>
<string name="stepsStreakCalculating">Calculating steps data</string>
</resources>