1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-09-27 16:56:57 +02:00

Add device selection preference

This commit is contained in:
Arjan Schrijver 2024-02-06 16:10:00 +01:00
parent 52a8451486
commit 50c511f366
6 changed files with 90 additions and 44 deletions

View File

@ -38,6 +38,8 @@ import com.google.android.material.card.MaterialCardView;
import java.io.Serializable;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
@ -50,7 +52,7 @@ import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardSleepW
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardStepsWidget;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardTodayWidget;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.HealthUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DashboardUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class DashboardFragment extends Fragment {
@ -148,6 +150,9 @@ public class DashboardFragment extends Fragment {
day.set(Calendar.MINUTE, 59);
day.set(Calendar.SECOND, 59);
dashboardData.clear();
Prefs prefs = GBApplication.getPrefs();
dashboardData.showAllDevices = prefs.getBoolean("dashboard_devices_all", true);
dashboardData.showDeviceList = prefs.getStringSet("dashboard_devices_multiselect", new HashSet<>());
dashboardData.timeTo = (int) (day.getTimeInMillis() / 1000);
dashboardData.timeFrom = DateTimeUtils.shiftDays(dashboardData.timeTo, -1);
@ -160,7 +165,6 @@ public class DashboardFragment extends Fragment {
arrowRight.setAlpha(1);
}
Prefs prefs = GBApplication.getPrefs();
boolean cardsEnabled = prefs.getBoolean("dashboard_cards_enabled", true);
if (prefs.getBoolean("dashboard_widget_today_enabled", true)) {
@ -253,6 +257,8 @@ public class DashboardFragment extends Fragment {
* data available.
*/
public static class DashboardData implements Serializable {
public boolean showAllDevices;
public Set<String> showDeviceList;
public int timeFrom;
public int timeTo;
private int stepsTotal;
@ -277,49 +283,49 @@ public class DashboardFragment extends Fragment {
public synchronized int getStepsTotal() {
if (stepsTotal == 0)
stepsTotal = HealthUtils.getStepsTotal(timeTo);
stepsTotal = DashboardUtils.getStepsTotal(this);
return stepsTotal;
}
public synchronized float getStepsGoalFactor() {
if (stepsGoalFactor == 0)
stepsGoalFactor = HealthUtils.getStepsGoalFactor(timeTo);
stepsGoalFactor = DashboardUtils.getStepsGoalFactor(this);
return stepsGoalFactor;
}
public synchronized float getDistanceTotal() {
if (distanceTotalMeters == 0)
distanceTotalMeters = HealthUtils.getDistanceTotal(timeTo);
distanceTotalMeters = DashboardUtils.getDistanceTotal(this);
return distanceTotalMeters;
}
public synchronized float getDistanceGoalFactor() {
if (distanceGoalFactor == 0)
distanceGoalFactor = HealthUtils.getDistanceGoalFactor(timeTo);
distanceGoalFactor = DashboardUtils.getDistanceGoalFactor(this);
return distanceGoalFactor;
}
public synchronized long getActiveMinutesTotal() {
if (activeMinutesTotal == 0)
activeMinutesTotal = HealthUtils.getActiveMinutesTotal(timeFrom, timeTo);
activeMinutesTotal = DashboardUtils.getActiveMinutesTotal(this);
return activeMinutesTotal;
}
public synchronized float getActiveMinutesGoalFactor() {
if (activeMinutesGoalFactor == 0)
activeMinutesGoalFactor = HealthUtils.getActiveMinutesGoalFactor(timeFrom, timeTo);
activeMinutesGoalFactor = DashboardUtils.getActiveMinutesGoalFactor(this);
return activeMinutesGoalFactor;
}
public synchronized long getSleepMinutesTotal() {
if (sleepTotalMinutes == 0)
sleepTotalMinutes = HealthUtils.getSleepMinutesTotal(timeTo);
sleepTotalMinutes = DashboardUtils.getSleepMinutesTotal(this);
return sleepTotalMinutes;
}
public synchronized float getSleepMinutesGoalFactor() {
if (sleepGoalFactor == 0)
sleepGoalFactor = HealthUtils.getSleepMinutesGoalFactor(timeTo);
sleepGoalFactor = DashboardUtils.getSleepMinutesGoalFactor(this);
return sleepGoalFactor;
}
}

View File

@ -45,6 +45,7 @@ import android.widget.Toast;
import androidx.core.app.ActivityCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.ListPreference;
import androidx.preference.MultiSelectListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
@ -55,6 +56,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
@ -72,6 +74,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleSettingsActivit
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.ConfigActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.zetime.ZeTimePreferenceActivity;
import nodomain.freeyourgadget.gadgetbridge.externalevents.TimeChangeReceiver;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Weather;
import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
@ -397,6 +400,19 @@ public class SettingsActivity extends AbstractSettingsActivityV2 {
audioPlayer.setDefaultValue(newValues[0]);
}
final MultiSelectListPreference dashboardDevices = findPreference("dashboard_devices_multiselect");
if (dashboardDevices != null) {
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
List<String> deviceMACs = new ArrayList<>();
List<String> deviceNames = new ArrayList<>();
for (GBDevice dev : devices) {
deviceMACs.add(dev.getAddress());
deviceNames.add(dev.getAliasOrName());
}
dashboardDevices.setEntryValues(deviceMACs.toArray(new String[0]));
dashboardDevices.setEntries(deviceNames.toArray(new String[0]));
}
final Preference theme = findPreference("pref_key_theme");
final Preference amoled_black = findPreference("pref_key_theme_amoled_black");

View File

@ -34,14 +34,19 @@ import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.util.DashboardUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.HealthUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class DashboardCalendarActivity extends AbstractGBActivity {
private static final Logger LOG = LoggerFactory.getLogger(DashboardCalendarActivity.class);
@ -49,6 +54,9 @@ public class DashboardCalendarActivity extends AbstractGBActivity {
private final ConcurrentHashMap<Calendar, TextView> dayCells = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Integer, Integer> dayColors = new ConcurrentHashMap<>();
private boolean showAllDevices;
private Set<String> showDeviceList;
TextView monthTextView;
TextView arrowLeft;
TextView arrowRight;
@ -65,6 +73,10 @@ public class DashboardCalendarActivity extends AbstractGBActivity {
long receivedTimestamp = getIntent().getLongExtra(EXTRA_TIMESTAMP, 0);
if (receivedTimestamp != 0) cal.setTimeInMillis(receivedTimestamp);
Prefs prefs = GBApplication.getPrefs();
showAllDevices = prefs.getBoolean("dashboard_devices_all", true);
showDeviceList = prefs.getStringSet("dashboard_devices_multiselect", new HashSet<>());
arrowLeft = findViewById(R.id.arrow_left);
arrowLeft.setOnClickListener(v -> {
cal.add(Calendar.MONTH, -1);
@ -179,9 +191,12 @@ public class DashboardCalendarActivity extends AbstractGBActivity {
protected Void doInBackground(Void... params) {
for (Calendar day : dayCells.keySet()) {
// Determine day color by the amount of the steps goal reached
int timeTo = (int) (day.getTimeInMillis() / 1000);
int timeFrom = DateTimeUtils.shiftDays(timeTo, -1);
float goalFactor = HealthUtils.getStepsGoalFactor(timeTo);
DashboardFragment.DashboardData dashboardData = new DashboardFragment.DashboardData();
dashboardData.showAllDevices = showAllDevices;
dashboardData.showDeviceList = showDeviceList;
dashboardData.timeTo = (int) (day.getTimeInMillis() / 1000);
dashboardData.timeFrom = DateTimeUtils.shiftDays(dashboardData.timeTo, -1);
float goalFactor = DashboardUtils.getStepsGoalFactor(dashboardData);
@ColorInt int dayColor;
if (goalFactor >= 1) {
dayColor = Color.argb(128, 0, 255, 0); // Green

View File

@ -53,7 +53,7 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySession;
import nodomain.freeyourgadget.gadgetbridge.util.HealthUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DashboardUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
/**
@ -277,8 +277,8 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
List<ActivitySession> stepSessions = new ArrayList<>();
try (DBHandler dbHandler = GBApplication.acquireDB()) {
for (GBDevice dev : devices) {
if (dev.getDeviceCoordinator().supportsActivityTracking()) {
List<? extends ActivitySample> activitySamples = HealthUtils.getAllSamples(dbHandler, dev, dashboardData.timeFrom, dashboardData.timeTo);
if ((dashboardData.showAllDevices || dashboardData.showDeviceList.contains(dev.getAddress())) && dev.getDeviceCoordinator().supportsActivityTracking()) {
List<? extends ActivitySample> activitySamples = DashboardUtils.getAllSamples(dbHandler, dev, dashboardData);
allActivitySamples.addAll(activitySamples);
StepAnalysis stepAnalysis = new StepAnalysis();
stepSessions.addAll(stepAnalysis.calculateStepSessions(activitySamples));

View File

@ -24,6 +24,7 @@ import java.util.GregorianCalendar;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.StepAnalysis;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
@ -35,8 +36,8 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivitySession;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.model.DailyTotals;
public class HealthUtils {
private static final Logger LOG = LoggerFactory.getLogger(HealthUtils.class);
public class DashboardUtils {
private static final Logger LOG = LoggerFactory.getLogger(DashboardUtils.class);
public static long getSteps(GBDevice device, DBHandler db, int timeTo) {
Calendar day = GregorianCalendar.getInstance();
@ -45,13 +46,13 @@ public class HealthUtils {
return ds.getDailyTotalsForDevice(device, day, db)[0];
}
public static int getStepsTotal(int timeTo) {
public static int getStepsTotal(DashboardFragment.DashboardData dashboardData) {
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
int totalSteps = 0;
try (DBHandler dbHandler = GBApplication.acquireDB()) {
for (GBDevice dev : devices) {
if (dev.getDeviceCoordinator().supportsActivityTracking()) {
totalSteps += getSteps(dev, dbHandler, timeTo);
if ((dashboardData.showAllDevices || dashboardData.showDeviceList.contains(dev.getAddress())) && dev.getDeviceCoordinator().supportsActivityTracking()) {
totalSteps += getSteps(dev, dbHandler, dashboardData.timeTo);
}
}
} catch (Exception e) {
@ -60,10 +61,10 @@ public class HealthUtils {
return totalSteps;
}
public static float getStepsGoalFactor(int timeTo) {
public static float getStepsGoalFactor(DashboardFragment.DashboardData dashboardData) {
ActivityUser activityUser = new ActivityUser();
float stepsGoal = activityUser.getStepsGoal();
float goalFactor = getStepsTotal(timeTo) / stepsGoal;
float goalFactor = getStepsTotal(dashboardData) / stepsGoal;
if (goalFactor > 1) goalFactor = 1;
return goalFactor;
@ -76,13 +77,13 @@ public class HealthUtils {
return ds.getDailyTotalsForDevice(device, day, db)[1];
}
public static long getSleepMinutesTotal(int timeTo) {
public static long getSleepMinutesTotal(DashboardFragment.DashboardData dashboardData) {
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
long totalSleepMinutes = 0;
try (DBHandler dbHandler = GBApplication.acquireDB()) {
for (GBDevice dev : devices) {
if (dev.getDeviceCoordinator().supportsActivityTracking()) {
totalSleepMinutes += getSleep(dev, dbHandler, timeTo);
if ((dashboardData.showAllDevices || dashboardData.showDeviceList.contains(dev.getAddress())) && dev.getDeviceCoordinator().supportsActivityTracking()) {
totalSleepMinutes += getSleep(dev, dbHandler, dashboardData.timeTo);
}
}
} catch (Exception e) {
@ -91,22 +92,22 @@ public class HealthUtils {
return totalSleepMinutes;
}
public static float getSleepMinutesGoalFactor(int timeTo) {
public static float getSleepMinutesGoalFactor(DashboardFragment.DashboardData dashboardData) {
ActivityUser activityUser = new ActivityUser();
int sleepMinutesGoal = activityUser.getSleepDurationGoal() * 60;
float goalFactor = (float) getSleepMinutesTotal(timeTo) / sleepMinutesGoal;
float goalFactor = (float) getSleepMinutesTotal(dashboardData) / sleepMinutesGoal;
if (goalFactor > 1) goalFactor = 1;
return goalFactor;
}
public static float getDistanceTotal(int timeTo) {
public static float getDistanceTotal(DashboardFragment.DashboardData dashboardData) {
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
long totalSteps = 0;
try (DBHandler dbHandler = GBApplication.acquireDB()) {
for (GBDevice dev : devices) {
if (dev.getDeviceCoordinator().supportsActivityTracking()) {
totalSteps += getSteps(dev, dbHandler, timeTo);
if ((dashboardData.showAllDevices || dashboardData.showDeviceList.contains(dev.getAddress())) && dev.getDeviceCoordinator().supportsActivityTracking()) {
totalSteps += getSteps(dev, dbHandler, dashboardData.timeTo);
}
}
} catch (Exception e) {
@ -117,22 +118,22 @@ public class HealthUtils {
return totalSteps * stepLength * 0.01f;
}
public static float getDistanceGoalFactor(int timeTo) {
public static float getDistanceGoalFactor(DashboardFragment.DashboardData dashboardData) {
ActivityUser activityUser = new ActivityUser();
int distanceGoal = activityUser.getDistanceGoalMeters();
float goalFactor = getDistanceTotal(timeTo) / distanceGoal;
float goalFactor = getDistanceTotal(dashboardData) / distanceGoal;
if (goalFactor > 1) goalFactor = 1;
return goalFactor;
}
public static long getActiveMinutesTotal(int timeFrom, int timeTo) {
public static long getActiveMinutesTotal(DashboardFragment.DashboardData dashboardData) {
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
long totalActiveMinutes = 0;
try (DBHandler dbHandler = GBApplication.acquireDB()) {
for (GBDevice dev : devices) {
if (dev.getDeviceCoordinator().supportsActivityTracking()) {
totalActiveMinutes += getActiveMinutes(dev, dbHandler, timeFrom, timeTo);
if ((dashboardData.showAllDevices || dashboardData.showDeviceList.contains(dev.getAddress())) && dev.getDeviceCoordinator().supportsActivityTracking()) {
totalActiveMinutes += getActiveMinutes(dev, dbHandler, dashboardData);
}
}
} catch (Exception e) {
@ -141,19 +142,19 @@ public class HealthUtils {
return totalActiveMinutes;
}
public static float getActiveMinutesGoalFactor(int timeFrom, int timeTo) {
public static float getActiveMinutesGoalFactor(DashboardFragment.DashboardData dashboardData) {
ActivityUser activityUser = new ActivityUser();
int activeTimeGoal = activityUser.getActiveTimeGoalMinutes();
float goalFactor = (float) getActiveMinutesTotal(timeFrom, timeTo) / activeTimeGoal;
float goalFactor = (float) getActiveMinutesTotal(dashboardData) / activeTimeGoal;
if (goalFactor > 1) goalFactor = 1;
return goalFactor;
}
public static long getActiveMinutes(GBDevice gbDevice, DBHandler db, int timeFrom, int timeTo) {
public static long getActiveMinutes(GBDevice gbDevice, DBHandler db, DashboardFragment.DashboardData dashboardData) {
ActivitySession stepSessionsSummary = new ActivitySession();
List<ActivitySession> stepSessions;
List<? extends ActivitySample> activitySamples = getAllSamples(db, gbDevice, timeFrom, timeTo);
List<? extends ActivitySample> activitySamples = getAllSamples(db, gbDevice, dashboardData);
StepAnalysis stepAnalysis = new StepAnalysis();
boolean isEmptySummary = false;
@ -168,9 +169,9 @@ public class HealthUtils {
return duration / 1000 / 60;
}
public static List<? extends ActivitySample> getAllSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
public static List<? extends ActivitySample> getAllSamples(DBHandler db, GBDevice device, DashboardFragment.DashboardData dashboardData) {
SampleProvider<? extends ActivitySample> provider = getProvider(db, device);
return provider.getAllActivitySamples(tsFrom, tsTo);
return provider.getAllActivitySamples(dashboardData.timeFrom, dashboardData.timeTo);
}
protected static SampleProvider<? extends AbstractActivitySample> getProvider(DBHandler db, GBDevice device) {

View File

@ -145,7 +145,15 @@
android:key="dashboard_devices_all"
android:layout="@layout/preference_checkbox"
android:title="All devices"
android:enabled="false"
android:disableDependentsState="true"
app:iconSpaceReserved="false" />
<MultiSelectListPreference
android:dependency="dashboard_devices_all"
android:dialogTitle="Select devices"
android:entries="@array/empty_array"
android:entryValues="@array/empty_array"
android:key="dashboard_devices_multiselect"
android:title="Select devices..."
app:iconSpaceReserved="false" />
</PreferenceCategory>
</PreferenceScreen>