1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-12-27 02:55:50 +01:00

Dashboard: Add option to show yesterday's data in Today widget

This commit is contained in:
Arjan Schrijver 2024-09-25 22:10:31 +02:00 committed by Arjan Schrijver
parent 7d15859737
commit 52798393a4
4 changed files with 110 additions and 11 deletions

View File

@ -69,6 +69,9 @@ public class DashboardPreferencesActivity extends AbstractSettingsActivityV2 {
"dashboard_cards_enabled", "dashboard_cards_enabled",
"pref_dashboard_widgets_order", "pref_dashboard_widgets_order",
"dashboard_widget_today_24h", "dashboard_widget_today_24h",
"dashboard_widget_today_24h_upside_down",
"dashboard_widget_today_show_yesterday",
"dashboard_widget_today_time_indicator",
"dashboard_widget_today_2columns", "dashboard_widget_today_2columns",
"dashboard_widget_today_legend", "dashboard_widget_today_legend",
"dashboard_widget_today_hr_interval", "dashboard_widget_today_hr_interval",

View File

@ -58,6 +58,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySession; import nodomain.freeyourgadget.gadgetbridge.model.ActivitySession;
import nodomain.freeyourgadget.gadgetbridge.util.DashboardUtils; import nodomain.freeyourgadget.gadgetbridge.util.DashboardUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs; import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
/** /**
@ -139,9 +140,11 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
private void draw() { private void draw() {
Prefs prefs = GBApplication.getPrefs(); Prefs prefs = GBApplication.getPrefs();
boolean upsideDown24h = prefs.getBoolean("dashboard_widget_today_24h_upside_down", false); boolean upsideDown24h = prefs.getBoolean("dashboard_widget_today_24h_upside_down", false);
boolean showYesterday = prefs.getBoolean("dashboard_widget_today_show_yesterday", false);
// Prepare circular chart // Prepare circular chart
long midDaySecond = dashboardData.timeFrom + (12 * 60 * 60); long currentDayStart = dashboardData.timeTo - 86400;
long midDaySecond = currentDayStart + (12 * 60 * 60);
int width = Resources.getSystem().getDisplayMetrics().widthPixels; int width = Resources.getSystem().getDisplayMetrics().widthPixels;
int height = width; int height = width;
int barWidth = Math.round(width * 0.08f); int barWidth = Math.round(width * 0.08f);
@ -231,11 +234,24 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
// Draw generalized activities on circular chart // Draw generalized activities on circular chart
long secondIndex = dashboardData.timeFrom; long secondIndex = dashboardData.timeFrom;
long currentTime = Calendar.getInstance().getTimeInMillis() / 1000; long currentTime = Calendar.getInstance().getTimeInMillis() / 1000;
boolean dayIsToday = !(dashboardData.timeTo < currentTime);
int startAngle = mode_24h && upsideDown24h ? 90 : 270; int startAngle = mode_24h && upsideDown24h ? 90 : 270;
synchronized (dashboardData.generalizedActivities) { synchronized (dashboardData.generalizedActivities) {
for (DashboardFragment.DashboardData.GeneralizedActivity activity : dashboardData.generalizedActivities) { for (DashboardFragment.DashboardData.GeneralizedActivity activity : dashboardData.generalizedActivities) {
// Determine margin depending on 24h/12h mode // Determine margin
float margin = (mode_24h || activity.timeFrom >= midDaySecond) ? outerCircleMargin : innerCircleMargin; float margin = innerCircleMargin;
if (mode_24h || activity.timeFrom >= midDaySecond) {
margin = outerCircleMargin;
}
if (!mode_24h && showYesterday && dayIsToday) {
if (activity.timeFrom < currentDayStart && activity.timeFrom > midDaySecond - 86400) {
margin = outerCircleMargin;
}
}
// Skip activities from before 24h ago (to prevent double drawing the same position)
if (showYesterday && dayIsToday && (activity.timeTo < currentTime - 86400)) {
continue;
}
// Draw inactive slices // Draw inactive slices
if (!mode_24h && secondIndex < midDaySecond && activity.timeFrom >= midDaySecond) { if (!mode_24h && secondIndex < midDaySecond && activity.timeFrom >= midDaySecond) {
paint.setStrokeWidth(barWidth / 3f); paint.setStrokeWidth(barWidth / 3f);
@ -253,39 +269,70 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
if (activity.activityKind == ActivityKind.NOT_MEASURED) { if (activity.activityKind == ActivityKind.NOT_MEASURED) {
paint.setStrokeWidth(barWidth / 3f); paint.setStrokeWidth(barWidth / 3f);
paint.setColor(color_worn); paint.setColor(color_worn);
if (showYesterday && dayIsToday && activity.timeFrom < currentDayStart) {
paint.setAlpha(64);
}
canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint); canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint);
} else if (activity.activityKind == ActivityKind.NOT_WORN) { } else if (activity.activityKind == ActivityKind.NOT_WORN) {
paint.setStrokeWidth(barWidth / 3f); paint.setStrokeWidth(barWidth / 3f);
paint.setColor(color_not_worn); paint.setColor(color_not_worn);
if (showYesterday && dayIsToday && activity.timeFrom < currentDayStart) {
paint.setAlpha(64);
}
canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint); canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint);
} else if (activity.activityKind == ActivityKind.LIGHT_SLEEP || activity.activityKind == ActivityKind.SLEEP_ANY) { } else if (activity.activityKind == ActivityKind.LIGHT_SLEEP || activity.activityKind == ActivityKind.SLEEP_ANY) {
paint.setStrokeWidth(barWidth); paint.setStrokeWidth(barWidth);
paint.setColor(color_light_sleep); paint.setColor(color_light_sleep);
if (showYesterday && dayIsToday && activity.timeFrom < currentDayStart) {
paint.setAlpha(64);
}
canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint); canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint);
} else if (activity.activityKind == ActivityKind.REM_SLEEP) { } else if (activity.activityKind == ActivityKind.REM_SLEEP) {
paint.setStrokeWidth(barWidth); paint.setStrokeWidth(barWidth);
paint.setColor(color_rem_sleep); paint.setColor(color_rem_sleep);
if (showYesterday && dayIsToday && activity.timeFrom < currentDayStart) {
paint.setAlpha(64);
}
canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint); canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint);
} else if (activity.activityKind == ActivityKind.DEEP_SLEEP) { } else if (activity.activityKind == ActivityKind.DEEP_SLEEP) {
paint.setStrokeWidth(barWidth); paint.setStrokeWidth(barWidth);
paint.setColor(color_deep_sleep); paint.setColor(color_deep_sleep);
if (showYesterday && dayIsToday && activity.timeFrom < currentDayStart) {
paint.setAlpha(64);
}
canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint); canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint);
} else if (activity.activityKind == ActivityKind.AWAKE_SLEEP) { } else if (activity.activityKind == ActivityKind.AWAKE_SLEEP) {
paint.setStrokeWidth(barWidth); paint.setStrokeWidth(barWidth);
paint.setColor(color_awake_sleep); paint.setColor(color_awake_sleep);
if (showYesterday && dayIsToday && activity.timeFrom < currentDayStart) {
paint.setAlpha(64);
}
canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint); canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint);
} else if (activity.activityKind == ActivityKind.EXERCISE) { } else if (activity.activityKind == ActivityKind.EXERCISE) {
paint.setStrokeWidth(barWidth); paint.setStrokeWidth(barWidth);
paint.setColor(color_exercise); paint.setColor(color_exercise);
if (showYesterday && dayIsToday && activity.timeFrom < currentDayStart) {
paint.setAlpha(64);
}
canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint); canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint);
} else { } else {
paint.setStrokeWidth(barWidth); paint.setStrokeWidth(barWidth);
paint.setColor(color_activity); paint.setColor(color_activity);
if (showYesterday && dayIsToday && activity.timeFrom < currentDayStart) {
paint.setAlpha(64);
}
canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint); canvas.drawArc(margin, margin, width - margin, height - margin, start_angle, sweep_angle, false, paint);
} }
secondIndex = activity.timeTo; secondIndex = activity.timeTo;
} }
} }
// Draw indicator for current time
if (prefs.getBoolean("dashboard_widget_today_time_indicator", false) && currentTime < dashboardData.timeTo) {
float margin = (mode_24h || currentTime >= midDaySecond) ? outerCircleMargin : innerCircleMargin;
paint.setStrokeWidth(barWidth);
paint.setColor(GBApplication.getTextColor(requireContext()));
canvas.drawArc(margin, margin, width - margin, height - margin, startAngle + (currentTime - dashboardData.timeFrom) / degreeFactor, 300 / degreeFactor, false, paint);
}
// Fill remaining time until current time in 12h mode before midday // Fill remaining time until current time in 12h mode before midday
if (!mode_24h && currentTime < midDaySecond) { if (!mode_24h && currentTime < midDaySecond) {
// Fill inner bar up until current time // Fill inner bar up until current time
@ -332,6 +379,17 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
protected void fillData() { protected void fillData() {
if (todayView == null) return; if (todayView == null) return;
Prefs prefs = GBApplication.getPrefs();
if (prefs.getBoolean("dashboard_widget_today_show_yesterday", false)) {
Calendar today = Calendar.getInstance();
Calendar dashboardDate = Calendar.getInstance();
dashboardDate.setTimeInMillis((dashboardData.timeFrom + 1) * 1000L);
if (DateTimeUtils.isSameDay(today, dashboardDate)) {
dashboardData.timeFrom -= 86400;
}
}
todayView.post(new Runnable() { todayView.post(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -344,6 +402,9 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
private class FillDataAsyncTask extends AsyncTask<Void, Void, Void> { private class FillDataAsyncTask extends AsyncTask<Void, Void, Void> {
private final TreeMap<Long, ActivityKind> activityTimestamps = new TreeMap<>(); private final TreeMap<Long, ActivityKind> activityTimestamps = new TreeMap<>();
/**
* Add per-second activities to `activityTimestamps`
*/
private void addActivity(long timeFrom, long timeTo, ActivityKind activityKind) { private void addActivity(long timeFrom, long timeTo, ActivityKind activityKind) {
for (long i = timeFrom; i <= timeTo; i++) { for (long i = timeFrom; i <= timeTo; i++) {
// If the current timestamp isn't saved yet, do so immediately // If the current timestamp isn't saved yet, do so immediately
@ -403,6 +464,9 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
} }
} }
/**
* Add NOT_MEASURED (worn) activities for every successful heart rate measurement
*/
private void calculateWornSessions(List<ActivitySample> samples) { private void calculateWornSessions(List<ActivitySample> samples) {
int firstTimestamp = 0; int firstTimestamp = 0;
int lastTimestamp = 0; int lastTimestamp = 0;
@ -435,13 +499,25 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
} }
} }
/**
* Merge per-second activities from `activityTimestamps` into generalized activity ranges
* with minute-based resolution
*/
private void createGeneralizedActivities() { private void createGeneralizedActivities() {
long currentTime = Calendar.getInstance().getTimeInMillis() / 1000;
long midDaySecond = dashboardData.timeTo - (12 * 60 * 60);
DashboardFragment.DashboardData.GeneralizedActivity previous = null; DashboardFragment.DashboardData.GeneralizedActivity previous = null;
long midDaySecond = dashboardData.timeFrom + (12 * 60 * 60);
for (Map.Entry<Long, ActivityKind> activity : activityTimestamps.entrySet()) { for (Map.Entry<Long, ActivityKind> activity : activityTimestamps.entrySet()) {
long timestamp = activity.getKey(); long timestamp = activity.getKey();
ActivityKind activityKind = activity.getValue(); ActivityKind activityKind = activity.getValue();
if (previous == null || previous.activityKind != activityKind || (!mode_24h && timestamp == midDaySecond) || previous.timeTo < timestamp - 60) { // Start a new merged activity on certain conditions
if (previous == null ||
previous.activityKind != activityKind ||
(!mode_24h && timestamp == midDaySecond) ||
(!mode_24h && timestamp == midDaySecond - 86400) ||
timestamp == dashboardData.timeTo - 86400 ||
timestamp == currentTime - 86400 ||
previous.timeTo < timestamp - 60) {
previous = new DashboardFragment.DashboardData.GeneralizedActivity(activityKind, timestamp, timestamp); previous = new DashboardFragment.DashboardData.GeneralizedActivity(activityKind, timestamp, timestamp);
dashboardData.generalizedActivities.add(previous); dashboardData.generalizedActivities.add(previous);
} else { } else {
@ -494,6 +570,8 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
for (ActivitySession session : stepSessions) { for (ActivitySession session : stepSessions) {
addActivity(session.getStartTime().getTime() / 1000, session.getEndTime().getTime() / 1000, ActivityKind.ACTIVITY); addActivity(session.getStartTime().getTime() / 1000, session.getEndTime().getTime() / 1000, ActivityKind.ACTIVITY);
} }
// Merge per-second activities
createGeneralizedActivities(); createGeneralizedActivities();
final long nanoEnd = System.nanoTime(); final long nanoEnd = System.nanoTime();

View File

@ -3326,4 +3326,8 @@
<string name="error_no_cycling_sensor_found">no cycling sensor found</string> <string name="error_no_cycling_sensor_found">no cycling sensor found</string>
<string name="contact_birthday">%1s\'s birthday</string> <string name="contact_birthday">%1s\'s birthday</string>
<string name="birthdays">Birthdays</string> <string name="birthdays">Birthdays</string>
<string name="pref_dashboard_widget_today_yesterday_data_title">Data from yesterday</string>
<string name="pref_dashboard_widget_today_yesterday_data_summary">Show data from yesterday dimmed between the current time and midnight</string>
<string name="pref_dashboard_widget_today_time_indicator_title">Current time indicator</string>
<string name="pref_dashboard_widget_today_time_indicator_summary">Show an indicator at the current time, to visually separate data from yesterday and today</string>
</resources> </resources>

View File

@ -54,6 +54,20 @@
android:title="@string/pref_dashboard_widget_today_upside_down_title" android:title="@string/pref_dashboard_widget_today_upside_down_title"
android:summary="@string/pref_dashboard_widget_today_upside_down_summary" android:summary="@string/pref_dashboard_widget_today_upside_down_summary"
app:iconSpaceReserved="false" /> app:iconSpaceReserved="false" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="dashboard_widget_today_show_yesterday"
android:layout="@layout/preference_checkbox"
android:title="@string/pref_dashboard_widget_today_yesterday_data_title"
android:summary="@string/pref_dashboard_widget_today_yesterday_data_summary"
app:iconSpaceReserved="false" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="dashboard_widget_today_time_indicator"
android:layout="@layout/preference_checkbox"
android:title="@string/pref_dashboard_widget_today_time_indicator_title"
android:summary="@string/pref_dashboard_widget_today_time_indicator_summary"
app:iconSpaceReserved="false" />
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:defaultValue="true" android:defaultValue="true"
android:key="dashboard_widget_today_2columns" android:key="dashboard_widget_today_2columns"