mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
MetricsSamples: add experimental UI visualisation paths
- (de-)activate via Settings / Developer Options / Experimental metrics UI - UI currently uses this only for TrainingAcuteLoad, TrainingChronicLoad and RestingMetabolicRate - Garmin devices are the only ones that actually record these values in the database
This commit is contained in:
+10
-2
@@ -1,5 +1,6 @@
|
||||
/* Copyright (C) 2015-2024 Andreas Shimokawa, Carsten Pfeiffer, Daniele
|
||||
Gobbetti, Dikay900, José Rebelo, Pavel Elagin, Petr Vaněk, walkjivefly
|
||||
/* Copyright (C) 2015-2026 Andreas Shimokawa, Carsten Pfeiffer, Daniele
|
||||
Gobbetti, Dikay900, José Rebelo, Pavel Elagin, Petr Vaněk, walkjivefly,
|
||||
Thomas Kuehne
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
@@ -48,7 +49,9 @@ import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBAccess;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.GenericMetricSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MetricSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||
|
||||
/**
|
||||
@@ -422,4 +425,9 @@ public abstract class AbstractChartFragment<D extends ChartsData> extends Abstra
|
||||
getChartsHost().setDateInfo(DateTimeUtils.formatDateRange(from, to, dateFlags));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supportsMetrics(MetricSample.Metric metric) {
|
||||
final GBDevice device = getChartsHost().getDevice();
|
||||
return GenericMetricSampleProvider.supportsMetrics(device, metric);
|
||||
}
|
||||
}
|
||||
|
||||
+29
-5
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2024-2025 a0z, José Rebelo, Martin.JM, Thomas Kuehne
|
||||
/* Copyright (C) 2024-2026 a0z, José Rebelo, Martin.JM, Thomas Kuehne
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.charts;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.GenericMetricSampleProvider.getLatestMetricSample;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.MetricSample.Metric.GENERIC_RESTING_METABOLIC_RATE;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -30,6 +33,8 @@ import androidx.core.content.ContextCompat;
|
||||
import com.github.mikephil.charting.charts.Chart;
|
||||
|
||||
import org.apache.commons.lang3.EnumUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
@@ -48,9 +53,11 @@ import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MetricSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.RestingMetabolicRateSample;
|
||||
|
||||
public class CaloriesDailyFragment extends AbstractChartFragment<CaloriesDailyFragment.CaloriesData> {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CaloriesDailyFragment.class);
|
||||
|
||||
private ImageView caloriesGauge;
|
||||
private TextView dateView;
|
||||
@@ -67,6 +74,7 @@ public class CaloriesDailyFragment extends AbstractChartFragment<CaloriesDailyFr
|
||||
TOTAL_CALORIES_SEGMENT
|
||||
}
|
||||
private GaugeViewMode gaugeViewMode;
|
||||
private boolean metricMetabolicResting;
|
||||
|
||||
@Override
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
@@ -95,6 +103,12 @@ public class CaloriesDailyFragment extends AbstractChartFragment<CaloriesDailyFr
|
||||
getChartsHost().enableSwipeRefresh(scrollY == 0);
|
||||
});
|
||||
|
||||
metricMetabolicResting = GBApplication.getPrefs().experimentalMetrics()
|
||||
&& supportsMetrics(GENERIC_RESTING_METABOLIC_RATE);
|
||||
if (metricMetabolicResting) {
|
||||
LOG.info("using experimental MetricSample for resting metabolic rate");
|
||||
}
|
||||
|
||||
caloriesGauge = rootView.findViewById(R.id.calories_gauge);
|
||||
dateView = rootView.findViewById(R.id.date_view);
|
||||
caloriesResting = rootView.findViewById(R.id.calories_resting);
|
||||
@@ -124,6 +138,9 @@ public class CaloriesDailyFragment extends AbstractChartFragment<CaloriesDailyFr
|
||||
}
|
||||
|
||||
public boolean supportsActiveCalories() {
|
||||
if (metricMetabolicResting) {
|
||||
return true;
|
||||
}
|
||||
final GBDevice device = getChartsHost().getDevice();
|
||||
return device.getDeviceCoordinator().supportsActiveCalories(device);
|
||||
}
|
||||
@@ -167,8 +184,15 @@ public class CaloriesDailyFragment extends AbstractChartFragment<CaloriesDailyFr
|
||||
String formattedDate = new SimpleDateFormat("E, MMM dd").format(date);
|
||||
dateView.setText(formattedDate);
|
||||
List<? extends ActivitySample> samples = getActivitySamples(db, device, startTs, endTs);
|
||||
RestingMetabolicRateSample metabolicRate = getRestingMetabolicRate(db, device);
|
||||
if (metabolicRate == null) {
|
||||
final Integer restingMetabolicRate;
|
||||
if (metricMetabolicResting) {
|
||||
MetricSample sample = getLatestMetricSample(db, device, GENERIC_RESTING_METABOLIC_RATE);
|
||||
restingMetabolicRate = (sample == null) ? null : (int) sample.getMetricScore();
|
||||
} else {
|
||||
RestingMetabolicRateSample sample = getRestingMetabolicRate(db, device);
|
||||
restingMetabolicRate = (sample == null) ? null : sample.getRestingMetabolicRate();
|
||||
}
|
||||
if (restingMetabolicRate == null) {
|
||||
return new CaloriesData(0, 0, 0, 0);
|
||||
}
|
||||
int totalBurnt;
|
||||
@@ -179,7 +203,7 @@ public class CaloriesDailyFragment extends AbstractChartFragment<CaloriesDailyFr
|
||||
if (sameDay) {
|
||||
passedDayProportion = (double) (calendar.getTimeInMillis() - day.getTimeInMillis()) / (24L * 60 * 60 * 1000);
|
||||
}
|
||||
int restingBurnt = (int) (metabolicRate.getRestingMetabolicRate() * passedDayProportion);
|
||||
int restingBurnt = (int) (restingMetabolicRate * passedDayProportion);
|
||||
|
||||
for (int i = 0; i <= samples.size() - 1; i++) {
|
||||
ActivitySample sample = samples.get(i);
|
||||
@@ -191,7 +215,7 @@ public class CaloriesDailyFragment extends AbstractChartFragment<CaloriesDailyFr
|
||||
activeBurnt = activeBurnt / 1000;
|
||||
totalBurnt = restingBurnt + activeBurnt;
|
||||
|
||||
return new CaloriesData(totalBurnt, activeBurnt, restingBurnt, metabolicRate.getRestingMetabolicRate());
|
||||
return new CaloriesData(totalBurnt, activeBurnt, restingBurnt, restingMetabolicRate);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+28
-2
@@ -1,5 +1,24 @@
|
||||
/* Copyright (C) 2025-2026 trentsuzuki, Thomas Kuehne
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.charts;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.GenericMetricSampleProvider.getLatestMetricSample;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.MetricSample.Metric.GENERIC_RESTING_METABOLIC_RATE;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -19,6 +38,7 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityAmount;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityAmounts;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MetricSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.RestingMetabolicRateSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue;
|
||||
|
||||
@@ -47,8 +67,14 @@ abstract class CaloriesFragment<T extends ChartsData> extends AbstractChartFragm
|
||||
}
|
||||
|
||||
protected List<CaloriesFragment.CaloriesDay> getMyCaloriesDaysData(DBHandler db, Calendar day, GBDevice device) {
|
||||
RestingMetabolicRateSample metabolicRate = getRestingMetabolicRate(db, device);
|
||||
int restingCalories = metabolicRate.getRestingMetabolicRate();
|
||||
int restingCalories;
|
||||
if (GBApplication.getPrefs().experimentalMetrics() && supportsMetrics(GENERIC_RESTING_METABOLIC_RATE)) {
|
||||
MetricSample sample = getLatestMetricSample(db, device, GENERIC_RESTING_METABOLIC_RATE);
|
||||
restingCalories = (sample == null) ? 0 : (int) sample.getMetricScore();
|
||||
} else {
|
||||
RestingMetabolicRateSample metabolicRate = getRestingMetabolicRate(db, device);
|
||||
restingCalories = metabolicRate.getRestingMetabolicRate();
|
||||
}
|
||||
|
||||
day = (Calendar) day.clone(); // do not modify the caller's argument
|
||||
day.add(Calendar.DATE, -TOTAL_DAYS + 1);
|
||||
|
||||
+58
-15
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2025 a0z, Thomas Kuehne
|
||||
/* Copyright (C) 2025-2026 a0z, Thomas Kuehne
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.charts;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.GenericMetricSampleProvider.getLatestMetricSampleBefore;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.GenericMetricSampleProvider.getMetricSamples;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.MetricSample.Metric.GENERIC_TRAINING_LOAD_ACUTE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.MetricSample.Metric.GENERIC_TRAINING_LOAD_CHRONIC;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
@@ -67,6 +72,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.TimeSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GenericTrainingLoadAcuteSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GenericTrainingLoadChronicSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MetricSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WorkoutLoadSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||
|
||||
@@ -92,6 +98,8 @@ public class LoadFragment extends AbstractChartFragment<LoadFragment.LoadsData>
|
||||
protected int TEXT_COLOR;
|
||||
protected int LOAD_COLOR;
|
||||
|
||||
private boolean metricTrainingLoad;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View rootView = inflater.inflate(R.layout.fragment_load, container, false);
|
||||
@@ -104,6 +112,13 @@ public class LoadFragment extends AbstractChartFragment<LoadFragment.LoadsData>
|
||||
dailyLoadChart = rootView.findViewById(R.id.daily_load_chart);
|
||||
thisWeekTotal = rootView.findViewById(R.id.this_week_total);
|
||||
lastWeekTotal = rootView.findViewById(R.id.last_week_total);
|
||||
|
||||
metricTrainingLoad = GBApplication.getPrefs().experimentalMetrics()
|
||||
&& supportsMetrics(GENERIC_TRAINING_LOAD_ACUTE);
|
||||
if (metricTrainingLoad) {
|
||||
LOG.info("using experimental MetricSample for training load");
|
||||
}
|
||||
|
||||
if (supportsTrainingLoad()) {
|
||||
acuteLoadChart = rootView.findViewById(R.id.acute_load_chart);
|
||||
acuteLoad = rootView.findViewById(R.id.acute_load);
|
||||
@@ -123,6 +138,9 @@ public class LoadFragment extends AbstractChartFragment<LoadFragment.LoadsData>
|
||||
}
|
||||
|
||||
public boolean supportsTrainingLoad() {
|
||||
if (metricTrainingLoad) {
|
||||
return true;
|
||||
}
|
||||
final GBDevice device = getChartsHost().getDevice();
|
||||
return device.getDeviceCoordinator().supportsTrainingLoad(device);
|
||||
}
|
||||
@@ -295,13 +313,24 @@ public class LoadFragment extends AbstractChartFragment<LoadFragment.LoadsData>
|
||||
load = workoutLoadSamples.stream().mapToInt(WorkoutLoadSample::getValue).sum();
|
||||
}
|
||||
if (supportsTrainingLoad()) {
|
||||
List<? extends GenericTrainingLoadAcuteSample> workoutTrainingAcuteLoadSamples = getTrainingLoadAcuteSamples(db, device, startTs, endTs);
|
||||
if (!workoutTrainingAcuteLoadSamples.isEmpty()) {
|
||||
acuteLoad = workoutTrainingAcuteLoadSamples.get(workoutTrainingAcuteLoadSamples.size() - 1).getValue();
|
||||
}
|
||||
List<? extends GenericTrainingLoadChronicSample> workoutTrainingChronicLoadSamples = getTrainingLoadChronicSamples(db, device, startTs, endTs);
|
||||
if (!workoutTrainingChronicLoadSamples.isEmpty()) {
|
||||
chronicLoad = workoutTrainingChronicLoadSamples.get(workoutTrainingChronicLoadSamples.size() - 1).getValue();
|
||||
if (metricTrainingLoad) {
|
||||
List<? extends MetricSample> workoutTrainingAcuteLoadSamples = getMetricSamples(db, device, GENERIC_TRAINING_LOAD_ACUTE, startTs * 1000L, endTs * 1000L);
|
||||
if (!workoutTrainingAcuteLoadSamples.isEmpty()) {
|
||||
acuteLoad = (int) workoutTrainingAcuteLoadSamples.get(workoutTrainingAcuteLoadSamples.size() - 1).getMetricScore();
|
||||
}
|
||||
List<? extends MetricSample> workoutTrainingChronicLoadSamples = getMetricSamples(db, device, GENERIC_TRAINING_LOAD_CHRONIC, startTs * 1000L, endTs * 1000L);
|
||||
if (!workoutTrainingChronicLoadSamples.isEmpty()) {
|
||||
chronicLoad = (int) workoutTrainingChronicLoadSamples.get(workoutTrainingChronicLoadSamples.size() - 1).getMetricScore();
|
||||
}
|
||||
} else {
|
||||
List<? extends GenericTrainingLoadAcuteSample> workoutTrainingAcuteLoadSamples = getTrainingLoadAcuteSamples(db, device, startTs, endTs);
|
||||
if (!workoutTrainingAcuteLoadSamples.isEmpty()) {
|
||||
acuteLoad = workoutTrainingAcuteLoadSamples.get(workoutTrainingAcuteLoadSamples.size() - 1).getValue();
|
||||
}
|
||||
List<? extends GenericTrainingLoadChronicSample> workoutTrainingChronicLoadSamples = getTrainingLoadChronicSamples(db, device, startTs, endTs);
|
||||
if (!workoutTrainingChronicLoadSamples.isEmpty()) {
|
||||
chronicLoad = workoutTrainingChronicLoadSamples.get(workoutTrainingChronicLoadSamples.size() - 1).getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
data.add(new LoadData((Calendar) day.clone(), load, acuteLoad, chronicLoad, i));
|
||||
@@ -320,13 +349,27 @@ public class LoadFragment extends AbstractChartFragment<LoadFragment.LoadsData>
|
||||
int latestChronicLoad = 0;
|
||||
if (supportsTrainingLoad()) {
|
||||
final Date dayEnd = DateTimeUtils.dayEnd(getEndDate());
|
||||
GenericTrainingLoadAcuteSample latestAcuteLoadSample = getLatestTrainingLoadAcuteSample(db, device, dayEnd.getTime());
|
||||
if (latestAcuteLoadSample != null) {
|
||||
latestAcuteLoad = latestAcuteLoadSample.getValue();
|
||||
}
|
||||
GenericTrainingLoadChronicSample latestChronicLoadSample = getLatestTrainingLoadChronicSample(db, device, dayEnd.getTime());
|
||||
if (latestChronicLoadSample != null) {
|
||||
latestChronicLoad = latestChronicLoadSample.getValue();
|
||||
|
||||
if (metricTrainingLoad) {
|
||||
MetricSample latestAcuteLoadSample = getLatestMetricSampleBefore(db, device, GENERIC_TRAINING_LOAD_ACUTE, dayEnd.getTime());
|
||||
if (latestAcuteLoadSample != null) {
|
||||
latestAcuteLoad = (int) latestAcuteLoadSample.getMetricScore();
|
||||
}
|
||||
|
||||
MetricSample latestChronicLoadSample = getLatestMetricSampleBefore(db, device, GENERIC_TRAINING_LOAD_CHRONIC, dayEnd.getTime());
|
||||
if (latestChronicLoadSample != null) {
|
||||
latestChronicLoad = (int) latestChronicLoadSample.getMetricScore();
|
||||
}
|
||||
} else {
|
||||
GenericTrainingLoadAcuteSample latestAcuteLoadSample = getLatestTrainingLoadAcuteSample(db, device, dayEnd.getTime());
|
||||
if (latestAcuteLoadSample != null) {
|
||||
latestAcuteLoad = latestAcuteLoadSample.getValue();
|
||||
}
|
||||
|
||||
GenericTrainingLoadChronicSample latestChronicLoadSample = getLatestTrainingLoadChronicSample(db, device, dayEnd.getTime());
|
||||
if (latestChronicLoadSample != null) {
|
||||
latestChronicLoad = latestChronicLoadSample.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return new LoadsData(data, latestAcuteLoad, latestChronicLoad, thisWeekLoad, lastWeekLoad);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2019-2024 Andreas Shimokawa, Carsten Pfeiffer, Daniel
|
||||
Dakhno, José Rebelo, Petr Vaněk
|
||||
/* Copyright (C) 2019-2026 Andreas Shimokawa, Carsten Pfeiffer, Daniel
|
||||
Dakhno, José Rebelo, Petr Vaněk, Thomas Kuehne
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.model;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.GenericMetricSampleProvider.getLatestMetricSample;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.GenericMetricSampleProvider.supportsMetrics;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.MetricSample.Metric.GENERIC_RESTING_METABOLIC_RATE;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -159,8 +163,15 @@ public class DailyTotals implements Serializable {
|
||||
day.set(Calendar.MINUTE, 0);
|
||||
day.set(Calendar.SECOND, 0);
|
||||
day.add(Calendar.HOUR, 0);
|
||||
RestingMetabolicRateSample metabolicRate = getRestingMetabolicRate(db, day, device);
|
||||
if (metabolicRate == null) {
|
||||
final Integer restingMetabolicRate;
|
||||
if (GBApplication.getPrefs().experimentalMetrics() && supportsMetrics(device, GENERIC_RESTING_METABOLIC_RATE)) {
|
||||
MetricSample sample = getLatestMetricSample(db, device, GENERIC_RESTING_METABOLIC_RATE, day);
|
||||
restingMetabolicRate = (sample == null) ? null : (int) sample.getMetricScore();
|
||||
} else {
|
||||
RestingMetabolicRateSample sample = getRestingMetabolicRate(db, day, device);
|
||||
restingMetabolicRate = (sample == null) ? null : sample.getRestingMetabolicRate();
|
||||
}
|
||||
if (restingMetabolicRate == null) {
|
||||
// should never happen
|
||||
return 0;
|
||||
}
|
||||
@@ -170,7 +181,7 @@ public class DailyTotals implements Serializable {
|
||||
if (sameDay) {
|
||||
passedDayProportion = (double) (calendar.getTimeInMillis() - day.getTimeInMillis()) / (24L * 60 * 60 * 1000);
|
||||
}
|
||||
return (int) (metabolicRate.getRestingMetabolicRate() * passedDayProportion);
|
||||
return (int) (restingMetabolicRate * passedDayProportion);
|
||||
}
|
||||
|
||||
public static List<? extends ActivitySample> getSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
|
||||
|
||||
@@ -238,4 +238,8 @@ public class GBPrefs extends Prefs {
|
||||
public boolean experimentalSettings() {
|
||||
return getBoolean("experimental_settings", false);
|
||||
}
|
||||
|
||||
public boolean experimentalMetrics() {
|
||||
return getBoolean("experimental_metrics", false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -773,6 +773,8 @@
|
||||
<string name="pref_cache_weather">Cache weather information</string>
|
||||
<string name="pref_experimental_settings_title">Experimental settings</string>
|
||||
<string name="pref_experimental_settings_summary">Experimental settings might be unstable or not work as expected. Proceed at your own risk.</string>
|
||||
<string name="pref_experimental_metrics_title">Generic Metrics</string>
|
||||
<string name="pref_experimental_metrics_summary">Enable experimental UI logic for generic metrics. Currently only relevant for training load and calories recorded by Garmin devices.</string>
|
||||
<string name="pref_cache_weather_summary">Weather information will be cached across application restarts.</string>
|
||||
<string name="pref_write_logfiles_not_available">File logging initialization failed, writing log files is currently not available. Restart the application to attempt to initialize the log files again.</string>
|
||||
<string name="initializing">Initializing</string>
|
||||
|
||||
@@ -540,6 +540,14 @@
|
||||
android:summary="@string/pref_experimental_settings_summary"
|
||||
android:title="@string/pref_experimental_settings_title"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="experimental_metrics"
|
||||
android:layout="@layout/preference_checkbox"
|
||||
android:summary="@string/pref_experimental_metrics_summary"
|
||||
android:title="@string/pref_experimental_metrics_title"
|
||||
app:iconSpaceReserved="false" />
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceScreen
|
||||
|
||||
Reference in New Issue
Block a user