1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-09 03:37:03 +01:00

Sleep tabs refactor

This commit is contained in:
a0z 2024-08-04 19:27:17 +02:00 committed by José Rebelo
parent 2f21c4bd9d
commit a3e6d446d7
9 changed files with 696 additions and 124 deletions

View File

@ -65,12 +65,12 @@ public abstract class AbstractWeekChartFragment extends AbstractActivityChartFra
protected final int TOTAL_DAYS = getRangeDays(); protected final int TOTAL_DAYS = getRangeDays();
protected int TOTAL_DAYS_FOR_AVERAGE = 0; protected int TOTAL_DAYS_FOR_AVERAGE = 0;
private Locale mLocale; protected Locale mLocale;
private int mTargetValue = 0; protected int mTargetValue = 0;
private PieChart mTodayPieChart; protected PieChart mTodayPieChart;
private BarChart mWeekChart; protected BarChart mWeekChart;
private TextView mBalanceView; protected TextView mBalanceView;
private int mOffsetHours = getOffsetHours(); private int mOffsetHours = getOffsetHours();
ImageView stepsStreaksButton; ImageView stepsStreaksButton;
@ -113,7 +113,7 @@ public abstract class AbstractWeekChartFragment extends AbstractActivityChartFra
} }
} }
private boolean enableStepStreaksButton(){ protected boolean enableStepStreaksButton(){
return this.getClass().getSimpleName().equals("WeekStepsChartFragment"); return this.getClass().getSimpleName().equals("WeekStepsChartFragment");
} }
@ -124,7 +124,7 @@ public abstract class AbstractWeekChartFragment extends AbstractActivityChartFra
// mBalanceView.setText(getBalanceMessage(balance)); // mBalanceView.setText(getBalanceMessage(balance));
} }
private String getWeeksChartsLabel(Calendar day){ protected String getWeeksChartsLabel(Calendar day){
if (GBApplication.getPrefs().getBoolean("charts_range", true)) { if (GBApplication.getPrefs().getBoolean("charts_range", true)) {
//month, show day date //month, show day date
return String.valueOf(day.get(Calendar.DAY_OF_MONTH)); return String.valueOf(day.get(Calendar.DAY_OF_MONTH));
@ -134,10 +134,9 @@ public abstract class AbstractWeekChartFragment extends AbstractActivityChartFra
return day.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, mLocale); return day.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, mLocale);
} }
} }
protected WeekChartsData<BarData> refreshWeekBeforeData(DBHandler db, BarChart barChart, Calendar day, GBDevice device) {
private WeekChartsData<BarData> refreshWeekBeforeData(DBHandler db, BarChart barChart, Calendar day, GBDevice device) {
day = (Calendar) day.clone(); // do not modify the caller's argument day = (Calendar) day.clone(); // do not modify the caller's argument
day.add(Calendar.DATE, -TOTAL_DAYS); day.add(Calendar.DATE, -TOTAL_DAYS + 1);
List<BarEntry> entries = new ArrayList<>(); List<BarEntry> entries = new ArrayList<>();
ArrayList<String> labels = new ArrayList<String>(); ArrayList<String> labels = new ArrayList<String>();
@ -191,10 +190,10 @@ public abstract class AbstractWeekChartFragment extends AbstractActivityChartFra
} }
} }
return new WeekChartsData(barData, new PreformattedXIndexLabelFormatter(labels), getBalanceMessage(balance, mTargetValue)); return new WeekChartsData(barData, new PreformattedXIndexLabelFormatter(labels), getBalanceMessage(balance, mTargetValue));
} }
private DayData refreshDayPie(DBHandler db, Calendar day, GBDevice device) { protected DayData refreshDayPie(DBHandler db, Calendar day, GBDevice device) {
PieData data = new PieData(); PieData data = new PieData();
List<PieEntry> entries = new ArrayList<>(); List<PieEntry> entries = new ArrayList<>();
@ -276,7 +275,7 @@ public abstract class AbstractWeekChartFragment extends AbstractActivityChartFra
private void setupTodayPieChart() { protected void setupTodayPieChart() {
mTodayPieChart.setBackgroundColor(BACKGROUND_COLOR); mTodayPieChart.setBackgroundColor(BACKGROUND_COLOR);
mTodayPieChart.getDescription().setTextColor(DESCRIPTION_COLOR); mTodayPieChart.getDescription().setTextColor(DESCRIPTION_COLOR);
mTodayPieChart.setEntryLabelColor(DESCRIPTION_COLOR); mTodayPieChart.setEntryLabelColor(DESCRIPTION_COLOR);
@ -286,7 +285,7 @@ public abstract class AbstractWeekChartFragment extends AbstractActivityChartFra
mTodayPieChart.getLegend().setEnabled(false); mTodayPieChart.getLegend().setEnabled(false);
} }
private void setupWeekChart() { protected void setupWeekChart() {
mWeekChart.setBackgroundColor(BACKGROUND_COLOR); mWeekChart.setBackgroundColor(BACKGROUND_COLOR);
mWeekChart.getDescription().setTextColor(DESCRIPTION_COLOR); mWeekChart.getDescription().setTextColor(DESCRIPTION_COLOR);
mWeekChart.getDescription().setText(""); mWeekChart.getDescription().setText("");
@ -369,7 +368,7 @@ public abstract class AbstractWeekChartFragment extends AbstractActivityChartFra
} }
} }
private ActivityAmounts getActivityAmountsForDay(DBHandler db, Calendar day, GBDevice device) { protected ActivityAmounts getActivityAmountsForDay(DBHandler db, Calendar day, GBDevice device) {
LimitedQueue<Integer, ActivityAmounts> activityAmountCache = null; LimitedQueue<Integer, ActivityAmounts> activityAmountCache = null;
ActivityAmounts amounts = null; ActivityAmounts amounts = null;
@ -426,7 +425,7 @@ public abstract class AbstractWeekChartFragment extends AbstractActivityChartFra
protected abstract String getBalanceMessage(long balance, int targetValue); protected abstract String getBalanceMessage(long balance, int targetValue);
private class WeekChartsData<T extends ChartData<?>> extends DefaultChartsData<T> { protected class WeekChartsData<T extends ChartData<?>> extends DefaultChartsData<T> {
private final String balanceMessage; private final String balanceMessage;
public WeekChartsData(T data, PreformattedXIndexLabelFormatter xIndexLabelFormatter, String balanceMessage) { public WeekChartsData(T data, PreformattedXIndexLabelFormatter xIndexLabelFormatter, String balanceMessage) {

View File

@ -20,12 +20,14 @@ package nodomain.freeyourgadget.gadgetbridge.activities.charts;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Color; import android.graphics.Color;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.text.method.ScrollingMovementMethod; import android.text.method.ScrollingMovementMethod;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
@ -34,10 +36,7 @@ import com.github.mikephil.charting.animation.Easing;
import com.github.mikephil.charting.charts.Chart; import com.github.mikephil.charting.charts.Chart;
import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.charts.PieChart;
import com.github.mikephil.charting.components.LegendEntry; import com.github.mikephil.charting.components.*;
import com.github.mikephil.charting.components.LimitLine;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieData;
import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieDataSet;
@ -49,10 +48,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList; import java.text.SimpleDateFormat;
import java.util.Collections; import java.util.*;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
@ -73,10 +70,14 @@ public class SleepChartFragment extends AbstractActivityChartFragment<SleepChart
private LineChart mActivityChart; private LineChart mActivityChart;
private PieChart mSleepAmountChart; private PieChart mSleepAmountChart;
private TextView mSleepchartInfo; private TextView mSleepchartInfo;
private TextView heartRateAverageLabel; private TextView remSleepTimeText;
private ImageView heartRateIcon; private LinearLayout remSleepTimeTextWrapper;
private TextView intensityTotalLabel; private TextView deepSleepTimeText;
private ImageView intensityTotalIcon; private TextView lightSleepTimeText;
private TextView lowestHrText;
private TextView highestHrText;
private TextView movementIntensityText;
private TextView sleepDateText;
private int heartRateMin = 0; private int heartRateMin = 0;
private int heartRateMax = 0; private int heartRateMax = 0;
private float intensityTotal = 0; private float intensityTotal = 0;
@ -135,7 +136,6 @@ public class SleepChartFragment extends AbstractActivityChartFragment<SleepChart
final long lightSleepDuration = calculateLightSleepDuration(sleepSessions); final long lightSleepDuration = calculateLightSleepDuration(sleepSessions);
final long deepSleepDuration = calculateDeepSleepDuration(sleepSessions); final long deepSleepDuration = calculateDeepSleepDuration(sleepSessions);
final long remSleepDuration = calculateRemSleepDuration(sleepSessions); final long remSleepDuration = calculateRemSleepDuration(sleepSessions);
final long totalSeconds = lightSleepDuration + deepSleepDuration + remSleepDuration; final long totalSeconds = lightSleepDuration + deepSleepDuration + remSleepDuration;
final List<PieEntry> entries = new ArrayList<>(); final List<PieEntry> entries = new ArrayList<>();
@ -151,16 +151,14 @@ public class SleepChartFragment extends AbstractActivityChartFragment<SleepChart
entries.add(new PieEntry(remSleepDuration, getActivity().getString(R.string.abstract_chart_fragment_kind_rem_sleep))); entries.add(new PieEntry(remSleepDuration, getActivity().getString(R.string.abstract_chart_fragment_kind_rem_sleep)));
colors.add(getColorFor(ActivityKind.TYPE_REM_SLEEP)); colors.add(getColorFor(ActivityKind.TYPE_REM_SLEEP));
} }
} else {
entries.add(new PieEntry(1));
colors.add(Color.GRAY);
} }
String totalSleep = DateTimeUtils.formatDurationHoursMinutes(totalSeconds, TimeUnit.SECONDS);
PieDataSet set = new PieDataSet(entries, ""); PieDataSet set = new PieDataSet(entries, "");
set.setValueFormatter(new ValueFormatter() { set.setSliceSpace(2f);
@Override
public String getFormattedValue(float value) {
return DateTimeUtils.formatDurationHoursMinutes((long) value, TimeUnit.SECONDS);
}
});
set.setColors(colors); set.setColors(colors);
set.setValueTextColor(DESCRIPTION_COLOR); set.setValueTextColor(DESCRIPTION_COLOR);
set.setValueTextSize(13f); set.setValueTextSize(13f);
@ -168,8 +166,12 @@ public class SleepChartFragment extends AbstractActivityChartFragment<SleepChart
set.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); set.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
data.setDataSet(set); data.setDataSet(set);
String totalSleep = DateTimeUtils.formatDurationHoursMinutes(totalSeconds, TimeUnit.SECONDS);
String totalRem = DateTimeUtils.formatDurationHoursMinutes(remSleepDuration, TimeUnit.SECONDS);
String totalDeep = DateTimeUtils.formatDurationHoursMinutes(deepSleepDuration, TimeUnit.SECONDS);
String totalLight = DateTimeUtils.formatDurationHoursMinutes(lightSleepDuration, TimeUnit.SECONDS);
//setupLegend(pieChart); //setupLegend(pieChart);
return new MySleepChartsData(totalSleep, data, sleepSessions); return new MySleepChartsData(data, sleepSessions, totalSleep, totalRem, totalDeep, totalLight);
} }
private long calculateLightSleepDuration(List<SleepSession> sleepSessions) { private long calculateLightSleepDuration(List<SleepSession> sleepSessions) {
@ -199,16 +201,47 @@ public class SleepChartFragment extends AbstractActivityChartFragment<SleepChart
@Override @Override
protected void updateChartsnUIThread(MyChartsData mcd) { protected void updateChartsnUIThread(MyChartsData mcd) {
MySleepChartsData pieData = mcd.getPieData(); MySleepChartsData pieData = mcd.getPieData();
Date date = new Date((long) this.getTSEnd() * 1000);
String formattedDate = new SimpleDateFormat("E, MMM dd").format(date);
sleepDateText.setText(formattedDate);
pieData.pieData.setDrawValues(false);
mSleepAmountChart.setTouchEnabled(false);
mSleepAmountChart.setCenterTextColor(GBApplication.getTextColor(getContext()));
mSleepAmountChart.setCenterText(pieData.getTotalSleep()); mSleepAmountChart.setCenterText(pieData.getTotalSleep());
if (!pieData.sleepSessions.isEmpty()) {
remSleepTimeText.setText(pieData.getTotalRem());
deepSleepTimeText.setText(pieData.getTotalDeep());
lightSleepTimeText.setText(pieData.getTotalLight());
} else {
remSleepTimeText.setText("-");
deepSleepTimeText.setText("-");
lightSleepTimeText.setText("-");
}
if (!supportsRemSleep(getChartsHost().getDevice())) {
remSleepTimeTextWrapper.setVisibility(View.GONE);
}
mSleepAmountChart.setCenterTextSize(18f);
mSleepAmountChart.setHoleColor(getContext().getResources().getColor(R.color.transparent));
mSleepAmountChart.setData(pieData.getPieData()); mSleepAmountChart.setData(pieData.getPieData());
mActivityChart.setData(null); // workaround for https://github.com/PhilJay/MPAndroidChart/issues/2317
mActivityChart.getXAxis().setValueFormatter(mcd.getChartsData().getXValueFormatter());
mActivityChart.setData(mcd.getChartsData().getData());
mSleepchartInfo.setText(buildYouSleptText(pieData)); mSleepchartInfo.setText(buildYouSleptText(pieData));
mSleepchartInfo.setMovementMethod(new ScrollingMovementMethod()); mSleepchartInfo.setMovementMethod(new ScrollingMovementMethod());
mActivityChart.setData(null); // workaround for https://github.com/PhilJay/MPAndroidChart/issues/2317
mActivityChart.getXAxis().setValueFormatter(mcd.getChartsData().getXValueFormatter());
mActivityChart.getAxisLeft().setDrawLabels(false);
mActivityChart.setData(mcd.getChartsData().getData());
heartRateMin = mcd.getHeartRateAxisMin(); heartRateMin = mcd.getHeartRateAxisMin();
heartRateMax = mcd.getHeartRateAxisMax(); heartRateMax = mcd.getHeartRateAxisMax();
intensityTotal = mcd.getIntensityTotal(); intensityTotal = mcd.getIntensityTotal();
lowestHrText.setText(String.valueOf(heartRateMin != 0 ? heartRateMin : "-"));
highestHrText.setText(String.valueOf(heartRateMax != 0 ? heartRateMax : "-"));
movementIntensityText.setText(intensityTotal != 0 ? new DecimalFormat("###.#").format(intensityTotal) : "-");
mSleepAmountChart.setHoleRadius(75);
mSleepAmountChart.setDrawEntryLabels(false);
mSleepAmountChart.getLegend().setEnabled(false);
if (!CHARTS_SLEEP_RANGE_24H if (!CHARTS_SLEEP_RANGE_24H
&& supportsHeartrate(getChartsHost().getDevice()) && supportsHeartrate(getChartsHost().getDevice())
@ -222,9 +255,6 @@ public class SleepChartFragment extends AbstractActivityChartFragment<SleepChart
hrAverage_line.setLineWidth(0.1f); hrAverage_line.setLineWidth(0.1f);
mActivityChart.getAxisRight().removeAllLimitLines(); mActivityChart.getAxisRight().removeAllLimitLines();
mActivityChart.getAxisRight().addLimitLine(hrAverage_line); mActivityChart.getAxisRight().addLimitLine(hrAverage_line);
DecimalFormat df = new DecimalFormat("###.#");
heartRateAverageLabel.setText(df.format(mcd.getHeartRateAverage()));
intensityTotalLabel.setText(df.format(mcd.getIntensityTotal()));
} }
} }
@ -297,17 +327,14 @@ public class SleepChartFragment extends AbstractActivityChartFragment<SleepChart
private String buildYouSleptText(MySleepChartsData pieData) { private String buildYouSleptText(MySleepChartsData pieData) {
final StringBuilder result = new StringBuilder(); final StringBuilder result = new StringBuilder();
if (pieData.getSleepSessions().isEmpty()) { if (!pieData.getSleepSessions().isEmpty()) {
result.append(getContext().getString(R.string.you_did_not_sleep));
} else {
for (SleepSession sleepSession : pieData.getSleepSessions()) { for (SleepSession sleepSession : pieData.getSleepSessions()) {
if (result.length() > 0) { if (result.length() > 0) {
result.append('\n'); result.append(" | ");
} }
result.append(getContext().getString( String from = DateTimeUtils.timeToString(sleepSession.getSleepStart());
R.string.you_slept, String to = DateTimeUtils.timeToString(sleepSession.getSleepEnd());
DateTimeUtils.timeToString(sleepSession.getSleepStart()), result.append(String.format("%s - %s", from, to));
DateTimeUtils.timeToString(sleepSession.getSleepEnd())));
} }
} }
return result.toString(); return result.toString();
@ -323,33 +350,26 @@ public class SleepChartFragment extends AbstractActivityChartFragment<SleepChart
Bundle savedInstanceState) { Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_sleepchart, container, false); View rootView = inflater.inflate(R.layout.fragment_sleepchart, container, false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
rootView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
getChartsHost().enableSwipeRefresh(scrollY == 0);
});
}
mActivityChart = rootView.findViewById(R.id.sleepchart); mActivityChart = rootView.findViewById(R.id.sleepchart);
mSleepAmountChart = rootView.findViewById(R.id.sleepchart_pie_light_deep); mSleepAmountChart = rootView.findViewById(R.id.sleepchart_pie_light_deep);
mSleepchartInfo = rootView.findViewById(R.id.sleepchart_info); mSleepchartInfo = rootView.findViewById(R.id.sleepchart_info);
heartRateIcon = rootView.findViewById(R.id.heartrate_widget_icon); remSleepTimeText = rootView.findViewById(R.id.sleep_chart_legend_rem_time);
heartRateAverageLabel = rootView.findViewById(R.id.heartrate_widget_label); remSleepTimeTextWrapper = rootView.findViewById(R.id.sleep_chart_legend_rem_time_wrapper);
intensityTotalIcon = rootView.findViewById(R.id.intensity_widget_icon); deepSleepTimeText = rootView.findViewById(R.id.sleep_chart_legend_deep_time);
intensityTotalLabel = rootView.findViewById(R.id.intensity_widget_label); lightSleepTimeText = rootView.findViewById(R.id.sleep_chart_legend_light_time);
lowestHrText = rootView.findViewById(R.id.sleep_hr_lowest);
highestHrText = rootView.findViewById(R.id.sleep_hr_highest);
movementIntensityText = rootView.findViewById(R.id.sleep_movement_intensity);
sleepDateText = rootView.findViewById(R.id.sleep_date);
ConstraintLayout intensityTotalWidgetLayout = rootView.findViewById(R.id.intensity_widget_layout);
ConstraintLayout heartRateWidgetLayout = rootView.findViewById(R.id.heartrate_widget_layout);
mSleepchartInfo.setMaxLines(sleepLinesLimit); mSleepchartInfo.setMaxLines(sleepLinesLimit);
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
DecimalFormat df = new DecimalFormat("###.#");
String detailedDuration = String.format(getString(R.string.charts_min_max_heartrate_popup), heartRateMin, heartRateMax, df.format(intensityTotal));
new ShowDurationDialog(detailedDuration, getContext()).show();
}
};
heartRateWidgetLayout.setOnClickListener(listener);
intensityTotalWidgetLayout.setOnClickListener(listener);
intensityTotalIcon.setOnClickListener(listener);
intensityTotalLabel.setOnClickListener(listener);
setupActivityChart(); setupActivityChart();
setupSleepAmountChart(); setupSleepAmountChart();
@ -438,9 +458,6 @@ public class SleepChartFragment extends AbstractActivityChartFragment<SleepChart
legendEntries.add(remSleepEntry); legendEntries.add(remSleepEntry);
} }
heartRateIcon.setVisibility(View.GONE); //hide heart icon
intensityTotalIcon.setVisibility(View.GONE); //hide intensity icon
if (supportsHeartrate(getChartsHost().getDevice())) { if (supportsHeartrate(getChartsHost().getDevice())) {
LegendEntry hrEntry = new LegendEntry(); LegendEntry hrEntry = new LegendEntry();
hrEntry.label = HEARTRATE_LABEL; hrEntry.label = HEARTRATE_LABEL;
@ -451,8 +468,6 @@ public class SleepChartFragment extends AbstractActivityChartFragment<SleepChart
hrAverageEntry.label = HEARTRATE_AVERAGE_LABEL; hrAverageEntry.label = HEARTRATE_AVERAGE_LABEL;
hrAverageEntry.formColor = Color.RED; hrAverageEntry.formColor = Color.RED;
legendEntries.add(hrAverageEntry); legendEntries.add(hrAverageEntry);
heartRateIcon.setVisibility(View.VISIBLE);
intensityTotalIcon.setVisibility(View.VISIBLE);
} }
} }
chart.getLegend().setCustom(legendEntries); chart.getLegend().setCustom(legendEntries);
@ -474,13 +489,19 @@ public class SleepChartFragment extends AbstractActivityChartFragment<SleepChart
private static class MySleepChartsData extends ChartsData { private static class MySleepChartsData extends ChartsData {
private String totalSleep; private String totalSleep;
private String totalRem;
private String totalDeep;
private String totalLight;
private final PieData pieData; private final PieData pieData;
private final List<SleepSession> sleepSessions; private final List<SleepSession> sleepSessions;
public MySleepChartsData(String totalSleep, PieData pieData, List<SleepSession> sleepSessions) { public MySleepChartsData(PieData pieData, List<SleepSession> sleepSessions, String totalSleep, String totalRem, String totalDeep, String totalLight) {
this.totalSleep = totalSleep;
this.pieData = pieData; this.pieData = pieData;
this.sleepSessions = sleepSessions; this.sleepSessions = sleepSessions;
this.totalSleep = totalSleep;
this.totalRem = totalRem;
this.totalDeep = totalDeep;
this.totalLight = totalLight;
} }
public PieData getPieData() { public PieData getPieData() {
@ -491,6 +512,18 @@ public class SleepChartFragment extends AbstractActivityChartFragment<SleepChart
return totalSleep; return totalSleep;
} }
public CharSequence getTotalRem() {
return totalRem;
}
public CharSequence getTotalDeep() {
return totalDeep;
}
public CharSequence getTotalLight() {
return totalLight;
}
public List<SleepSession> getSleepSessions() { public List<SleepSession> getSleepSessions() {
return sleepSessions; return sleepSessions;
} }

View File

@ -17,14 +17,27 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */ along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.activities.charts; 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.LinearLayout;
import android.widget.TextView;
import com.github.mikephil.charting.charts.Chart; import com.github.mikephil.charting.charts.Chart;
import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.LegendEntry; import com.github.mikephil.charting.components.LegendEntry;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.formatter.ValueFormatter;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.time.DateUtils;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -37,6 +50,122 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils; import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
public class WeekSleepChartFragment extends AbstractWeekChartFragment { public class WeekSleepChartFragment extends AbstractWeekChartFragment {
private TextView remSleepTimeText;
private LinearLayout remSleepTimeTextWrapper;
private TextView deepSleepTimeText;
private TextView lightSleepTimeText;
private TextView sleepDatesText;
private MySleepWeeklyData mySleepWeeklyData;
private MySleepWeeklyData getMySleepWeeklyData(DBHandler db, Calendar day, GBDevice device) {
day = (Calendar) day.clone(); // do not modify the caller's argument
day.add(Calendar.DATE, -TOTAL_DAYS + 1);
TOTAL_DAYS_FOR_AVERAGE=0;
long remWeeklyTotal = 0;
long deepWeeklyTotal = 0;
long lightWeeklyTotal = 0;
for (int counter = 0; counter < TOTAL_DAYS; counter++) {
ActivityAmounts amounts = getActivityAmountsForDay(db, day, device);
if (calculateBalance(amounts) > 0) {
TOTAL_DAYS_FOR_AVERAGE++;
}
float[] totalAmounts = getTotalsForActivityAmounts(amounts);
deepWeeklyTotal += (long) totalAmounts[0];
lightWeeklyTotal += (long) totalAmounts[1];
if (supportsRemSleep(device)) {
remWeeklyTotal += (long) totalAmounts[2];
}
day.add(Calendar.DATE, 1);
}
return new MySleepWeeklyData(remWeeklyTotal, deepWeeklyTotal, lightWeeklyTotal);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mLocale = getResources().getConfiguration().locale;
View rootView = inflater.inflate(R.layout.fragment_weeksleep_chart, container, false);
final int goal = getGoal();
if (goal >= 0) {
mTargetValue = goal;
}
mWeekChart = rootView.findViewById(R.id.weekstepschart);
remSleepTimeText = rootView.findViewById(R.id.sleep_chart_legend_rem_time);
remSleepTimeTextWrapper = rootView.findViewById(R.id.sleep_chart_legend_rem_time_wrapper);
deepSleepTimeText = rootView.findViewById(R.id.sleep_chart_legend_deep_time);
lightSleepTimeText = rootView.findViewById(R.id.sleep_chart_legend_light_time);
sleepDatesText = rootView.findViewById(R.id.sleep_dates);
setupWeekChart();
// refresh immediately instead of use refreshIfVisible(), for perceived performance
refresh();
return rootView;
}
@Override
protected void updateChartsnUIThread(MyChartsData mcd) {
setupLegend(mWeekChart);
//set custom renderer for 30days bar charts
if (GBApplication.getPrefs().getBoolean("charts_range", true)) {
mWeekChart.setRenderer(new AngledLabelsChartRenderer(mWeekChart, mWeekChart.getAnimator(), mWeekChart.getViewPortHandler()));
}
mWeekChart.setData(null); // workaround for https://github.com/PhilJay/MPAndroidChart/issues/2317
mWeekChart.setData(mcd.getWeekBeforeData().getData());
mWeekChart.getXAxis().setValueFormatter(mcd.getWeekBeforeData().getXValueFormatter());
mWeekChart.getBarData().setValueTextSize(14f);
mWeekChart.setScaleEnabled(false);
mWeekChart.setTouchEnabled(false);
if (TOTAL_DAYS_FOR_AVERAGE > 0) {
float avgDeep = Math.abs(this.mySleepWeeklyData.getTotalDeep() / TOTAL_DAYS_FOR_AVERAGE);
deepSleepTimeText.setText(DateTimeUtils.formatDurationHoursMinutes((int) avgDeep, TimeUnit.MINUTES));
float avgLight = Math.abs(this.mySleepWeeklyData.getTotalLight() / TOTAL_DAYS_FOR_AVERAGE);
lightSleepTimeText.setText(DateTimeUtils.formatDurationHoursMinutes((int) avgLight, TimeUnit.MINUTES));
float avgRem = Math.abs(this.mySleepWeeklyData.getTotalRem() / TOTAL_DAYS_FOR_AVERAGE);
remSleepTimeText.setText(DateTimeUtils.formatDurationHoursMinutes((int) avgRem, TimeUnit.MINUTES));
} else {
deepSleepTimeText.setText("-");
lightSleepTimeText.setText("-");
remSleepTimeText.setText("-");
}
if (!supportsRemSleep(getChartsHost().getDevice())) {
remSleepTimeTextWrapper.setVisibility(View.GONE);
}
Date to = new Date((long) this.getTSEnd() * 1000);
Date from = DateUtils.addDays(to,-(TOTAL_DAYS - 1));
String toFormattedDate = new SimpleDateFormat("E, MMM dd").format(to);
String fromFormattedDate = new SimpleDateFormat("E, MMM dd").format(from);
sleepDatesText.setText(fromFormattedDate + " - " + toFormattedDate);
}
@Override
protected MyChartsData refreshInBackground(ChartsHost chartsHost, DBHandler db, GBDevice device) {
Calendar day = Calendar.getInstance();
day.setTime(chartsHost.getEndDate());
//NB: we could have omitted the day, but this way we can move things to the past easily
WeekChartsData<BarData> weekBeforeData = refreshWeekBeforeData(db, mWeekChart, day, device);
mySleepWeeklyData = getMySleepWeeklyData(db, day, device);
return new MyChartsData(null, weekBeforeData);
}
@Override
protected void renderCharts() {
mWeekChart.invalidate();
}
@Override @Override
public String getTitle() { public String getTitle() {
if (GBApplication.getPrefs().getBoolean("charts_range", true)) { if (GBApplication.getPrefs().getBoolean("charts_range", true)) {
@ -205,4 +334,33 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment {
return getHM((long)value); return getHM((long)value);
} }
private static class MySleepWeeklyData {
private long totalRem;
private long totalDeep;
private long totalLight;
private int totalDaysForAverage;
public MySleepWeeklyData(long totalRem, long totalDeep, long totalLight) {
this.totalDeep = totalDeep;
this.totalRem = totalRem;
this.totalLight = totalLight;
this.totalDaysForAverage = 0;
}
public long getTotalRem() {
return this.totalRem;
}
public long getTotalDeep() {
return this.totalDeep;
}
public long getTotalLight() {
return this.totalLight;
}
public int getTotalDaysForAverage() {
return this.totalDaysForAverage;
}
}
} }

View File

@ -42,9 +42,9 @@ public abstract class AbstractDashboardWidget extends Fragment {
protected @ColorInt int color_worn = Color.rgb(128, 128, 128); protected @ColorInt int color_worn = Color.rgb(128, 128, 128);
protected @ColorInt int color_activity = Color.GREEN; protected @ColorInt int color_activity = Color.GREEN;
protected @ColorInt int color_exercise = Color.rgb(255, 128, 0); protected @ColorInt int color_exercise = Color.rgb(255, 128, 0);
protected @ColorInt int color_deep_sleep = Color.BLUE; protected @ColorInt int color_deep_sleep = Color.rgb(0, 84, 163);
protected @ColorInt int color_light_sleep = Color.rgb(150, 150, 255); protected @ColorInt int color_light_sleep = Color.rgb(7, 158, 243);
protected @ColorInt int color_rem_sleep = Color.rgb(182, 191, 255); protected @ColorInt int color_rem_sleep = Color.rgb(228, 39, 199);
protected @ColorInt int color_distance = Color.BLUE; protected @ColorInt int color_distance = Color.BLUE;
protected @ColorInt int color_active_time = Color.rgb(170, 0, 255); protected @ColorInt int color_active_time = Color.rgb(170, 0, 255);

View File

@ -54,10 +54,11 @@ public class ActivityKind {
public static final int TYPE_HIKING = 0x00400000; public static final int TYPE_HIKING = 0x00400000;
public static final int TYPE_CLIMBING = 0x00800000; public static final int TYPE_CLIMBING = 0x00800000;
public static final int TYPE_REM_SLEEP = 0x01000000; public static final int TYPE_REM_SLEEP = 0x01000000;
public static final int TYPE_AWAKE_SLEEP = 0x02000000;
private static final int TYPES_COUNT = 26; private static final int TYPES_COUNT = 26;
public static final int TYPE_SLEEP = TYPE_LIGHT_SLEEP | TYPE_DEEP_SLEEP | TYPE_REM_SLEEP; public static final int TYPE_SLEEP = TYPE_LIGHT_SLEEP | TYPE_DEEP_SLEEP | TYPE_REM_SLEEP | TYPE_AWAKE_SLEEP;
public static final int TYPE_ALL = TYPE_ACTIVITY | TYPE_SLEEP | TYPE_NOT_WORN; public static final int TYPE_ALL = TYPE_ACTIVITY | TYPE_SLEEP | TYPE_NOT_WORN;
public static int[] mapToDBActivityTypes(int types, SampleProvider provider) { public static int[] mapToDBActivityTypes(int types, SampleProvider provider) {

View File

@ -1,53 +1,266 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:orientation="vertical"
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.charts.ActivityChartsActivity$PlaceholderFragment">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:id="@+id/sleepchart_info" android:id="@+id/sleep_date"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="0" android:layout_marginTop="15dp"
android:scrollbarAlwaysDrawVerticalTrack="true" android:gravity="center"
android:scrollbarFadeDuration="0" android:textSize="20sp" />
android:scrollbars="vertical" />
<TextView
android:id="@+id/sleepchart_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="-"
android:textSize="12sp" />
<com.github.mikephil.charting.charts.PieChart <com.github.mikephil.charting.charts.PieChart
android:id="@+id/sleepchart_pie_light_deep" android:id="@+id/sleepchart_pie_light_deep"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="200dp"
android:layout_marginTop="15dp"
android:layout_weight="2" /> android:layout_weight="2" />
<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="5dp"
android:background="@color/chart_deep_sleep_dark" />
<TextView
android:id="@+id/sleep_chart_legend_deep_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_marginTop="20dip"
android:text="@string/stats_empty_value"
android:textSize="20sp" />
<TextView
android:id="@+id/sleep_chart_legend_deep_legend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="@string/sleep_colored_stats_deep"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
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="5dp"
android:background="@color/chart_light_sleep_dark" />
<TextView
android:id="@+id/sleep_chart_legend_light_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_marginTop="20dip"
android:text="@string/stats_empty_value"
android:textSize="20sp" />
<TextView
android:id="@+id/sleep_chart_legend_light_legend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:text="@string/sleep_colored_stats_light"
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="5dp"
android:background="@color/chart_rem_sleep_dark" />
<TextView
android:id="@+id/sleep_chart_legend_rem_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_marginTop="20dip"
android:gravity="center"
android:text="@string/stats_empty_value"
android:textSize="20sp" />
<TextView
android:id="@+id/sleep_chart_legend_rem_legend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:gravity="center"
android:text="@string/sleep_colored_stats_rem"
android:textSize="12sp" />
</LinearLayout>
</TableRow>
</TableLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="@color/secondarytext" />
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_columnWeight="1"
android:gravity="center"
android:orientation="vertical"
android:paddingHorizontal="5dip">
<TextView
android:id="@+id/sleep_hr_lowest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dip"
android:gravity="center"
android:text="@string/stats_empty_value"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/stats_lowest_hr"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_columnWeight="1"
android:gravity="center"
android:orientation="vertical"
android:paddingHorizontal="5dip">
<TextView
android:id="@+id/sleep_hr_highest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dip"
android:gravity="center"
android:text="@string/stats_empty_value"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/stats_highest_hr"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_columnWeight="1"
android:gravity="center"
android:orientation="vertical"
android:paddingHorizontal="5dip">
<TextView
android:id="@+id/sleep_movement_intensity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dip"
android:gravity="center"
android:text="@string/stats_empty_value"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/movement_intensity"
android:textSize="12sp" />
</LinearLayout>
</GridLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:layout_marginTop="25dp"
android:layout_marginBottom="25dp"
android:background="@color/secondarytext" />
<com.github.mikephil.charting.charts.LineChart <com.github.mikephil.charting.charts.LineChart
android:id="@+id/sleepchart" android:id="@+id/sleepchart"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="300dp"
android:layout_weight="2" /> android:layout_marginBottom="25dp"
android:layout_weight="4" />
</LinearLayout> </LinearLayout>
</ScrollView>
<include
layout="@layout/layout_widget_heartrate_average"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_gravity="top|end" />
<include
layout="@layout/layout_widget_intensity_total"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_marginTop="50dp"
android:layout_marginEnd="-1dp"
android:layout_gravity="top|end" />
</RelativeLayout>

View File

@ -0,0 +1,155 @@
<ScrollView 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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.charts.ActivityChartsActivity$PlaceholderFragment">
<TextView
android:id="@+id/sleep_dates"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="20sp"
android:layout_marginTop="15dp"
/>
<TableLayout
android:layout_weight="3"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:shrinkColumns="*"
android:stretchColumns="*"
android:layout_marginBottom="20dp"
android:layout_marginTop="5dp"
>
<TableRow
android:id="@+id/tableRow1"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:weightSum="2"
>
<LinearLayout
android:orientation="vertical"
android:paddingTop="20dip"
android:paddingLeft="20dip"
android:paddingRight="20dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_width="0dp"
>
<View
android:layout_width="fill_parent"
android:layout_height="5dp"
android:background="@color/chart_deep_sleep_dark"/>
<TextView
android:layout_marginTop="20dip"
android:id="@+id/sleep_chart_legend_deep_time"
android:text="@string/stats_empty_value"
android:textSize="20sp"
android:layout_gravity="start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/sleep_chart_legend_deep_legend"
android:text="@string/sleep_colored_stats_deep_avg"
android:textSize="12sp"
android:layout_gravity="start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:paddingTop="20dip"
android:paddingLeft="20dip"
android:paddingRight="20dip"
android:gravity="center"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_width="0dp"
>
<View
android:layout_width="fill_parent"
android:layout_height="5dp"
android:background="@color/chart_light_sleep_dark"/>
<TextView
android:layout_marginTop="20dip"
android:id="@+id/sleep_chart_legend_light_time"
android:text="@string/stats_empty_value"
android:textSize="20sp"
android:layout_gravity="start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/sleep_chart_legend_light_legend"
android:text="@string/sleep_colored_stats_light_avg"
android:textSize="12sp"
android:layout_gravity="start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
</TableRow>
<TableRow
android:id="@+id/tableRow2"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:weightSum="2"
>
<LinearLayout
android:id="@+id/sleep_chart_legend_rem_time_wrapper"
android:orientation="vertical"
android:paddingTop="20dip"
android:paddingLeft="20dip"
android:paddingRight="20dip"
android:gravity="center"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_width="0dp"
>
<View
android:layout_width="fill_parent"
android:layout_height="5dp"
android:background="@color/chart_rem_sleep_dark"/>
<TextView
android:layout_marginTop="20dip"
android:id="@+id/sleep_chart_legend_rem_time"
android:text="@string/stats_empty_value"
android:textSize="20sp"
android:layout_gravity="start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"/>
<TextView
android:id="@+id/sleep_chart_legend_rem_legend"
android:text="@string/sleep_colored_stats_rem_avg"
android:textSize="12sp"
android:layout_gravity="start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"/>
</LinearLayout>
</TableRow>
</TableLayout>
<com.github.mikephil.charting.charts.BarChart
android:id="@+id/weekstepschart"
android:layout_width="fill_parent"
android:layout_height="350dp"
/>
</LinearLayout>
</ScrollView>

View File

@ -21,14 +21,15 @@
<color name="chart_heartrate" type="color">#ffab40</color> <color name="chart_heartrate" type="color">#ffab40</color>
<color name="chart_heartrate_alternative" type="color">#8B0000</color> <color name="chart_heartrate_alternative" type="color">#8B0000</color>
<color name="chart_heartrate_fill" type="color">#fadab1</color> <color name="chart_heartrate_fill" type="color">#fadab1</color>
<color name="chart_deep_sleep_light" type="color">#0071b7</color>
<color name="chart_deep_sleep_dark" type="color">#4c5aff</color>
<color name="chart_light_sleep_light" type="color">#46acea</color> <color name="chart_deep_sleep_light" type="color">#0054a3</color>
<color name="chart_light_sleep_dark" type="color">#b6bfff</color> <color name="chart_deep_sleep_dark" type="color">#0054a3</color>
<color name="chart_rem_sleep_light" type="color">#b6bfff</color> <color name="chart_light_sleep_light" type="color">#079ef3</color>
<color name="chart_rem_sleep_dark" type="color">#46acea</color> <color name="chart_light_sleep_dark" type="color">#079ef3</color>
<color name="chart_rem_sleep_light" type="color">#e427c7</color>
<color name="chart_rem_sleep_dark" type="color">#e427c7</color>
<color name="chart_activity_light" type="color">#60bd6d</color> <color name="chart_activity_light" type="color">#60bd6d</color>
<color name="chart_activity_dark" type="color">#59b22c</color> <color name="chart_activity_dark" type="color">#59b22c</color>
@ -39,6 +40,8 @@
<color name="alternate_row_background_light">#FFEDEDED</color> <color name="alternate_row_background_light">#FFEDEDED</color>
<color name="alternate_row_background_dark">#545254</color> <color name="alternate_row_background_dark">#545254</color>
<color name="transparent">#00000000</color>
<drawable name="selected">@color/accent</drawable> <drawable name="selected">@color/accent</drawable>
</resources> </resources>

View File

@ -951,8 +951,18 @@
<string name="abstract_chart_fragment_kind_light_sleep">Light sleep</string> <string name="abstract_chart_fragment_kind_light_sleep">Light sleep</string>
<string name="abstract_chart_fragment_kind_deep_sleep">Deep sleep</string> <string name="abstract_chart_fragment_kind_deep_sleep">Deep sleep</string>
<string name="abstract_chart_fragment_kind_rem_sleep">REM sleep</string> <string name="abstract_chart_fragment_kind_rem_sleep">REM sleep</string>
<string name="abstract_chart_fragment_kind_awake_sleep">Awake sleep</string>
<string name="abstract_chart_fragment_kind_not_worn">Not worn</string> <string name="abstract_chart_fragment_kind_not_worn">Not worn</string>
<string name="you_slept">You slept from %1$s to %2$s</string> <string name="sleep_colored_stats_deep">Deep</string>
<string name="sleep_colored_stats_light">Light</string>
<string name="sleep_colored_stats_rem">REM</string>
<string name="sleep_colored_stats_deep_avg">Deep AVG</string>
<string name="sleep_colored_stats_light_avg">Light AVG</string>
<string name="sleep_colored_stats_rem_avg">REM AVG</string>
<string name="stats_empty_value">-</string>
<string name="stats_lowest_hr">Lowest HR</string>
<string name="stats_highest_hr">Highest HR</string>
<string name="you_slept">%1$s - %2$s</string>
<string name="you_did_not_sleep">You did not sleep</string> <string name="you_did_not_sleep">You did not sleep</string>
<string name="charts_min_max_heartrate_popup">Lowest heart rate: %1$d \nHighest heart rate: %2$d \nMovement intensity: %3$s</string> <string name="charts_min_max_heartrate_popup">Lowest heart rate: %1$d \nHighest heart rate: %2$d \nMovement intensity: %3$s</string>
<string name="device_not_connected">Not connected.</string> <string name="device_not_connected">Not connected.</string>