change daily sleep goal from hours to minutes (#1312)

This commit is contained in:
Thomas Kuehne
2025-08-31 10:27:24 +02:00
parent 55924e3d99
commit eba83f93ad
17 changed files with 77 additions and 39 deletions
@@ -58,7 +58,7 @@ public class GBDaoGenerator {
public static void main(String[] args) throws Exception {
final Schema schema = new Schema(114, MAIN_PACKAGE + ".entities");
final Schema schema = new Schema(115, MAIN_PACKAGE + ".entities");
Entity userAttributes = addUserAttributes(schema);
Entity user = addUserInfo(schema, userAttributes);
@@ -279,9 +279,10 @@ public class GBDaoGenerator {
userAttributes.addIdProperty();
userAttributes.addIntProperty("heightCM").notNull();
userAttributes.addIntProperty("weightKG").notNull();
userAttributes.addIntProperty("sleepGoalHPD").javaDocGetterAndSetter("Desired number of hours of sleep per day.");
userAttributes.addIntProperty("sleepGoalHPD").javaDocGetterAndSetter("@deprecated").codeBeforeGetterAndSetter("@Deprecated");
userAttributes.addIntProperty("stepsGoalSPD").javaDocGetterAndSetter("Desired number of steps per day.");
addDateValidityTo(userAttributes);
userAttributes.addIntProperty("sleepGoalMPD").javaDocGetterAndSetter("Desired number of minutes of sleep per day.");
return userAttributes;
}
@@ -142,7 +142,7 @@ public class GBApplication extends Application {
private static SharedPreferences sharedPrefs;
private static final String PREFS_VERSION = "shared_preferences_version";
//if preferences have to be migrated, increment the following and add the migration logic in migratePrefs below; see http://stackoverflow.com/questions/16397848/how-can-i-migrate-android-preferences-with-a-new-version
private static final int CURRENT_PREFS_VERSION = 50;
private static final int CURRENT_PREFS_VERSION = 51;
private static final LimitedQueue<Integer, String> mIDSenderLookup = new LimitedQueue<>(16);
private static GBPrefs prefs;
@@ -2136,6 +2136,15 @@ public class GBApplication extends Application {
}
}
if (oldVersion < 51) {
if (prefs.contains("activity_user_sleep_duration")) {
int hours = prefs.getInt("activity_user_sleep_duration", -1);
if (hours > -1){
editor.putInt("activity_user_sleep_duration_minutes", hours * 60);
}
}
}
editor.putString(PREFS_VERSION, Integer.toString(CURRENT_PREFS_VERSION));
editor.apply();
}
@@ -108,7 +108,7 @@ public class SleepAlarmWidget extends AppWidgetProvider {
GregorianCalendar calendar = new GregorianCalendar();
// add preferred sleep duration
if (userSleepDuration > 0) {
calendar.add(Calendar.HOUR_OF_DAY, userSleepDuration);
calendar.add(Calendar.MINUTE, userSleepDuration);
} else { // probably testing
calendar.add(Calendar.MINUTE, 1);
}
@@ -121,8 +121,7 @@ public class Widget extends AppWidgetProvider {
int distanceCm = (int) dailyTotals.getDistance();
ActivityUser activityUser = new ActivityUser();
int stepGoal = activityUser.getStepsGoal();
int sleepGoal = activityUser.getSleepDurationGoal();
int sleepGoalMinutes = sleepGoal * 60;
int sleepGoalMinutes = activityUser.getSleepDurationGoal();
int distanceGoal = activityUser.getDistanceGoalMeters() * 100;
int stepLength = activityUser.getStepLengthCm();
double distanceMeters = (distanceCm > 0 ? distanceCm : steps * stepLength) * 0.01;
@@ -26,7 +26,7 @@ import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_GOAL_WEIGHT_KG;
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_HEIGHT_CM;
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_NAME;
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_SLEEP_DURATION;
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_SLEEP_DURATION_MINUTES;
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_STEPS_GOAL;
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_STEP_LENGTH_CM;
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_WEIGHT_KG;
@@ -69,7 +69,7 @@ public class AboutUserPreferencesActivity extends AbstractSettingsActivityV2 {
addPreferenceHandlerFor(PREF_USER_GOAL_WEIGHT_KG, true, true);
addPreferenceHandlerFor(PREF_USER_GOAL_STANDING_TIME_HOURS, true, true);
addPreferenceHandlerFor(PREF_USER_GOAL_FAT_BURN_TIME_MINUTES, true, true);
addPreferenceHandlerFor(PREF_USER_SLEEP_DURATION, false, true);
addPreferenceHandlerFor(PREF_USER_SLEEP_DURATION_MINUTES, false, true);
addPreferenceHandlerFor(PREF_USER_STEP_LENGTH_CM, false, true);
addPreferenceHandlerFor(PREF_USER_DISTANCE_METERS, false, true);
@@ -79,7 +79,7 @@ public class AboutUserPreferencesActivity extends AbstractSettingsActivityV2 {
setInputTypeFor(PREF_USER_GOAL_WEIGHT_KG, InputType.TYPE_CLASS_NUMBER);
setInputTypeFor(PREF_USER_GOAL_STANDING_TIME_HOURS, InputType.TYPE_CLASS_NUMBER);
setInputTypeFor(PREF_USER_GOAL_FAT_BURN_TIME_MINUTES, InputType.TYPE_CLASS_NUMBER);
setInputTypeFor(PREF_USER_SLEEP_DURATION, InputType.TYPE_CLASS_NUMBER);
setInputTypeFor(PREF_USER_SLEEP_DURATION_MINUTES, InputType.TYPE_CLASS_NUMBER);
setInputTypeFor(PREF_USER_CALORIES_BURNT, InputType.TYPE_CLASS_NUMBER);
setInputTypeFor(PREF_USER_ACTIVETIME_MINUTES, InputType.TYPE_CLASS_NUMBER);
setInputTypeFor(PREF_USER_STEP_LENGTH_CM, InputType.TYPE_CLASS_NUMBER);
@@ -87,7 +87,7 @@ public class AboutUserPreferencesActivity extends AbstractSettingsActivityV2 {
}
/**
* @param prefKey the pref key that chagned
* @param prefKey the pref key that changed
* @param sendToDevice notify all device support classes of the preference change
* @param refreshDeviceList Ensure that the Control center is re-rendered when user preferences change
*/
@@ -26,6 +26,7 @@ import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
@@ -36,6 +37,7 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class WidgetAlarmsActivity extends Activity implements View.OnClickListener {
@@ -71,8 +73,12 @@ public class WidgetAlarmsActivity extends Activity implements View.OnClickListen
int userSleepDuration = new ActivityUser().getSleepDurationGoal();
textView = findViewById(R.id.alarm5);
if (userSleepDuration > 0) {
Duration duration = Duration.ofMinutes(userSleepDuration);
int hours = (int) duration.toHours();
int mins = (int) duration.minusHours(hours).toMinutes();
Resources res = getResources();
textView.setText(res.getQuantityString(R.plurals.widget_alarm_target_hours, userSleepDuration, userSleepDuration));
textView.setText(res.getQuantityString(R.plurals.widget_alarm_target_hours, hours, hours, mins));
} else {
textView.setVisibility(View.GONE);
}
@@ -113,7 +119,7 @@ public class WidgetAlarmsActivity extends Activity implements View.OnClickListen
int userSleepDuration = new ActivityUser().getSleepDurationGoal();
// add preferred sleep duration
if (userSleepDuration > 0) {
calendar.add(Calendar.HOUR_OF_DAY, userSleepDuration);
calendar.add(Calendar.MINUTE, userSleepDuration);
} else { // probably testing
calendar.add(Calendar.MINUTE, 1);
}
@@ -464,7 +464,7 @@ public class SleepPeriodFragment extends SleepFragment<SleepPeriodFragment.MyCha
}
int getGoal() {
return GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_SLEEP_DURATION, 8) * 60;
return GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_SLEEP_DURATION_MINUTES, ActivityUser.defaultUserSleepDurationGoal);
}
int getOffsetHours() {
@@ -1457,8 +1457,7 @@ public class GBDeviceAdapterv2 extends ListAdapter<GBDevice, GBDeviceAdapterv2.V
int distanceCm = (int) dailyTotals.getDistance();
ActivityUser activityUser = new ActivityUser();
int stepGoal = activityUser.getStepsGoal();
int sleepGoal = activityUser.getSleepDurationGoal();
int sleepGoalMinutes = sleepGoal * 60;
int sleepGoalMinutes = activityUser.getSleepDurationGoal();
int distanceGoal = activityUser.getDistanceGoalMeters() * 100;
int stepLength = activityUser.getStepLengthCm();
double distanceMeters = (distanceCm > 0 ? distanceCm : steps * stepLength) * 0.01;
@@ -278,7 +278,7 @@ public class DBHelper {
attributes.setValidFromUTC(now.getTime());
attributes.setHeightCM(prefsUser.getHeightCm());
attributes.setWeightKG(prefsUser.getWeightKg());
attributes.setSleepGoalHPD(prefsUser.getSleepDurationGoal());
attributes.setSleepGoalMPD(prefsUser.getSleepDurationGoal());
attributes.setStepsGoalSPD(prefsUser.getStepsGoal());
attributes.setUserId(user.getId());
session.getUserAttributesDao().insert(attributes);
@@ -340,8 +340,8 @@ public class DBHelper {
LOG.debug("user weight changed to {} from {}", prefsUser.getWeightKg(), attr.getWeightKG());
return false;
}
if (!Integer.valueOf(prefsUser.getSleepDurationGoal()).equals(attr.getSleepGoalHPD())) {
LOG.debug("user sleep goal changed to {} from {}", prefsUser.getSleepDurationGoal(), attr.getSleepGoalHPD());
if (!Integer.valueOf(prefsUser.getSleepDurationGoal()).equals(attr.getSleepGoalMPD())) {
LOG.debug("user sleep goal changed to {} from {}", prefsUser.getSleepDurationGoal(), attr.getSleepGoalMPD());
return false;
}
if (!Integer.valueOf(prefsUser.getStepsGoal()).equals(attr.getStepsGoalSPD())) {
@@ -0,0 +1,27 @@
package nodomain.freeyourgadget.gadgetbridge.database.schema;
import android.database.sqlite.SQLiteDatabase;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.database.DBUpdateScript;
import nodomain.freeyourgadget.gadgetbridge.entities.UserAttributesDao;
public class GadgetbridgeUpdate_115 implements DBUpdateScript {
@Override
public void upgradeSchema(SQLiteDatabase database) {
final String SLEEP_GOAL_MPD = UserAttributesDao.Properties.SleepGoalMPD.columnName;
final String SLEEP_GOAL_HPD = UserAttributesDao.Properties.SleepGoalMPD.columnName.replace("HPD", "MPD");
final String USER_ATTRIBUTES = UserAttributesDao.TABLENAME;
if (!DBHelper.existsColumn(USER_ATTRIBUTES, SLEEP_GOAL_MPD, database)) {
final String add = "ALTER TABLE " + USER_ATTRIBUTES + " ADD COLUMN " + SLEEP_GOAL_MPD + " INTEGER;";
final String update = "UPDATE " + USER_ATTRIBUTES + " SET " + SLEEP_GOAL_MPD + " = 60 * " + SLEEP_GOAL_HPD + ";";
database.execSQL(add);
database.execSQL(update);
}
}
@Override
public void downgradeSchema(SQLiteDatabase db) {
}
}
@@ -55,7 +55,7 @@ public class ActivityUser {
public static final int defaultUserAge = 0;
public static final int defaultUserHeightCm = 175;
public static final int defaultUserWeightKg = 70;
public static final int defaultUserSleepDurationGoal = 7;
public static final int defaultUserSleepDurationGoal = 7 * 60;
public static final int defaultUserStepsGoal = 8000;
public static final int defaultUserCaloriesBurntGoal = 350;
public static final int defaultUserDistanceGoalMeters = 5000;
@@ -70,7 +70,7 @@ public class ActivityUser {
public static final String PREF_USER_GENDER = "activity_user_gender";
public static final String PREF_USER_HEIGHT_CM = "activity_user_height_cm";
public static final String PREF_USER_WEIGHT_KG = "activity_user_weight_kg";
public static final String PREF_USER_SLEEP_DURATION = "activity_user_sleep_duration";
public static final String PREF_USER_SLEEP_DURATION_MINUTES = "activity_user_sleep_duration_minutes";
public static final String PREF_USER_STEPS_GOAL = "fitness_goal"; // FIXME: for compatibility
public static final String PREF_USER_CALORIES_BURNT = "activity_user_calories_burnt";
public static final String PREF_USER_DISTANCE_METERS = "activity_user_distance_meters";
@@ -129,11 +129,11 @@ public class ActivityUser {
}
/**
* @return the user defined sleep duration or the default value when none is set or the stored
* @return the user defined sleep duration in minutes or the default value when none is set or the stored
* value is out of any logical bounds.
*/
public int getSleepDurationGoal() {
if (activityUserSleepDurationGoal < 1 || activityUserSleepDurationGoal > 24) {
if (activityUserSleepDurationGoal < 1 || activityUserSleepDurationGoal > 24 * 60) {
activityUserSleepDurationGoal = defaultUserSleepDurationGoal;
}
return activityUserSleepDurationGoal;
@@ -157,7 +157,7 @@ public class ActivityUser {
activityUserHeightCm = prefs.getInt(PREF_USER_HEIGHT_CM, defaultUserHeightCm);
activityUserWeightKg = prefs.getInt(PREF_USER_WEIGHT_KG, defaultUserWeightKg);
activityUserDateOfBirth = prefs.getLocalDate(PREF_USER_DATE_OF_BIRTH, defaultUserDateOfBirth);
activityUserSleepDurationGoal = prefs.getInt(PREF_USER_SLEEP_DURATION, defaultUserSleepDurationGoal);
activityUserSleepDurationGoal = prefs.getInt(PREF_USER_SLEEP_DURATION_MINUTES, defaultUserSleepDurationGoal);
activityUserStepsGoal = prefs.getInt(PREF_USER_STEPS_GOAL, defaultUserStepsGoal);
activityUserCaloriesBurntGoal = prefs.getInt(PREF_USER_CALORIES_BURNT, defaultUserCaloriesBurntGoal);
activityUserDistanceGoalMeters = prefs.getInt(PREF_USER_DISTANCE_METERS, defaultUserDistanceGoalMeters);
@@ -2657,7 +2657,7 @@ public abstract class HuamiSupport extends AbstractBTLESingleDeviceSupport
break;
case ActivityUser.PREF_USER_STEPS_GOAL:
case ActivityUser.PREF_USER_CALORIES_BURNT:
case ActivityUser.PREF_USER_SLEEP_DURATION:
case ActivityUser.PREF_USER_SLEEP_DURATION_MINUTES:
case ActivityUser.PREF_USER_GOAL_WEIGHT_KG:
case ActivityUser.PREF_USER_GOAL_STANDING_TIME_HOURS:
case ActivityUser.PREF_USER_GOAL_FAT_BURN_TIME_MINUTES:
@@ -147,7 +147,7 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
// Fitness goals are global
case ActivityUser.PREF_USER_STEPS_GOAL:
case ActivityUser.PREF_USER_CALORIES_BURNT:
case ActivityUser.PREF_USER_SLEEP_DURATION:
case ActivityUser.PREF_USER_SLEEP_DURATION_MINUTES:
case ActivityUser.PREF_USER_GOAL_WEIGHT_KG:
case ActivityUser.PREF_USER_GOAL_STANDING_TIME_HOURS:
case ActivityUser.PREF_USER_GOAL_FAT_BURN_TIME_MINUTES: {
@@ -221,7 +221,7 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
protected void setFitnessGoal(final ZeppOsTransactionBuilder builder) {
final int goalSteps = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_STEPS_GOAL, ActivityUser.defaultUserStepsGoal);
final int goalCalories = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_CALORIES_BURNT, ActivityUser.defaultUserCaloriesBurntGoal);
final int goalSleep = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_SLEEP_DURATION, ActivityUser.defaultUserSleepDurationGoal);
final int goalSleep = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_SLEEP_DURATION_MINUTES, ActivityUser.defaultUserSleepDurationGoal);
final int goalWeight = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_GOAL_WEIGHT_KG, ActivityUser.defaultUserGoalWeightKg);
final int goalStandingTime = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_GOAL_STANDING_TIME_HOURS, ActivityUser.defaultUserGoalStandingTimeHours);
final int goalFatBurnTime = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_GOAL_FAT_BURN_TIME_MINUTES, ActivityUser.defaultUserFatBurnTimeMinutes);
@@ -229,7 +229,7 @@ public class ZeppOsConfigService extends AbstractZeppOsService {
final ConfigSetter setter = newSetter()
.setShort(ConfigArg.FITNESS_GOAL_CALORIES, (short) goalCalories)
.setShort(ConfigArg.FITNESS_GOAL_SLEEP, (short) (goalSleep * 60))
.setShort(ConfigArg.FITNESS_GOAL_SLEEP, (short) goalSleep)
.setShort(ConfigArg.FITNESS_GOAL_STANDING_TIME, (short) (goalStandingTime))
.setShort(ConfigArg.FITNESS_GOAL_FAT_BURN_TIME, (short) goalFatBurnTime);
@@ -214,7 +214,7 @@ public class ZeTimeDeviceSupport extends AbstractBTLESingleDeviceSupport {
setHeartRateLimits(builder);
break;
case DeviceSettingsPreferenceConst.PREF_USER_FITNESS_GOAL:
case ActivityUser.PREF_USER_SLEEP_DURATION:
case ActivityUser.PREF_USER_SLEEP_DURATION_MINUTES:
case ActivityUser.PREF_USER_CALORIES_BURNT:
case ActivityUser.PREF_USER_DISTANCE_METERS:
case ActivityUser.PREF_USER_ACTIVETIME_MINUTES:
@@ -1509,7 +1509,7 @@ public class ZeTimeDeviceSupport extends AbstractBTLESingleDeviceSupport {
int steps = activityUser.getStepsGoal() / 100; // ZeTime expect the steps in 100 increment
int calories = activityUser.getCaloriesBurntGoal();
int distance = activityUser.getDistanceGoalMeters() / 1000; // ZeTime only accepts km goals
int sleep = activityUser.getSleepDurationGoal();
int sleep = Math.round(activityUser.getSleepDurationGoal() / 60.0f);
int activeTime = activityUser.getActiveTimeGoalMinutes();
// set steps goal
@@ -135,7 +135,7 @@ public class DashboardUtils {
public static float getSleepMinutesGoalFactor(DashboardFragment.DashboardData dashboardData) {
ActivityUser activityUser = new ActivityUser();
int sleepMinutesGoal = activityUser.getSleepDurationGoal() * 60;
int sleepMinutesGoal = activityUser.getSleepDurationGoal();
float goalFactor = (float) getSleepMinutesTotal(dashboardData) / sleepMinutesGoal;
if (goalFactor > 1) goalFactor = 1;
+3 -6
View File
@@ -1312,7 +1312,7 @@
<string name="authentication_required">Authentication required</string>
<string name="authentication_failed_check_key">Authentication failed, please check auth key</string>
<string name="authentication_failed_negotiation">Authentication key negotiation failed</string>
<string name="activity_prefs_sleep_duration">Preferred sleep duration in hours</string>
<string name="activity_prefs_sleep_duration_minutes">Preferred sleep duration in minutes</string>
<string name="device_hw">Hardware revision: %1$s</string>
<string name="device_fw">Firmware version: %1$s</string>
<string name="error_creating_directory_for_logfiles">Error creating directory for log files: %1$s</string>
@@ -2817,11 +2817,8 @@
<string name="qhybrid_calibration_align_hint">Use the buttons below to align the watch hands to 12:00.</string>
<string name="lorem_ipsum" translatable="false">Lorem Ipsum</string>
<plurals name="widget_alarm_target_hours">
<item quantity="one">%d hour</item>
<item quantity="two">%d hours</item>
<item quantity="few">%d hours</item>
<item quantity="many">%d hours</item>
<item quantity="other">%d hours</item>
<item quantity="one">%1$d:%2$02d hour</item>
<item quantity="other">%1$d:%2$02d hours</item>
</plurals>
<string name="prefs_autolight">Automatic light</string>
<string name="prefs_light_duration_longer">Longer light duration</string>
+3 -3
View File
@@ -78,9 +78,9 @@
<EditTextPreference
android:icon="@drawable/ic_airline_seat_flat"
android:inputType="number"
android:key="activity_user_sleep_duration"
android:maxLength="2"
android:title="@string/activity_prefs_sleep_duration"
android:key="activity_user_sleep_duration_minutes"
android:maxLength="4"
android:title="@string/activity_prefs_sleep_duration_minutes"
app:useSimpleSummaryProvider="true" />
<EditTextPreference