mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-12-26 10:35:50 +01:00
VO2Max: replace GENERAL vo2max with ANY, add widgets
This commit is contained in:
parent
9f0d426a9f
commit
f2227bb083
@ -127,7 +127,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 = 40;
|
||||
private static final int CURRENT_PREFS_VERSION = 41;
|
||||
|
||||
private static final LimitedQueue<Integer, String> mIDSenderLookup = new LimitedQueue<>(16);
|
||||
private static GBPrefs prefs;
|
||||
@ -1823,6 +1823,14 @@ public class GBApplication extends Application {
|
||||
}
|
||||
}
|
||||
|
||||
if (oldVersion < 41) {
|
||||
// Add vo2max widget.
|
||||
final String dashboardWidgetsOrder = sharedPrefs.getString("pref_dashboard_widgets_order", null);
|
||||
if (!StringUtils.isBlank(dashboardWidgetsOrder) && !dashboardWidgetsOrder.contains("vo2max")) {
|
||||
editor.putString("pref_dashboard_widgets_order", dashboardWidgetsOrder + ",vo2max");
|
||||
}
|
||||
}
|
||||
|
||||
editor.putString(PREFS_VERSION, Integer.toString(CURRENT_PREFS_VERSION));
|
||||
editor.apply();
|
||||
}
|
||||
|
@ -75,6 +75,9 @@ import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardStress
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardStressSegmentedWidget;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardStressSimpleWidget;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardTodayWidget;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardVO2MaxCyclingWidget;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardVO2MaxAnyWidget;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardVO2MaxRunningWidget;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DashboardUtils;
|
||||
@ -298,6 +301,15 @@ public class DashboardFragment extends Fragment implements MenuProvider {
|
||||
case "hrv":
|
||||
widget = DashboardHrvWidget.newInstance(dashboardData);
|
||||
break;
|
||||
case "vo2max_running":
|
||||
widget = DashboardVO2MaxRunningWidget.newInstance(dashboardData);
|
||||
break;
|
||||
case "vo2max_cycling":
|
||||
widget = DashboardVO2MaxCyclingWidget.newInstance(dashboardData);
|
||||
break;
|
||||
case "vo2max":
|
||||
widget = DashboardVO2MaxAnyWidget.newInstance(dashboardData);
|
||||
break;
|
||||
default:
|
||||
LOG.error("Unknown dashboard widget {}", widgetName);
|
||||
continue;
|
||||
|
@ -246,7 +246,7 @@ public class HeartRateDailyFragment extends AbstractChartFragment<HeartRateDaily
|
||||
hrLineChart.getAxisRight().setAxisMaximum(maximum + 30);
|
||||
}
|
||||
|
||||
hrLineChart.getXAxis().setValueFormatter(new SampleXLabelFormatter(tsTranslation));
|
||||
hrLineChart.getXAxis().setValueFormatter(new SampleXLabelFormatter(tsTranslation, "HH:mm"));
|
||||
hrLineChart.setData(new LineData(dataSet));
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@ import java.util.Map;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.AbstractDashboardVO2MaxWidget;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.GaugeDrawer;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||
@ -49,17 +50,14 @@ public class VO2MaxFragment extends AbstractChartFragment<VO2MaxFragment.VO2MaxD
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(VO2MaxFragment.class);
|
||||
|
||||
private TextView mDateView;
|
||||
private TextView vo2MaxGeneralValue;
|
||||
private TextView vo2MaxRunningValue;
|
||||
private TextView vo2MaxCyclingValue;
|
||||
private ImageView vo2MaxGeneralGauge;
|
||||
private ImageView vo2MaxRunningGauge;
|
||||
private ImageView vo2MaxCyclingGauge;
|
||||
protected GaugeDrawer gaugeDrawer = new GaugeDrawer();
|
||||
private LineChart vo2MaxChart;
|
||||
private RelativeLayout vo2maxCyclingWrapper;
|
||||
private RelativeLayout vo2maxRunningWrapper;
|
||||
private RelativeLayout vo2maxGeneralWrapper;
|
||||
private GridLayout tilesGridWrapper;
|
||||
private int tsFrom;
|
||||
GBDevice device;
|
||||
@ -73,15 +71,12 @@ public class VO2MaxFragment extends AbstractChartFragment<VO2MaxFragment.VO2MaxD
|
||||
View rootView = inflater.inflate(R.layout.fragment_vo2max, container, false);
|
||||
|
||||
mDateView = rootView.findViewById(R.id.vo2max_date_view);
|
||||
vo2MaxGeneralValue = rootView.findViewById(R.id.vo2max_general_gauge_value);
|
||||
vo2MaxRunningValue = rootView.findViewById(R.id.vo2max_running_gauge_value);
|
||||
vo2MaxCyclingValue = rootView.findViewById(R.id.vo2max_cycling_gauge_value);
|
||||
vo2MaxGeneralGauge = rootView.findViewById(R.id.vo2max_general_gauge);
|
||||
vo2MaxRunningGauge = rootView.findViewById(R.id.vo2max_running_gauge);
|
||||
vo2MaxCyclingGauge = rootView.findViewById(R.id.vo2max_cycling_gauge);
|
||||
vo2MaxChart = rootView.findViewById(R.id.vo2max_chart);
|
||||
vo2maxCyclingWrapper = rootView.findViewById(R.id.vo2max_cycling_card_layout);
|
||||
vo2maxGeneralWrapper = rootView.findViewById(R.id.vo2max_general_card_layout);
|
||||
vo2maxRunningWrapper = rootView.findViewById(R.id.vo2max_running_card_layout);
|
||||
tilesGridWrapper = rootView.findViewById(R.id.tiles_grid_wrapper);
|
||||
device = getChartsHost().getDevice();
|
||||
@ -91,11 +86,9 @@ public class VO2MaxFragment extends AbstractChartFragment<VO2MaxFragment.VO2MaxD
|
||||
if (!supportsVO2MaxRunning(device)) {
|
||||
tilesGridWrapper.removeView(vo2maxRunningWrapper);
|
||||
}
|
||||
if (!supportsVO2MaxGeneral(device)) {
|
||||
tilesGridWrapper.removeView(vo2maxGeneralWrapper);
|
||||
}
|
||||
setupVO2MaxChart();
|
||||
refresh();
|
||||
setupLegend(vo2MaxChart);
|
||||
|
||||
|
||||
return rootView;
|
||||
@ -106,11 +99,6 @@ public class VO2MaxFragment extends AbstractChartFragment<VO2MaxFragment.VO2MaxD
|
||||
return coordinator != null && coordinator.supportsVO2MaxCycling();
|
||||
}
|
||||
|
||||
public boolean supportsVO2MaxGeneral(GBDevice device) {
|
||||
DeviceCoordinator coordinator = device.getDeviceCoordinator();
|
||||
return coordinator != null && coordinator.supportsVO2MaxGeneral();
|
||||
}
|
||||
|
||||
public boolean supportsVO2MaxRunning(GBDevice device) {
|
||||
DeviceCoordinator coordinator = device.getDeviceCoordinator();
|
||||
return coordinator != null && coordinator.supportsVO2MaxRunning();
|
||||
@ -160,7 +148,6 @@ public class VO2MaxFragment extends AbstractChartFragment<VO2MaxFragment.VO2MaxD
|
||||
TimestampTranslation tsTranslation = new TimestampTranslation();
|
||||
List<Entry> runningEntries = new ArrayList<>();
|
||||
List<Entry> cyclingEntries = new ArrayList<>();
|
||||
List<Entry> generalEntries = new ArrayList<>();
|
||||
vo2MaxData.records.forEach((record) -> {
|
||||
float nd = (float) (record.timestamp - this.tsFrom) / (60 * 60 * 24);
|
||||
switch (record.type) {
|
||||
@ -170,54 +157,25 @@ public class VO2MaxFragment extends AbstractChartFragment<VO2MaxFragment.VO2MaxD
|
||||
case CYCLING:
|
||||
cyclingEntries.add(new Entry(nd, record.value));
|
||||
break;
|
||||
case GENERAL:
|
||||
generalEntries.add(new Entry(nd, record.value));
|
||||
break;
|
||||
}
|
||||
});
|
||||
final int[] colors = {
|
||||
ContextCompat.getColor(GBApplication.getContext(), R.color.vo2max_value_poor_color),
|
||||
ContextCompat.getColor(GBApplication.getContext(), R.color.vo2max_value_fair_color),
|
||||
ContextCompat.getColor(GBApplication.getContext(), R.color.vo2max_value_good_color),
|
||||
ContextCompat.getColor(GBApplication.getContext(), R.color.vo2max_value_excellent_color),
|
||||
ContextCompat.getColor(GBApplication.getContext(), R.color.vo2max_value_superior_color),
|
||||
};
|
||||
final float[] segments = {
|
||||
0.20F,
|
||||
0.20F,
|
||||
0.20F,
|
||||
0.20F,
|
||||
0.20F,
|
||||
};
|
||||
float[] vo2MaxRanges = {
|
||||
55.4F,
|
||||
51.1F,
|
||||
45.4F,
|
||||
41.7F,
|
||||
0.0F,
|
||||
};
|
||||
|
||||
final int[] colors = AbstractDashboardVO2MaxWidget.getColors();
|
||||
final float[] segments = AbstractDashboardVO2MaxWidget.getSegments();
|
||||
float[] vo2MaxRanges = AbstractDashboardVO2MaxWidget.getVO2MaxRanges();
|
||||
final List<ILineDataSet> lineDataSets = new ArrayList<>();
|
||||
if (supportsVO2MaxGeneral(device)) {
|
||||
VO2MaxRecord latestGeneralRecord = vo2MaxData.getLatestValue(Vo2MaxSample.Type.GENERAL);
|
||||
float generalVO2MaxValue = calculateVO2maxGaugeValue(vo2MaxRanges, latestGeneralRecord != null ? latestGeneralRecord.value : 0);
|
||||
gaugeDrawer.drawSegmentedGauge(vo2MaxGeneralGauge, colors, segments, generalVO2MaxValue, false, true);
|
||||
vo2MaxGeneralValue.setText(String.valueOf(latestGeneralRecord != null ? Math.round(latestGeneralRecord.value) : "-"));
|
||||
lineDataSets.add(createDataSet(generalEntries, getResources().getColor(R.color.vo2max_general_char_line_color), getString(R.string.vo2_max_general)));
|
||||
}
|
||||
if (supportsVO2MaxRunning(device)) {
|
||||
VO2MaxRecord latestRunningRecord = vo2MaxData.getLatestValue(Vo2MaxSample.Type.RUNNING);
|
||||
float runningVO2MaxValue = calculateVO2maxGaugeValue(vo2MaxRanges, latestRunningRecord != null ? latestRunningRecord.value : 0);
|
||||
vo2MaxRunningValue.setText(String.valueOf(latestRunningRecord != null ? Math.round(latestRunningRecord.value) : "-"));
|
||||
gaugeDrawer.drawSegmentedGauge(vo2MaxRunningGauge, colors, segments, runningVO2MaxValue, false, true);
|
||||
lineDataSets.add(createDataSet(runningEntries, getResources().getColor(R.color.vo2max_running_char_line_color), getString(R.string.vo2_max_running)));
|
||||
lineDataSets.add(createDataSet(runningEntries, getResources().getColor(R.color.vo2max_running_char_line_color), getString(R.string.vo2max_running)));
|
||||
}
|
||||
if (supportsVO2MaxCycling(device)) {
|
||||
VO2MaxRecord latestCyclingRecord = vo2MaxData.getLatestValue(Vo2MaxSample.Type.CYCLING);
|
||||
float cyclingVO2MaxValue = calculateVO2maxGaugeValue(vo2MaxRanges, latestCyclingRecord != null ? latestCyclingRecord.value : 0);
|
||||
gaugeDrawer.drawSegmentedGauge(vo2MaxCyclingGauge, colors, segments, cyclingVO2MaxValue, false, true);
|
||||
vo2MaxCyclingValue.setText(String.valueOf(latestCyclingRecord != null ? Math.round(latestCyclingRecord.value) : "-"));
|
||||
lineDataSets.add(createDataSet(cyclingEntries, getResources().getColor(R.color.vo2max_cycling_char_line_color), getString(R.string.vo2_max_cycling)));
|
||||
lineDataSets.add(createDataSet(cyclingEntries, getResources().getColor(R.color.vo2max_cycling_char_line_color), getString(R.string.vo2max_cycling)));
|
||||
}
|
||||
final LineData lineData = new LineData(lineDataSets);
|
||||
vo2MaxChart.getXAxis().setValueFormatter(getVO2MaxLineChartValueFormatter());
|
||||
@ -320,7 +278,10 @@ public class VO2MaxFragment extends AbstractChartFragment<VO2MaxFragment.VO2MaxD
|
||||
yAxisRight.setDrawAxisLine(true);
|
||||
}
|
||||
|
||||
protected void setupLegend(Chart<?> chart) {}
|
||||
protected void setupLegend(Chart<?> chart) {
|
||||
chart.getLegend().setTextColor(LEGEND_TEXT_COLOR);
|
||||
chart.getLegend().setWordWrapEnabled(true);
|
||||
}
|
||||
|
||||
protected static class VO2MaxRecord {
|
||||
float value;
|
||||
|
@ -0,0 +1,124 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.Vo2MaxSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Vo2MaxSample;
|
||||
|
||||
public abstract class AbstractDashboardVO2MaxWidget extends AbstractGaugeWidget implements DashboardVO2MaxWidgetInterface {
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(AbstractDashboardVO2MaxWidget.class);
|
||||
|
||||
public AbstractDashboardVO2MaxWidget(int label, @Nullable String targetActivityTab) {
|
||||
super(label, targetActivityTab);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void populateData(final DashboardFragment.DashboardData dashboardData) {
|
||||
final List<GBDevice> devices = getSupportedDevices(dashboardData);
|
||||
final VO2MaxData data = new VO2MaxData();
|
||||
|
||||
// Latest vo2max sample.
|
||||
Vo2MaxSample sample = null;
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
for (GBDevice dev : devices) {
|
||||
final Vo2MaxSampleProvider sampleProvider = (Vo2MaxSampleProvider) dev.getDeviceCoordinator().getVo2MaxSampleProvider(dev, dbHandler.getDaoSession());
|
||||
final Vo2MaxSample latestSample = sampleProvider.getLatestSample(getVO2MaxType(), dashboardData.timeTo * 1000L);
|
||||
if (latestSample != null && (sample == null || latestSample.getTimestamp() > sample.getTimestamp())) {
|
||||
sample = latestSample;
|
||||
}
|
||||
}
|
||||
|
||||
if (sample != null) {
|
||||
data.value = sample.getValue();
|
||||
}
|
||||
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Could not get vo2max for today", e);
|
||||
}
|
||||
|
||||
dashboardData.put(getWidgetKey(), data);
|
||||
}
|
||||
|
||||
public static int[] getColors() {
|
||||
return new int[]{
|
||||
ContextCompat.getColor(GBApplication.getContext(), R.color.vo2max_value_poor_color),
|
||||
ContextCompat.getColor(GBApplication.getContext(), R.color.vo2max_value_fair_color),
|
||||
ContextCompat.getColor(GBApplication.getContext(), R.color.vo2max_value_good_color),
|
||||
ContextCompat.getColor(GBApplication.getContext(), R.color.vo2max_value_excellent_color),
|
||||
ContextCompat.getColor(GBApplication.getContext(), R.color.vo2max_value_superior_color),
|
||||
};
|
||||
}
|
||||
|
||||
public static float[] getSegments() {
|
||||
return new float[] {
|
||||
0.20F,
|
||||
0.20F,
|
||||
0.20F,
|
||||
0.20F,
|
||||
0.20F,
|
||||
};
|
||||
}
|
||||
|
||||
public static float[] getVO2MaxRanges() {
|
||||
return new float[] {
|
||||
55.4F,
|
||||
51.1F,
|
||||
45.4F,
|
||||
41.7F,
|
||||
0.0F,
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void draw(final DashboardFragment.DashboardData dashboardData) {
|
||||
final VO2MaxData vo2MaxData = (VO2MaxData) dashboardData.get(getWidgetKey());
|
||||
if (vo2MaxData == null) {
|
||||
drawSimpleGauge(0, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
final int[] colors = getColors();
|
||||
final float[] segments = getSegments();
|
||||
final float[] vo2MaxRanges = getVO2MaxRanges();
|
||||
float vo2MaxValue = calculateVO2maxGaugeValue(vo2MaxRanges, vo2MaxData.value != -1 ? vo2MaxData.value : 0);
|
||||
setText(String.valueOf(vo2MaxData.value != -1 ? Math.round(vo2MaxData.value) : "-"));
|
||||
drawSegmentedGauge(
|
||||
colors,
|
||||
segments,
|
||||
vo2MaxValue,
|
||||
false,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
private float calculateVO2maxGaugeValue(float[] vo2MaxRanges, float vo2MaxValue) {
|
||||
float value = -1;
|
||||
for (int i = 0; i < vo2MaxRanges.length; i++) {
|
||||
if (vo2MaxValue - vo2MaxRanges[i] > 0) {
|
||||
float rangeValue = i - 1 >= 0 ? vo2MaxRanges[i-1] : 60F;
|
||||
float rangeDiff = rangeValue - vo2MaxRanges[i];
|
||||
float valueDiff = vo2MaxValue - vo2MaxRanges[i];
|
||||
float multiplayer = valueDiff / rangeDiff;
|
||||
value = (4 - i) * 0.2F + 0.2F * (multiplayer > 1 ? 1 : multiplayer) ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private static class VO2MaxData implements Serializable {
|
||||
private float value = -1;
|
||||
}
|
||||
}
|
@ -16,22 +16,14 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
|
@ -0,0 +1,36 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Vo2MaxSample;
|
||||
|
||||
public class DashboardVO2MaxAnyWidget extends AbstractDashboardVO2MaxWidget {
|
||||
|
||||
public DashboardVO2MaxAnyWidget() {
|
||||
super(R.string.vo2max, "vo2max");
|
||||
}
|
||||
|
||||
public static DashboardVO2MaxAnyWidget newInstance(final DashboardFragment.DashboardData dashboardData) {
|
||||
final DashboardVO2MaxAnyWidget fragment = new DashboardVO2MaxAnyWidget();
|
||||
final Bundle args = new Bundle();
|
||||
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public Vo2MaxSample.Type getVO2MaxType() {
|
||||
return Vo2MaxSample.Type.ANY;
|
||||
}
|
||||
|
||||
public String getWidgetKey() {
|
||||
return "vo2max";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSupportedBy(final GBDevice device) {
|
||||
return device.getDeviceCoordinator().supportsVO2Max();
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Vo2MaxSample;
|
||||
|
||||
public class DashboardVO2MaxCyclingWidget extends AbstractDashboardVO2MaxWidget {
|
||||
|
||||
public DashboardVO2MaxCyclingWidget() {
|
||||
super(R.string.vo2max_cycling, "vo2max");
|
||||
}
|
||||
|
||||
public static DashboardVO2MaxCyclingWidget newInstance(final DashboardFragment.DashboardData dashboardData) {
|
||||
final DashboardVO2MaxCyclingWidget fragment = new DashboardVO2MaxCyclingWidget();
|
||||
final Bundle args = new Bundle();
|
||||
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public Vo2MaxSample.Type getVO2MaxType() {
|
||||
return Vo2MaxSample.Type.CYCLING;
|
||||
}
|
||||
|
||||
public String getWidgetKey() {
|
||||
return "vo2max_cycling";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSupportedBy(final GBDevice device) {
|
||||
return device.getDeviceCoordinator().supportsVO2MaxCycling();
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Vo2MaxSample;
|
||||
|
||||
public class DashboardVO2MaxRunningWidget extends AbstractDashboardVO2MaxWidget {
|
||||
|
||||
public DashboardVO2MaxRunningWidget() {
|
||||
super(R.string.vo2max_running, "vo2max");
|
||||
}
|
||||
|
||||
public static DashboardVO2MaxRunningWidget newInstance(final DashboardFragment.DashboardData dashboardData) {
|
||||
final DashboardVO2MaxRunningWidget fragment = new DashboardVO2MaxRunningWidget();
|
||||
final Bundle args = new Bundle();
|
||||
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public Vo2MaxSample.Type getVO2MaxType() {
|
||||
return Vo2MaxSample.Type.RUNNING;
|
||||
}
|
||||
|
||||
public String getWidgetKey() {
|
||||
return "vo2max_running";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSupportedBy(final GBDevice device) {
|
||||
return device.getDeviceCoordinator().supportsVO2MaxRunning();
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Vo2MaxSample;
|
||||
|
||||
public interface DashboardVO2MaxWidgetInterface {
|
||||
Vo2MaxSample.Type getVO2MaxType();
|
||||
String getWidgetKey();
|
||||
}
|
@ -490,11 +490,6 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsVO2MaxGeneral() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsActivityTabs() {
|
||||
return supportsActivityTracking();
|
||||
|
@ -221,7 +221,6 @@ public interface DeviceCoordinator {
|
||||
boolean supportsHrvMeasurement();
|
||||
boolean supportsVO2Max();
|
||||
boolean supportsVO2MaxCycling();
|
||||
boolean supportsVO2MaxGeneral();
|
||||
boolean supportsVO2MaxRunning();
|
||||
boolean supportsSleepMeasurement();
|
||||
boolean supportsStepCounter();
|
||||
|
@ -146,7 +146,7 @@ public class GarminVo2MaxSampleProvider implements Vo2MaxSampleProvider<Vo2MaxSa
|
||||
@Nullable
|
||||
@Override
|
||||
public Vo2MaxSample getLatestSample() {
|
||||
return getLatestSample(Vo2MaxSample.Type.GENERAL, 0);
|
||||
return getLatestSample(Vo2MaxSample.Type.ANY, 0);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -231,7 +231,7 @@ public class GarminVo2MaxSampleProvider implements Vo2MaxSampleProvider<Vo2MaxSa
|
||||
type = Vo2MaxSample.Type.CYCLING;
|
||||
break;
|
||||
default:
|
||||
type = Vo2MaxSample.Type.GENERAL;
|
||||
type = Vo2MaxSample.Type.ANY;
|
||||
}
|
||||
return new GarminVo2maxSample(summary.getStartTime().getTime(), type, (float) value);
|
||||
} catch (final JSONException e) {
|
||||
|
@ -18,7 +18,7 @@ package nodomain.freeyourgadget.gadgetbridge.model;
|
||||
|
||||
public interface Vo2MaxSample extends TimeSample {
|
||||
enum Type {
|
||||
GENERAL,
|
||||
ANY,
|
||||
RUNNING,
|
||||
CYCLING
|
||||
}
|
||||
|
@ -23,41 +23,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:columnCount="2"
|
||||
>
|
||||
<RelativeLayout
|
||||
android:id="@+id/vo2max_general_card_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="UselessParent"
|
||||
android:layout_gravity="fill"
|
||||
android:layout_columnWeight="1"
|
||||
>
|
||||
<ImageView
|
||||
android:id="@+id/vo2max_general_gauge"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="75dp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:scaleType="fitStart" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/vo2max_general_gauge_value"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="28dp"
|
||||
android:text="@string/stats_empty_value"
|
||||
android:textSize="30sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/vo2max_general_gauge_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/vo2max_general_gauge_value"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:text="@string/vo2max_general_gauge_label" />
|
||||
|
||||
</RelativeLayout>
|
||||
<RelativeLayout
|
||||
android:id="@+id/vo2max_running_card_layout"
|
||||
android:layout_width="wrap_content"
|
||||
@ -91,7 +56,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/vo2max_running_gauge_value"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:text="@string/vo2max_running_gauge_label" />
|
||||
android:text="@string/running" />
|
||||
|
||||
</RelativeLayout>
|
||||
<RelativeLayout
|
||||
@ -127,7 +92,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/vo2max_cycling_gauge_value"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:text="@string/vo2max_cycling_gauge_label" />
|
||||
android:text="@string/cycling" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
@ -4177,11 +4177,13 @@
|
||||
<item>@string/active_time</item>
|
||||
<item>@string/menuitem_sleep</item>
|
||||
<item>@string/body_energy</item>
|
||||
<item>@string/vo2max</item>
|
||||
<item>@string/menuitem_stress_simple</item>
|
||||
<item>@string/menuitem_stress_segmented</item>
|
||||
<item>@string/menuitem_stress_breakdown</item>
|
||||
<item>@string/hrv</item>
|
||||
<item>@string/vo2max</item>
|
||||
<item>@string/vo2max_running</item>
|
||||
<item>@string/vo2max_cycling</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_dashboard_widgets_order_values">
|
||||
@ -4192,11 +4194,13 @@
|
||||
<item>activetime</item>
|
||||
<item>sleep</item>
|
||||
<item>bodyenergy</item>
|
||||
<item>vo2max</item>
|
||||
<item>stress_simple</item>
|
||||
<item>stress_segmented</item>
|
||||
<item>stress_breakdown</item>
|
||||
<item>hrv</item>
|
||||
<item>vo2max</item>
|
||||
<item>vo2max_running</item>
|
||||
<item>vo2max_cycling</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref_dashboard_widgets_order_default">
|
||||
@ -4209,5 +4213,6 @@
|
||||
<item>bodyenergy</item>
|
||||
<item>stress_segmented</item>
|
||||
<item>hrv</item>
|
||||
<item>vo2max</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
@ -53,7 +53,6 @@
|
||||
<color name="hrv_status_char_line_color" type="color">#d12a2a</color>
|
||||
<color name="vo2max_running_char_line_color" type="color">#46acea</color>
|
||||
<color name="vo2max_cycling_char_line_color" type="color">#59b22c</color>
|
||||
<color name="vo2max_general_char_line_color" type="color">#824be3</color>
|
||||
<color name="vo2max_value_poor_color" type="color">#d93832</color>
|
||||
<color name="vo2max_value_fair_color" type="color">#ffa703</color>
|
||||
<color name="vo2max_value_good_color" type="color">#04c79c</color>
|
||||
|
@ -1623,9 +1623,8 @@
|
||||
<string name="hrv_status_unit">%1$d ms</string>
|
||||
<string name="hrv_status_baseline">%1$d-%2$d ms</string>
|
||||
<string name="hrv_status_baseline_label">Baseline</string>
|
||||
<string name="vo2_max_running">VO2Max Running</string>
|
||||
<string name="vo2_max_cycling">VO2Max Cycling</string>
|
||||
<string name="vo2_max_general">VO2Max General</string>
|
||||
<string name="running">Running</string>
|
||||
<string name="cycling">Cycling</string>
|
||||
<string name="bpm_value_unit">%1$d bpm</string>
|
||||
<string name="steps_distance_unit">%1$,.2f km</string>
|
||||
<string name="body_energy_gained">Gained</string>
|
||||
@ -1993,9 +1992,6 @@
|
||||
<string name="warning">Warning!</string>
|
||||
<string name="note">Note</string>
|
||||
<string name="no_data">No data</string>
|
||||
<string name="vo2max_general_gauge_label">VO2Max</string>
|
||||
<string name="vo2max_running_gauge_label">Running VO2Max</string>
|
||||
<string name="vo2max_cycling_gauge_label">Cycling VO2Max</string>
|
||||
<!-- LED Color -->
|
||||
<string name="preferences_led_color">LED Color</string>
|
||||
<!-- FM transmitters -->
|
||||
@ -2537,6 +2533,8 @@
|
||||
<string name="pref_header_hrv_status">HRV Status</string>
|
||||
<string name="body_energy">Body Energy</string>
|
||||
<string name="vo2max">VO2 Max</string>
|
||||
<string name="vo2max_running">VO2 Max (Running)</string>
|
||||
<string name="vo2max_cycling">VO2 Max (Cycling)</string>
|
||||
<string name="thirty_days_timeline">30 Days Timeline</string>
|
||||
<string name="pref_header_sony_ambient_sound_control">Ambient Sound Control</string>
|
||||
<string name="pref_header_sony_sound_control">Sound Control</string>
|
||||
|
Loading…
Reference in New Issue
Block a user