mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-09 03:37:03 +01:00
HRV Status (#3953)
Co-authored-by: a0z <a0z@tutamail.com> Co-committed-by: a0z <a0z@tutamail.com>
This commit is contained in:
parent
996d176cc2
commit
f3b1a06d47
@ -122,7 +122,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 = 30;
|
||||
private static final int CURRENT_PREFS_VERSION = 31;
|
||||
|
||||
private static final LimitedQueue<Integer, String> mIDSenderLookup = new LimitedQueue<>(16);
|
||||
private static GBPrefs prefs;
|
||||
@ -1483,6 +1483,36 @@ public class GBApplication extends Application {
|
||||
}
|
||||
}
|
||||
|
||||
if (oldVersion < 31) {
|
||||
// Add the new HRV Status tab to all devices
|
||||
try (DBHandler db = acquireDB()) {
|
||||
final DaoSession daoSession = db.getDaoSession();
|
||||
final List<Device> activeDevices = DBHelper.getActiveDevices(daoSession);
|
||||
|
||||
for (final Device dbDevice : activeDevices) {
|
||||
final SharedPreferences deviceSharedPrefs = GBApplication.getDeviceSpecificSharedPrefs(dbDevice.getIdentifier());
|
||||
|
||||
final String chartsTabsValue = deviceSharedPrefs.getString("charts_tabs", null);
|
||||
if (chartsTabsValue == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final String newPrefValue;
|
||||
if (!StringUtils.isBlank(chartsTabsValue)) {
|
||||
newPrefValue = chartsTabsValue + ",hrvstatus";
|
||||
} else {
|
||||
newPrefValue = "hrvstatus";
|
||||
}
|
||||
|
||||
final SharedPreferences.Editor deviceSharedPrefsEdit = deviceSharedPrefs.edit();
|
||||
deviceSharedPrefsEdit.putString("charts_tabs", newPrefValue);
|
||||
deviceSharedPrefsEdit.apply();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "error acquiring DB lock");
|
||||
}
|
||||
}
|
||||
|
||||
editor.putString(PREFS_VERSION, Integer.toString(CURRENT_PREFS_VERSION));
|
||||
editor.apply();
|
||||
}
|
||||
|
@ -111,6 +111,9 @@ public class ActivityChartsActivity extends AbstractChartsActivity {
|
||||
if(!coordinator.supportsCyclingData()) {
|
||||
tabList.remove("cycling");
|
||||
}
|
||||
if (!coordinator.supportsHrvMeasurement()) {
|
||||
tabList.remove("hrvstatus");
|
||||
}
|
||||
return tabList;
|
||||
}
|
||||
|
||||
@ -140,6 +143,8 @@ public class ActivityChartsActivity extends AbstractChartsActivity {
|
||||
return new SleepChartFragment();
|
||||
case "sleepweek":
|
||||
return new WeekSleepChartFragment();
|
||||
case "hrvstatus":
|
||||
return new HRVStatusFragment();
|
||||
case "stress":
|
||||
return new StressChartFragment();
|
||||
case "pai":
|
||||
@ -192,6 +197,8 @@ public class ActivityChartsActivity extends AbstractChartsActivity {
|
||||
return getString(R.string.sleepchart_your_sleep);
|
||||
case "sleepweek":
|
||||
return getSleepTitle();
|
||||
case "hrvstatus":
|
||||
return getString(R.string.pref_header_hrv_status);
|
||||
case "stress":
|
||||
return getString(R.string.menuitem_stress);
|
||||
case "pai":
|
||||
|
@ -0,0 +1,367 @@
|
||||
/* Copyright (C) 2017-2024 Andreas Shimokawa, Daniele Gobbetti, José Rebelo
|
||||
|
||||
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 android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.github.mikephil.charting.charts.Chart;
|
||||
import com.github.mikephil.charting.charts.LineChart;
|
||||
import com.github.mikephil.charting.components.LegendEntry;
|
||||
import com.github.mikephil.charting.components.XAxis;
|
||||
import com.github.mikephil.charting.components.YAxis;
|
||||
import com.github.mikephil.charting.data.Entry;
|
||||
import com.github.mikephil.charting.data.LineData;
|
||||
import com.github.mikephil.charting.data.LineDataSet;
|
||||
import com.github.mikephil.charting.formatter.ValueFormatter;
|
||||
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.TimeSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.HrvSummarySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.HrvValueSample;
|
||||
|
||||
|
||||
public class HRVStatusFragment extends AbstractChartFragment<HRVStatusFragment.HRVStatusWeeklyData> {
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(HRVStatusFragment.class);
|
||||
protected final int TOTAL_DAYS = 7;
|
||||
|
||||
private LineChart mWeeklyHRVStatusChart;
|
||||
private TextView mHRVStatusSevenDaysAvg;
|
||||
private TextView mHRVStatusSevenDaysAvgStatus; // Balanced, Unbalanced, Low
|
||||
private TextView mHRVStatusLastNight;
|
||||
private TextView mHRVStatusLastNight5MinHighest;
|
||||
private TextView mHRVStatusDayAvg;
|
||||
private TextView mHRVStatusBaseline;
|
||||
private TextView mDateView;
|
||||
protected int CHART_TEXT_COLOR;
|
||||
protected int LEGEND_TEXT_COLOR;
|
||||
protected int TEXT_COLOR;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View rootView = inflater.inflate(R.layout.fragment_hrv_status, container, false);
|
||||
|
||||
mWeeklyHRVStatusChart = rootView.findViewById(R.id.hrv_weekly_line_chart);
|
||||
mHRVStatusLastNight = rootView.findViewById(R.id.hrv_status_last_night);
|
||||
mHRVStatusSevenDaysAvg = rootView.findViewById(R.id.hrv_status_seven_days_avg);
|
||||
mHRVStatusSevenDaysAvgStatus = rootView.findViewById(R.id.hrv_status_seven_days_avg_rate);
|
||||
mHRVStatusLastNight5MinHighest = rootView.findViewById(R.id.hrv_status_last_night_highest_5);
|
||||
mHRVStatusDayAvg = rootView.findViewById(R.id.hrv_status_day_avg);
|
||||
mHRVStatusBaseline = rootView.findViewById(R.id.hrv_status_baseline);
|
||||
mDateView = rootView.findViewById(R.id.hrv_status_date_view);
|
||||
|
||||
setupLineChart();
|
||||
refresh();
|
||||
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return getString(R.string.pref_header_hrv_status);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
TEXT_COLOR = GBApplication.getTextColor(getContext());
|
||||
LEGEND_TEXT_COLOR = GBApplication.getTextColor(getContext());
|
||||
CHART_TEXT_COLOR = GBApplication.getSecondaryTextColor(getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HRVStatusWeeklyData refreshInBackground(ChartsHost chartsHost, DBHandler db, GBDevice device) {
|
||||
Calendar day = Calendar.getInstance();
|
||||
Date tsEnd = getChartsHost().getEndDate();
|
||||
day.setTime(tsEnd);
|
||||
String formattedDate = new SimpleDateFormat("E, MMM dd").format(tsEnd);
|
||||
mDateView.setText(formattedDate);
|
||||
List<HRVStatusDayData> weeklyData = getWeeklyData(db, day, device);
|
||||
return new HRVStatusWeeklyData(weeklyData);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderCharts() {
|
||||
mWeeklyHRVStatusChart.invalidate();
|
||||
}
|
||||
|
||||
protected LineDataSet createDataSet(final List<Entry> values) {
|
||||
final LineDataSet lineDataSet = new LineDataSet(values, getString(R.string.hrv_status_day_avg));
|
||||
lineDataSet.setColor(getResources().getColor(R.color.hrv_status_char_line_color));
|
||||
lineDataSet.setDrawCircles(false);
|
||||
lineDataSet.setLineWidth(2f);
|
||||
lineDataSet.setFillAlpha(255);
|
||||
lineDataSet.setCircleRadius(5f);
|
||||
lineDataSet.setDrawCircles(true);
|
||||
lineDataSet.setDrawCircleHole(true);
|
||||
lineDataSet.setCircleColor(getResources().getColor(R.color.hrv_status_char_line_color));
|
||||
lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT);
|
||||
lineDataSet.setDrawValues(true);
|
||||
lineDataSet.setValueTextSize(10f);
|
||||
lineDataSet.setValueTextColor(CHART_TEXT_COLOR);
|
||||
lineDataSet.setValueFormatter(new ValueFormatter() {
|
||||
@Override
|
||||
public String getFormattedValue(float value) {
|
||||
return String.format(Locale.ROOT, "%d", (int) value);
|
||||
}
|
||||
});
|
||||
return lineDataSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateChartsnUIThread(HRVStatusWeeklyData weeklyData) {
|
||||
mWeeklyHRVStatusChart.setData(null); // workaround for https://github.com/PhilJay/MPAndroidChart/issues/2317
|
||||
List<Entry> lineEntries = new ArrayList<>();
|
||||
final List<ILineDataSet> lineDataSets = new ArrayList<>();
|
||||
weeklyData.getDaysData().forEach((HRVStatusDayData day) -> {
|
||||
if (day.status.getNum() > 0) {
|
||||
lineEntries.add(new Entry(day.i, day.dayAvg));
|
||||
} else {
|
||||
if (!lineEntries.isEmpty()) {
|
||||
lineDataSets.add(createDataSet(lineEntries));
|
||||
lineEntries.clear();
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!lineEntries.isEmpty()) {
|
||||
lineDataSets.add(createDataSet(lineEntries));
|
||||
}
|
||||
|
||||
List<LegendEntry> legendEntries = new ArrayList<>(1);
|
||||
LegendEntry activityEntry = new LegendEntry();
|
||||
activityEntry.label = getString(R.string.hrv_status_day_avg_legend);
|
||||
activityEntry.formColor = getResources().getColor(R.color.hrv_status_char_line_color);
|
||||
legendEntries.add(activityEntry);
|
||||
mWeeklyHRVStatusChart.getLegend().setTextColor(LEGEND_TEXT_COLOR);
|
||||
mWeeklyHRVStatusChart.getLegend().setCustom(legendEntries);
|
||||
|
||||
final LineData lineData = new LineData(lineDataSets);
|
||||
mWeeklyHRVStatusChart.setData(lineData);
|
||||
|
||||
final XAxis x = mWeeklyHRVStatusChart.getXAxis();
|
||||
x.setValueFormatter(getHRVStatusChartDayValueFormatter(weeklyData));
|
||||
|
||||
HRVStatusDayData today = weeklyData.getCurrentDay();
|
||||
mHRVStatusSevenDaysAvg.setText(today.weeklyAvg > 0 ? getString(R.string.hrv_status_unit, today.weeklyAvg) : "-");
|
||||
mHRVStatusLastNight.setText(today.lastNight > 0 ? getString(R.string.hrv_status_unit, today.lastNight) : "-");
|
||||
mHRVStatusLastNight5MinHighest.setText(today.lastNight5MinHigh > 0 ? getString(R.string.hrv_status_unit, today.lastNight5MinHigh) : "-");
|
||||
mHRVStatusDayAvg.setText(today.dayAvg > 0 ? getString(R.string.hrv_status_unit, today.dayAvg) : "-");
|
||||
mHRVStatusBaseline.setText(today.baseLineBalancedLower > 0 && today.baseLineBalancedUpper > 0 ? getString(R.string.hrv_status_baseline, today.baseLineBalancedLower, today.baseLineBalancedUpper) : "-");
|
||||
switch (today.status.getNum()) {
|
||||
case 0:
|
||||
mHRVStatusSevenDaysAvgStatus.setText("-");
|
||||
mHRVStatusSevenDaysAvgStatus.setTextColor(TEXT_COLOR);
|
||||
break;
|
||||
case 1:
|
||||
mHRVStatusSevenDaysAvgStatus.setText(getString(R.string.hrv_status_poor));
|
||||
mHRVStatusSevenDaysAvgStatus.setTextColor(getResources().getColor(R.color.hrv_status_poor));
|
||||
break;
|
||||
case 2:
|
||||
mHRVStatusSevenDaysAvgStatus.setText(getString(R.string.hrv_status_low));
|
||||
mHRVStatusSevenDaysAvgStatus.setTextColor(getResources().getColor(R.color.hrv_status_low));
|
||||
break;
|
||||
case 3:
|
||||
mHRVStatusSevenDaysAvgStatus.setText(getString(R.string.hrv_status_unbalanced));
|
||||
mHRVStatusSevenDaysAvgStatus.setTextColor(getResources().getColor(R.color.hrv_status_unbalanced));
|
||||
break;
|
||||
case 4:
|
||||
mHRVStatusSevenDaysAvgStatus.setText(getString(R.string.hrv_status_balanced));
|
||||
mHRVStatusSevenDaysAvgStatus.setTextColor(getResources().getColor(R.color.hrv_status_balanced));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private List<HRVStatusDayData> getWeeklyData(DBHandler db, Calendar day, GBDevice device) {
|
||||
day = (Calendar) day.clone(); // do not modify the caller's argument
|
||||
day.add(Calendar.DATE, -TOTAL_DAYS);
|
||||
|
||||
List<HRVStatusDayData> weeklyData = new ArrayList<>();
|
||||
for (int counter = 0; counter < TOTAL_DAYS; counter++) {
|
||||
int startTs = (int) (day.getTimeInMillis() / 1000);
|
||||
int endTs = startTs + 24 * 60 * 60 - 1;
|
||||
day.add(Calendar.DATE, 1);
|
||||
List<? extends HrvSummarySample> summarySamples = getSamples(db, device, startTs, endTs);
|
||||
List<? extends HrvValueSample> valueSamples = getHrvValueSamples(db, device, startTs, endTs);
|
||||
|
||||
int avgHRV = (int) valueSamples.stream().mapToInt(v -> {return v.getValue();}).average().orElse(0);
|
||||
if (!summarySamples.isEmpty()) {
|
||||
int finalCounter = counter;
|
||||
Calendar finalDay = (Calendar) day.clone();
|
||||
summarySamples.forEach(sample -> {
|
||||
weeklyData.add(new HRVStatusDayData(
|
||||
finalDay,
|
||||
finalCounter,
|
||||
sample.getTimestamp(),
|
||||
avgHRV, sample.getWeeklyAverage(),
|
||||
sample.getLastNightAverage(),
|
||||
sample.getLastNight5MinHigh(),
|
||||
sample.getBaselineBalancedLower(),
|
||||
sample.getBaselineBalancedUpper(),
|
||||
sample.getStatus()
|
||||
));
|
||||
});
|
||||
} else {
|
||||
HRVStatusDayData d = new HRVStatusDayData(
|
||||
(Calendar) day.clone(),
|
||||
counter,
|
||||
0,
|
||||
avgHRV,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
HrvSummarySample.Status.NONE
|
||||
);
|
||||
weeklyData.add(d);
|
||||
}
|
||||
}
|
||||
return weeklyData;
|
||||
}
|
||||
|
||||
private List<? extends HrvSummarySample> getSamples(final DBHandler db, final GBDevice device, int tsFrom, int tsTo) {
|
||||
final DeviceCoordinator coordinator = device.getDeviceCoordinator();
|
||||
final TimeSampleProvider<? extends HrvSummarySample> sampleProvider = coordinator.getHrvSummarySampleProvider(device, db.getDaoSession());
|
||||
return sampleProvider.getAllSamples(tsFrom * 1000L, tsTo * 1000L);
|
||||
}
|
||||
|
||||
public List<? extends HrvValueSample> getHrvValueSamples(final DBHandler db, final GBDevice device, int tsFrom, int tsTo) {
|
||||
final DeviceCoordinator coordinator = device.getDeviceCoordinator();
|
||||
final TimeSampleProvider<? extends HrvValueSample> sampleProvider = coordinator.getHrvValueSampleProvider(device, db.getDaoSession());
|
||||
return sampleProvider.getAllSamples(tsFrom * 1000L, tsTo * 1000L);
|
||||
}
|
||||
|
||||
private void setupLineChart() {
|
||||
mWeeklyHRVStatusChart.getDescription().setEnabled(false);
|
||||
mWeeklyHRVStatusChart.setTouchEnabled(false);
|
||||
mWeeklyHRVStatusChart.setPinchZoom(false);
|
||||
mWeeklyHRVStatusChart.setDoubleTapToZoomEnabled(false);
|
||||
|
||||
|
||||
final XAxis xAxisBottom = mWeeklyHRVStatusChart.getXAxis();
|
||||
xAxisBottom.setPosition(XAxis.XAxisPosition.BOTTOM);
|
||||
xAxisBottom.setDrawLabels(true);
|
||||
xAxisBottom.setDrawGridLines(false);
|
||||
xAxisBottom.setEnabled(true);
|
||||
xAxisBottom.setDrawLimitLinesBehindData(true);
|
||||
xAxisBottom.setAxisMaximum(6 + 0.5f);
|
||||
xAxisBottom.setAxisMinimum(0 - 0.5f);
|
||||
xAxisBottom.setTextColor(CHART_TEXT_COLOR);
|
||||
|
||||
final YAxis yAxisLeft = mWeeklyHRVStatusChart.getAxisLeft();
|
||||
yAxisLeft.setDrawGridLines(true);
|
||||
yAxisLeft.setAxisMaximum(120);
|
||||
yAxisLeft.setAxisMinimum(0);
|
||||
yAxisLeft.setDrawTopYLabelEntry(false);
|
||||
yAxisLeft.setEnabled(true);
|
||||
yAxisLeft.setTextColor(CHART_TEXT_COLOR);
|
||||
|
||||
final YAxis yAxisRight = mWeeklyHRVStatusChart.getAxisRight();
|
||||
yAxisRight.setEnabled(true);
|
||||
yAxisRight.setDrawLabels(false);
|
||||
yAxisRight.setDrawGridLines(false);
|
||||
yAxisRight.setDrawAxisLine(true);
|
||||
}
|
||||
|
||||
ValueFormatter getHRVStatusChartDayValueFormatter(HRVStatusWeeklyData weeklyData) {
|
||||
return new ValueFormatter() {
|
||||
@Override
|
||||
public String getFormattedValue(float value) {
|
||||
return formatHRVStatusChartValue((long) value, weeklyData);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected String formatHRVStatusChartValue(long value, HRVStatusWeeklyData weeklyData) {
|
||||
HRVStatusDayData day = weeklyData.getDay((int) value);
|
||||
SimpleDateFormat formatLetterDay = new SimpleDateFormat("EEEEE", Locale.getDefault());
|
||||
return formatLetterDay.format(new Date(day.day.getTimeInMillis()));
|
||||
}
|
||||
|
||||
protected void setupLegend(Chart chart) {}
|
||||
|
||||
protected static class HRVStatusWeeklyData extends ChartsData {
|
||||
private final List<HRVStatusDayData> data;
|
||||
|
||||
public HRVStatusWeeklyData(final List<HRVStatusDayData> chartsData) {
|
||||
this.data = chartsData;
|
||||
}
|
||||
|
||||
public HRVStatusDayData getDay(int i) {
|
||||
return this.data.get(i);
|
||||
}
|
||||
|
||||
public HRVStatusDayData getCurrentDay() {
|
||||
return this.data.get(this.data.size() - 1);
|
||||
}
|
||||
|
||||
public List<HRVStatusDayData> getDaysData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
protected static class HRVStatusDayData {
|
||||
public Integer i;
|
||||
public long timestamp;
|
||||
public Integer weeklyAvg;
|
||||
public Integer lastNight;
|
||||
public Integer lastNight5MinHigh;
|
||||
public Integer dayAvg;
|
||||
public Integer baseLineBalancedLower;
|
||||
public Integer baseLineBalancedUpper;
|
||||
public HrvSummarySample.Status status;
|
||||
public Calendar day;
|
||||
|
||||
public HRVStatusDayData(Calendar day,
|
||||
int i, long timestamp,
|
||||
Integer dayAvg,
|
||||
Integer weeklyAvg,
|
||||
Integer lastNight,
|
||||
Integer lastNight5MinHigh,
|
||||
Integer baseLineBalancedLower,
|
||||
Integer baseLineBalancedUpper,
|
||||
HrvSummarySample.Status status) {
|
||||
this.lastNight = lastNight;
|
||||
this.weeklyAvg = weeklyAvg;
|
||||
this.lastNight5MinHigh = lastNight5MinHigh;
|
||||
this.i = i;
|
||||
this.timestamp = timestamp;
|
||||
this.status = status;
|
||||
this.day = day;
|
||||
this.dayAvg = dayAvg;
|
||||
this.baseLineBalancedLower = baseLineBalancedLower;
|
||||
this.baseLineBalancedUpper = baseLineBalancedUpper;
|
||||
}
|
||||
}
|
||||
}
|
@ -79,4 +79,5 @@ public class AmazfitActiveCoordinator extends ZeppOsCoordinator {
|
||||
public boolean supportsBluetoothPhoneCalls(final GBDevice device) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
263
app/src/main/res/layout/fragment_hrv_status.xml
Normal file
263
app/src/main/res/layout/fragment_hrv_status.xml
Normal file
@ -0,0 +1,263 @@
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.HRVStatus$PlaceholderFragment">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/hrv_status_date_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textSize="20sp"
|
||||
android:layout_marginTop="15dp"
|
||||
/>
|
||||
|
||||
<TableLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="30dp"
|
||||
android:layout_weight="3"
|
||||
android:shrinkColumns="*"
|
||||
android:stretchColumns="*">
|
||||
|
||||
<TableRow
|
||||
android:id="@+id/tableRow1"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:weightSum="2">
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="20dip"
|
||||
android:paddingTop="20dip"
|
||||
android:paddingRight="20dip">
|
||||
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="5px"
|
||||
android:background="@color/value_line_color" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/hrv_status_seven_days_avg"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:layout_marginTop="20dip"
|
||||
android:text="-"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:text="@string/hrv_status_seven_days_avg"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="20dip"
|
||||
android:paddingTop="20dip"
|
||||
android:paddingRight="20dip">
|
||||
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="5px"
|
||||
android:background="@color/value_line_color" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/hrv_status_seven_days_avg_rate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:layout_marginTop="20dip"
|
||||
android:text="-"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:text="@string/hrv_status_seven_days_avg_status"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:id="@+id/tableRow3"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:weightSum="2">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/hrv_status_day_avg_wrapper"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="20dip"
|
||||
android:paddingTop="20dip"
|
||||
android:paddingRight="20dip">
|
||||
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="5px"
|
||||
android:background="@color/value_line_color" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/hrv_status_day_avg"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:layout_marginTop="20dip"
|
||||
android:text="-"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:text="@string/hrv_status_day_avg"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/hrv_status_baseline_wrapper"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="20dip"
|
||||
android:paddingTop="20dip"
|
||||
android:paddingRight="20dip">
|
||||
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="5px"
|
||||
android:background="@color/value_line_color" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/hrv_status_baseline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:layout_marginTop="20dip"
|
||||
android:text="-"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:text="@string/hrv_status_baseline_label"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:id="@+id/tableRow2"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:weightSum="2">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/sleep_chart_legend_rem_time_wrapper"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="20dip"
|
||||
android:paddingTop="20dip"
|
||||
android:paddingRight="20dip">
|
||||
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="5px"
|
||||
android:background="@color/value_line_color" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/hrv_status_last_night"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:layout_marginTop="20dip"
|
||||
android:text="-"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:text="@string/hrv_status_last_night"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/hrv_status_last_night_highest_5_wrapper"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="20dip"
|
||||
android:paddingTop="20dip"
|
||||
android:paddingRight="20dip">
|
||||
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="5px"
|
||||
android:background="@color/value_line_color" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/hrv_status_last_night_highest_5"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:layout_marginTop="20dip"
|
||||
android:text="-"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:text="@string/hrv_status_last_night_highest_5"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
</TableRow>
|
||||
|
||||
</TableLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250sp">
|
||||
|
||||
<com.github.mikephil.charting.charts.LineChart
|
||||
android:id="@+id/hrv_weekly_line_chart"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_weight="2" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
@ -3011,6 +3011,7 @@
|
||||
<item>@string/sleepchart_your_sleep</item>
|
||||
<item>@string/weeksleepchart_sleep_a_week_or_month</item>
|
||||
<item>@string/weekstepschart_steps_a_week_or_month</item>
|
||||
<item>@string/pref_header_hrv_status</item>
|
||||
<item>@string/menuitem_stress</item>
|
||||
<item>@string/menuitem_pai</item>
|
||||
<item>@string/stats_title</item>
|
||||
@ -3025,6 +3026,7 @@
|
||||
<item>@string/p_sleep</item>
|
||||
<item>@string/p_sleep_week</item>
|
||||
<item>@string/p_steps_week</item>
|
||||
<item>@string/p_hrv_status</item>
|
||||
<item>@string/p_stress</item>
|
||||
<item>@string/p_pai</item>
|
||||
<item>@string/p_speed_zones</item>
|
||||
@ -3039,6 +3041,7 @@
|
||||
<item>@string/p_activity_list</item>
|
||||
<item>@string/p_sleep</item>
|
||||
<item>@string/p_sleep_week</item>
|
||||
<item>@string/p_hrv_status</item>
|
||||
<item>@string/p_steps_week</item>
|
||||
<item>@string/p_stress</item>
|
||||
<item>@string/p_pai</item>
|
||||
|
@ -43,6 +43,14 @@
|
||||
<color name="chart_stress_moderate" type="color">#ffab40</color>
|
||||
<color name="chart_stress_high" type="color">#8B0000</color>
|
||||
|
||||
<color name="hrv_status_balanced" type="color">#0c8a03</color>
|
||||
<color name="hrv_status_unbalanced" type="color">#fc9d03</color>
|
||||
<color name="hrv_status_low" type="color">#fc5203</color>
|
||||
<color name="hrv_status_poor" type="color">#be03fc</color>
|
||||
<color name="hrv_status_char_line_color" type="color">#d12a2a</color>
|
||||
|
||||
<color name="value_line_color" type="color">#858585</color>
|
||||
|
||||
<color name="alternate_row_background_light">#FFEDEDED</color>
|
||||
<color name="alternate_row_background_dark">#545254</color>
|
||||
|
||||
|
@ -842,6 +842,7 @@
|
||||
<string name="prefs_charts_tabs">Charts tabs</string>
|
||||
<string name="prefs_charts_tabs_summary">Visible chart tabs</string>
|
||||
<string name="sleepchart_your_sleep">Sleep</string>
|
||||
<string name="hrv_status">HRV Status</string>
|
||||
<string name="weeksleepchart_sleep_a_week">Sleep per week</string>
|
||||
<string name="weeksleepchart_today_sleep_description">Sleep today, target: %1$s</string>
|
||||
<string name="weekstepschart_steps_a_week">Steps per week</string>
|
||||
@ -1438,6 +1439,20 @@
|
||||
<string name="activity_summary_detail_editing_gpx_track">Editing linked GPX track</string>
|
||||
<string name="activity_summary_today">Today</string>
|
||||
<string name="activity_summary_yesterday">Yesterday</string>
|
||||
<string name="hrv_status_day_avg">DAY AVG</string>
|
||||
<string name="hrv_status_day_avg_legend">DAY AVG(MS)</string>
|
||||
<string name="hrv_status_seven_days_avg">7 DAY AVG</string>
|
||||
<string name="hrv_status_seven_days_avg_status">STATUS</string>
|
||||
<string name="hrv_status_balanced">Balanced</string>
|
||||
<string name="hrv_status_unbalanced">Unbalanced</string>
|
||||
<string name="hrv_status_low">Low</string>
|
||||
<string name="hrv_status_poor">Poor</string>
|
||||
<string name="hrv_status_last_night">LAST NIGHT</string>
|
||||
<string name="hrv_status_last_night_highest_5">LST N HIGHEST 5-MIN AVG</string>
|
||||
<string name="hrv_status_seven_days_avg_long">7 DAY AVERAGE</string>
|
||||
<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="activity_type_biking">Biking</string>
|
||||
<string name="activity_type_treadmill">Treadmill</string>
|
||||
<string name="activity_type_exercise">Exercise</string>
|
||||
@ -2298,6 +2313,7 @@
|
||||
<string name="pref_header_heartrate_alerts">Heart rate alerts</string>
|
||||
<string name="pref_header_stress">Stress</string>
|
||||
<string name="pref_header_spo2">Blood Oxygen</string>
|
||||
<string name="pref_header_hrv_status">HRV Status</string>
|
||||
<string name="pref_header_sony_ambient_sound_control">Ambient Sound Control</string>
|
||||
<string name="pref_header_sony_sound_control">Sound Control</string>
|
||||
<string name="pref_header_sony_device_info">Device Information</string>
|
||||
|
@ -105,6 +105,7 @@
|
||||
<item name="p_stress" type="string">stress</item>
|
||||
<item name="p_pai" type="string">pai</item>
|
||||
<item name="p_speed_zones" type="string">speedzones</item>
|
||||
<item name="p_hrv_status" type="string">hrvstatus</item>
|
||||
<item name="p_live_stats" type="string">livestats</item>
|
||||
<item name="p_spo2" type="string">spo2</item>
|
||||
<item name="p_temperature" type="string">temperature</item>
|
||||
|
Loading…
Reference in New Issue
Block a user