mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-19 00:19:25 +01:00
Add combined goals widget
This commit is contained in:
parent
cb77ca0495
commit
c5ed03962c
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2023 Arjan Schrijver
|
||||
/* Copyright (C) 2023-2024 Arjan Schrijver
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
@ -43,6 +43,7 @@ import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.AbstractDashboardWidget;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardActiveTimeWidget;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardDistanceWidget;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardGoalsWidget;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardSleepWidget;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardStepsWidget;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardTodayWidget;
|
||||
@ -57,6 +58,7 @@ public class DashboardFragment extends Fragment {
|
||||
private TextView arrowRight;
|
||||
private GridLayout gridLayout;
|
||||
private DashboardTodayWidget todayWidget;
|
||||
private DashboardGoalsWidget goalsWidget;
|
||||
private DashboardStepsWidget stepsWidget;
|
||||
private DashboardDistanceWidget distanceWidget;
|
||||
private DashboardActiveTimeWidget activeTimeWidget;
|
||||
@ -85,6 +87,7 @@ public class DashboardFragment extends Fragment {
|
||||
});
|
||||
|
||||
todayWidget = null;
|
||||
goalsWidget = null;
|
||||
stepsWidget = null;
|
||||
distanceWidget = null;
|
||||
activeTimeWidget = null;
|
||||
@ -116,6 +119,7 @@ public class DashboardFragment extends Fragment {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
gridLayout.removeAllViews();
|
||||
todayWidget = null;
|
||||
goalsWidget = null;
|
||||
stepsWidget = null;
|
||||
distanceWidget = null;
|
||||
activeTimeWidget = null;
|
||||
@ -150,6 +154,14 @@ public class DashboardFragment extends Fragment {
|
||||
todayWidget.setTimespan(timeFrom, timeTo);
|
||||
}
|
||||
}
|
||||
if (prefs.getBoolean("dashboard_widget_goals_enabled", true)) {
|
||||
if (goalsWidget == null) {
|
||||
goalsWidget = DashboardGoalsWidget.newInstance(timeFrom, timeTo);
|
||||
createWidget(goalsWidget, cardsEnabled, 2);
|
||||
} else {
|
||||
goalsWidget.setTimespan(timeFrom, timeTo);
|
||||
}
|
||||
}
|
||||
if (prefs.getBoolean("dashboard_widget_steps_enabled", true)) {
|
||||
if (stepsWidget == null) {
|
||||
stepsWidget = DashboardStepsWidget.newInstance(timeFrom, timeTo);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2023 Arjan Schrijver
|
||||
/* Copyright (C) 2023-2024 Arjan Schrijver
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
@ -32,6 +32,7 @@ import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.charts.StepAnalysis;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||
@ -40,6 +41,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DailyTotals;
|
||||
|
||||
public abstract class AbstractDashboardWidget extends Fragment {
|
||||
@ -51,6 +53,14 @@ public abstract class AbstractDashboardWidget extends Fragment {
|
||||
protected int timeFrom;
|
||||
protected int timeTo;
|
||||
|
||||
protected @ColorInt int color_not_worn = Color.argb(128, 0, 0, 0);
|
||||
protected @ColorInt int color_worn = Color.argb(128, 128, 128, 128);
|
||||
protected @ColorInt int color_activity = Color.GREEN;
|
||||
protected @ColorInt int color_deep_sleep = Color.BLUE;
|
||||
protected @ColorInt int color_light_sleep = Color.rgb(150, 150, 255);
|
||||
protected @ColorInt int color_distance = Color.BLUE;
|
||||
protected @ColorInt int color_active_time = Color.rgb(170, 0, 255);
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@ -136,4 +146,102 @@ public abstract class AbstractDashboardWidget extends Fragment {
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
protected int getStepsTotal() {
|
||||
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
|
||||
int totalSteps = 0;
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
for (GBDevice dev : devices) {
|
||||
if (dev.getDeviceCoordinator().supportsActivityTracking()) {
|
||||
totalSteps += getSteps(dev, dbHandler);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Could not calculate total amount of steps: ", e);
|
||||
}
|
||||
return totalSteps;
|
||||
}
|
||||
|
||||
protected float getStepsGoalFactor() {
|
||||
ActivityUser activityUser = new ActivityUser();
|
||||
float stepsGoal = activityUser.getStepsGoal();
|
||||
float goalFactor = getStepsTotal() / stepsGoal;
|
||||
if (goalFactor > 1) goalFactor = 1;
|
||||
|
||||
return goalFactor;
|
||||
}
|
||||
|
||||
protected float getDistanceTotal() {
|
||||
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
|
||||
long totalSteps = 0;
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
for (GBDevice dev : devices) {
|
||||
if (dev.getDeviceCoordinator().supportsActivityTracking()) {
|
||||
totalSteps += getSteps(dev, dbHandler);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Could not calculate total distance: ", e);
|
||||
}
|
||||
ActivityUser activityUser = new ActivityUser();
|
||||
int stepLength = activityUser.getStepLengthCm();
|
||||
return totalSteps * stepLength * 0.01f;
|
||||
}
|
||||
|
||||
protected float getDistanceGoalFactor() {
|
||||
ActivityUser activityUser = new ActivityUser();
|
||||
int distanceGoal = activityUser.getDistanceGoalMeters();
|
||||
float goalFactor = getDistanceTotal() / distanceGoal;
|
||||
if (goalFactor > 1) goalFactor = 1;
|
||||
|
||||
return goalFactor;
|
||||
}
|
||||
|
||||
protected long getActiveMinutesTotal() {
|
||||
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
|
||||
long totalActiveMinutes = 0;
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
for (GBDevice dev : devices) {
|
||||
if (dev.getDeviceCoordinator().supportsActivityTracking()) {
|
||||
totalActiveMinutes += getActiveMinutes(dev, dbHandler, timeFrom, timeTo);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Could not calculate total amount of activity: ", e);
|
||||
}
|
||||
return totalActiveMinutes;
|
||||
}
|
||||
|
||||
protected float getActiveMinutesGoalFactor() {
|
||||
ActivityUser activityUser = new ActivityUser();
|
||||
int activeTimeGoal = activityUser.getActiveTimeGoalMinutes();
|
||||
float goalFactor = (float) getActiveMinutesTotal() / activeTimeGoal;
|
||||
if (goalFactor > 1) goalFactor = 1;
|
||||
|
||||
return goalFactor;
|
||||
}
|
||||
|
||||
protected long getSleepMinutesTotal() {
|
||||
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
|
||||
long totalSleepMinutes = 0;
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
for (GBDevice dev : devices) {
|
||||
if (dev.getDeviceCoordinator().supportsActivityTracking()) {
|
||||
totalSleepMinutes += getSleep(dev, dbHandler);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Could not calculate total amount of sleep: ", e);
|
||||
}
|
||||
return totalSleepMinutes;
|
||||
}
|
||||
|
||||
protected float getSleepMinutesGoalFactor() {
|
||||
ActivityUser activityUser = new ActivityUser();
|
||||
int sleepMinutesGoal = activityUser.getSleepDurationGoal() * 60;
|
||||
float goalFactor = (float) getSleepMinutesTotal() / sleepMinutesGoal;
|
||||
if (goalFactor > 1) goalFactor = 1;
|
||||
|
||||
return goalFactor;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2023 Arjan Schrijver
|
||||
/* Copyright (C) 2023-2024 Arjan Schrijver
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@ -27,13 +26,7 @@ import android.widget.TextView;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||
|
||||
/**
|
||||
* A simple {@link AbstractDashboardWidget} subclass.
|
||||
@ -86,26 +79,12 @@ public class DashboardActiveTimeWidget extends AbstractDashboardWidget {
|
||||
@Override
|
||||
protected void fillData() {
|
||||
// Update text representation
|
||||
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
|
||||
long totalActiveMinutes = 0;
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
for (GBDevice dev : devices) {
|
||||
if (dev.getDeviceCoordinator().supportsActivityTracking()) {
|
||||
totalActiveMinutes += getActiveMinutes(dev, dbHandler, timeFrom, timeTo);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Could not calculate total amount of activity: ", e);
|
||||
}
|
||||
long totalActiveMinutes = getActiveMinutesTotal();
|
||||
String activeHours = String.format("%d", (int) Math.floor(totalActiveMinutes / 60f));
|
||||
String activeMinutes = String.format("%02d", (int) (totalActiveMinutes % 60f));
|
||||
activeTime.setText(activeHours + ":" + activeMinutes);
|
||||
|
||||
// Draw gauge
|
||||
ActivityUser activityUser = new ActivityUser();
|
||||
int activeTimeGoal = activityUser.getActiveTimeGoalMinutes();
|
||||
float goalFactor = (float) totalActiveMinutes / activeTimeGoal;
|
||||
if (goalFactor > 1) goalFactor = 1;
|
||||
activeTimeGauge.setImageBitmap(drawGauge(200, 15, Color.rgb(170, 0, 255), goalFactor));
|
||||
activeTimeGauge.setImageBitmap(drawGauge(200, 15, color_active_time, getActiveMinutesGoalFactor()));
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2023 Arjan Schrijver
|
||||
/* Copyright (C) 2023-2024 Arjan Schrijver
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@ -27,13 +26,7 @@ import android.widget.TextView;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FormatUtils;
|
||||
|
||||
/**
|
||||
@ -87,27 +80,10 @@ public class DashboardDistanceWidget extends AbstractDashboardWidget {
|
||||
@Override
|
||||
protected void fillData() {
|
||||
// Update text representation
|
||||
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
|
||||
long totalSteps = 0;
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
for (GBDevice dev : devices) {
|
||||
if (dev.getDeviceCoordinator().supportsActivityTracking()) {
|
||||
totalSteps += getSteps(dev, dbHandler);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Could not calculate total distance: ", e);
|
||||
}
|
||||
ActivityUser activityUser = new ActivityUser();
|
||||
int stepLength = activityUser.getStepLengthCm();
|
||||
float distanceMeters = totalSteps * stepLength * 0.01f;
|
||||
String distanceFormatted = FormatUtils.getFormattedDistanceLabel(distanceMeters);
|
||||
String distanceFormatted = FormatUtils.getFormattedDistanceLabel(getDistanceTotal());
|
||||
distanceText.setText(distanceFormatted);
|
||||
|
||||
// Draw gauge
|
||||
int distanceGoal = activityUser.getDistanceGoalMeters();
|
||||
float goalFactor = distanceMeters / distanceGoal;
|
||||
if (goalFactor > 1) goalFactor = 1;
|
||||
distanceGauge.setImageBitmap(drawGauge(200, 15, Color.GREEN, goalFactor));
|
||||
distanceGauge.setImageBitmap(drawGauge(200, 15, color_distance, getDistanceGoalFactor()));
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
/* Copyright (C) 2023-2024 Arjan Schrijver
|
||||
|
||||
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 <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Bundle;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
|
||||
/**
|
||||
* A simple {@link AbstractDashboardWidget} subclass.
|
||||
* Use the {@link DashboardGoalsWidget#newInstance} factory method to
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
public class DashboardGoalsWidget extends AbstractDashboardWidget {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DashboardGoalsWidget.class);
|
||||
private ImageView goalsChart;
|
||||
|
||||
public DashboardGoalsWidget() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this factory method to create a new instance of
|
||||
* this fragment using the provided parameters.
|
||||
*
|
||||
* @param timeFrom Start time in seconds since Unix epoch.
|
||||
* @param timeTo End time in seconds since Unix epoch.
|
||||
* @return A new instance of fragment DashboardGoalsWidget.
|
||||
*/
|
||||
public static DashboardGoalsWidget newInstance(int timeFrom, int timeTo) {
|
||||
DashboardGoalsWidget fragment = new DashboardGoalsWidget();
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(ARG_TIME_FROM, timeFrom);
|
||||
args.putInt(ARG_TIME_TO, timeTo);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View todayView = inflater.inflate(R.layout.dashboard_widget_goals, container, false);
|
||||
goalsChart = todayView.findViewById(R.id.dashboard_goals_chart);
|
||||
|
||||
// Initialize legend
|
||||
TextView legend = todayView.findViewById(R.id.dashboard_goals_legend);
|
||||
SpannableString l_steps = new SpannableString("■ " + getString(R.string.steps));
|
||||
l_steps.setSpan(new ForegroundColorSpan(color_activity), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
SpannableString l_distance = new SpannableString("■ " + getString(R.string.distance));
|
||||
l_distance.setSpan(new ForegroundColorSpan(color_distance), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
SpannableString l_active_time = new SpannableString("■ " + getString(R.string.activity_list_summary_active_time));
|
||||
l_active_time.setSpan(new ForegroundColorSpan(color_active_time), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
SpannableString l_sleep = new SpannableString("■ " + getString(R.string.menuitem_sleep));
|
||||
l_sleep.setSpan(new ForegroundColorSpan(color_light_sleep), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
SpannableStringBuilder legendBuilder = new SpannableStringBuilder();
|
||||
legend.setText(legendBuilder.append(l_steps).append(" ").append(l_distance).append("\n").append(l_sleep).append(" ").append(l_active_time));
|
||||
|
||||
fillData();
|
||||
|
||||
return todayView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (goalsChart != null) fillData();
|
||||
}
|
||||
|
||||
protected void fillData() {
|
||||
int width = 230;
|
||||
int height = 230;
|
||||
int barWidth = 10;
|
||||
int barMargin = (int) Math.ceil(barWidth / 2f);
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
Paint paint = new Paint();
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeCap(Paint.Cap.ROUND);
|
||||
paint.setStrokeWidth(barWidth);
|
||||
|
||||
paint.setColor(color_activity);
|
||||
canvas.drawArc(barMargin, barMargin, width - barMargin, height - barMargin, 270, 360 * getStepsGoalFactor(), false, paint);
|
||||
|
||||
barMargin += barWidth * 1.5;
|
||||
paint.setColor(color_distance);
|
||||
canvas.drawArc(barMargin, barMargin, width - barMargin, height - barMargin, 270, 360 * getDistanceGoalFactor(), false, paint);
|
||||
|
||||
barMargin += barWidth * 1.5;
|
||||
paint.setColor(color_active_time);
|
||||
canvas.drawArc(barMargin, barMargin, width - barMargin, height - barMargin, 270, 360 * getActiveMinutesGoalFactor(), false, paint);
|
||||
|
||||
barMargin += barWidth * 1.5;
|
||||
paint.setColor(color_deep_sleep);
|
||||
canvas.drawArc(barMargin, barMargin, width - barMargin, height - barMargin, 270, 360 * getSleepMinutesGoalFactor(), false, paint);
|
||||
|
||||
goalsChart.setImageBitmap(bitmap);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2023 Arjan Schrijver
|
||||
/* Copyright (C) 2023-2024 Arjan Schrijver
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@ -27,13 +26,7 @@ import android.widget.TextView;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||
|
||||
/**
|
||||
* A simple {@link AbstractDashboardWidget} subclass.
|
||||
@ -86,26 +79,12 @@ public class DashboardSleepWidget extends AbstractDashboardWidget {
|
||||
@Override
|
||||
protected void fillData() {
|
||||
// Update text representation
|
||||
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
|
||||
long totalSleepMinutes = 0;
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
for (GBDevice dev : devices) {
|
||||
if (dev.getDeviceCoordinator().supportsActivityTracking()) {
|
||||
totalSleepMinutes += getSleep(dev, dbHandler);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Could not calculate total amount of sleep: ", e);
|
||||
}
|
||||
long totalSleepMinutes = getSleepMinutesTotal();
|
||||
String sleepHours = String.format("%d", (int) Math.floor(totalSleepMinutes / 60f));
|
||||
String sleepMinutes = String.format("%02d", (int) (totalSleepMinutes % 60f));
|
||||
sleepAmount.setText(sleepHours + ":" + sleepMinutes);
|
||||
|
||||
// Draw gauge
|
||||
ActivityUser activityUser = new ActivityUser();
|
||||
int sleepMinutesGoal = activityUser.getSleepDurationGoal() * 60;
|
||||
float goalFactor = (float) totalSleepMinutes / sleepMinutesGoal;
|
||||
if (goalFactor > 1) goalFactor = 1;
|
||||
sleepGauge.setImageBitmap(drawGauge(200, 15, Color.rgb(170, 0, 255), goalFactor));
|
||||
sleepGauge.setImageBitmap(drawGauge(200, 15, color_light_sleep, getSleepMinutesGoalFactor()));
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2023 Arjan Schrijver
|
||||
/* Copyright (C) 2023-2024 Arjan Schrijver
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@ -27,13 +26,7 @@ import android.widget.TextView;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||
|
||||
/**
|
||||
* A simple {@link AbstractDashboardWidget} subclass.
|
||||
@ -83,24 +76,9 @@ public class DashboardStepsWidget extends AbstractDashboardWidget {
|
||||
|
||||
protected void fillData() {
|
||||
// Update text representation
|
||||
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
|
||||
int totalSteps = 0;
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
for (GBDevice dev : devices) {
|
||||
if (dev.getDeviceCoordinator().supportsActivityTracking()) {
|
||||
totalSteps += getSteps(dev, dbHandler);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Could not calculate total amount of steps: ", e);
|
||||
}
|
||||
stepsCount.setText(String.valueOf(totalSteps));
|
||||
stepsCount.setText(String.valueOf(getStepsTotal()));
|
||||
|
||||
// Draw gauge
|
||||
ActivityUser activityUser = new ActivityUser();
|
||||
float stepsGoal = activityUser.getStepsGoal();
|
||||
float goalFactor = totalSteps / stepsGoal;
|
||||
if (goalFactor > 1) goalFactor = 1;
|
||||
stepsGauge.setImageBitmap(drawGauge(200, 15, Color.BLUE, goalFactor));
|
||||
stepsGauge.setImageBitmap(drawGauge(200, 15, color_activity, getStepsGoalFactor()));
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2023 Arjan Schrijver
|
||||
/* Copyright (C) 2023-2024 Arjan Schrijver
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
@ -114,13 +114,13 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
|
||||
// Initialize legend
|
||||
TextView legend = todayView.findViewById(R.id.dashboard_piechart_legend);
|
||||
SpannableString l_not_worn = new SpannableString("■ " + getString(R.string.abstract_chart_fragment_kind_not_worn));
|
||||
l_not_worn.setSpan(new ForegroundColorSpan(Color.rgb(0, 0, 0)), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
l_not_worn.setSpan(new ForegroundColorSpan(color_not_worn), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
SpannableString l_activity = new SpannableString("■ " + getString(R.string.activity_type_activity));
|
||||
l_activity.setSpan(new ForegroundColorSpan(Color.rgb(0, 255, 0)), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
l_activity.setSpan(new ForegroundColorSpan(color_activity), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
SpannableString l_deep_sleep = new SpannableString("■ " + getString(R.string.activity_type_deep_sleep));
|
||||
l_deep_sleep.setSpan(new ForegroundColorSpan(Color.rgb(0, 0, 255)), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
l_deep_sleep.setSpan(new ForegroundColorSpan(color_deep_sleep), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
SpannableString l_light_sleep = new SpannableString("■ " + getString(R.string.activity_type_light_sleep));
|
||||
l_light_sleep.setSpan(new ForegroundColorSpan(Color.rgb(150, 150, 255)), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
l_light_sleep.setSpan(new ForegroundColorSpan(color_light_sleep), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
SpannableStringBuilder legendBuilder = new SpannableStringBuilder();
|
||||
legend.setText(legendBuilder.append(l_not_worn).append(" ").append(l_activity).append("\n").append(l_light_sleep).append(" ").append(l_deep_sleep));
|
||||
|
||||
@ -143,7 +143,7 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
|
||||
PieDataSet scaleDataSet = new PieDataSet(scaleEntries, "Time scale");
|
||||
scaleDataSet.setSliceSpace(0f);
|
||||
scaleDataSet.setDrawValues(false);
|
||||
scaleDataSet.setColor(Color.argb(0,0,0,0));
|
||||
scaleDataSet.setColor(Color.TRANSPARENT);
|
||||
PieData scaleData = new PieData(scaleDataSet);
|
||||
scale.setData(scaleData);
|
||||
|
||||
@ -265,24 +265,24 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
|
||||
// Draw inactive slice
|
||||
if (activity.timeFrom > secondIndex) {
|
||||
entries.add(new PieEntry(activity.timeFrom - secondIndex, "Inactive"));
|
||||
colors.add(Color.rgb(128, 128, 128));
|
||||
colors.add(color_worn);
|
||||
}
|
||||
// Draw activity slices
|
||||
if (activity.activityKind == ActivityKind.TYPE_NOT_WORN) {
|
||||
entries.add(new PieEntry(activity.timeTo - activity.timeFrom, "Not worn"));
|
||||
colors.add(Color.rgb(0, 0, 0));
|
||||
colors.add(color_not_worn);
|
||||
secondIndex = activity.timeTo;
|
||||
} else if (activity.activityKind == ActivityKind.TYPE_LIGHT_SLEEP || activity.activityKind == ActivityKind.TYPE_SLEEP) {
|
||||
entries.add(new PieEntry(activity.timeTo - activity.timeFrom, "Light sleep"));
|
||||
colors.add(Color.rgb(150, 150, 255));
|
||||
colors.add(color_light_sleep);
|
||||
secondIndex = activity.timeTo;
|
||||
} else if (activity.activityKind == ActivityKind.TYPE_DEEP_SLEEP) {
|
||||
entries.add(new PieEntry(activity.timeTo - activity.timeFrom, "Deep sleep"));
|
||||
colors.add(Color.rgb(0, 0, 255));
|
||||
colors.add(color_deep_sleep);
|
||||
secondIndex = activity.timeTo;
|
||||
} else {
|
||||
entries.add(new PieEntry(activity.timeTo - activity.timeFrom, "Active"));
|
||||
colors.add(Color.rgb(0, 255, 0));
|
||||
colors.add(color_activity);
|
||||
secondIndex = activity.timeTo;
|
||||
}
|
||||
}
|
||||
@ -291,7 +291,7 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
|
||||
if (currentTime > timeFrom && currentTime < midDaySecond) {
|
||||
// Fill with unknown slice up until current time
|
||||
entries_0_12.add(new PieEntry(currentTime - secondIndex, "Unknown"));
|
||||
colors_0_12.add(Color.argb(128, 128, 128, 128));
|
||||
colors_0_12.add(color_worn);
|
||||
// Draw transparent slice for remaining time until midday
|
||||
entries_0_12.add(new PieEntry(midDaySecond - currentTime, "Empty"));
|
||||
colors_0_12.add(Color.TRANSPARENT);
|
||||
@ -299,7 +299,7 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
|
||||
if (currentTime >= midDaySecond && currentTime < timeTo) {
|
||||
// Fill with unknown slice up until current time
|
||||
entries_12_24.add(new PieEntry(currentTime - secondIndex, "Unknown"));
|
||||
colors_12_24.add(Color.rgb(128, 128, 128));
|
||||
colors_12_24.add(color_worn);
|
||||
// Draw transparent slice for remaining time until midnight
|
||||
entries_12_24.add(new PieEntry(timeTo - currentTime, "Empty"));
|
||||
colors_12_24.add(Color.TRANSPARENT);
|
||||
|
21
app/src/main/res/layout/dashboard_widget_goals.xml
Normal file
21
app/src/main/res/layout/dashboard_widget_goals.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout 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"
|
||||
android:orientation="vertical"
|
||||
tools:context=".activities.dashboard.DashboardGoalsWidget">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dashboard_goals_chart"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="230dp"
|
||||
android:scaleType="fitCenter" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dashboard_goals_legend"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:textAlignment="center" />
|
||||
</LinearLayout>
|
@ -98,7 +98,6 @@
|
||||
android:key="dashboard_widget_goals_enabled"
|
||||
android:layout="@layout/preference_checkbox"
|
||||
android:title="Goals chart"
|
||||
android:enabled="false"
|
||||
app:iconSpaceReserved="false" />
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
|
Loading…
Reference in New Issue
Block a user