From 40bc35935f9e5416328c3c63a3e7e72e94b18aa0 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Thu, 25 Jun 2020 07:04:43 -0500 Subject: [PATCH] Create target widget --- .../src/main/AndroidManifest.xml | 205 ++++++++++-------- .../activities/common/views/TargetChart.java | 13 +- .../habits/show/views/TargetCard.java | 46 ++-- .../uhabits/widgets/StackWidgetType.java | 11 +- .../isoron/uhabits/widgets/TargetWidget.kt | 60 +++++ .../uhabits/widgets/TargetWidgetProvider.kt | 29 +++ .../isoron/uhabits/widgets/WidgetUpdater.kt | 1 + .../res/layout/target_stackview_widget.xml | 19 ++ 8 files changed, 279 insertions(+), 105 deletions(-) create mode 100644 android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt create mode 100644 android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidgetProvider.kt create mode 100644 android/uhabits-android/src/main/res/layout/target_stackview_widget.xml diff --git a/android/uhabits-android/src/main/AndroidManifest.xml b/android/uhabits-android/src/main/AndroidManifest.xml index b5138b3d3..9a3e7961f 100644 --- a/android/uhabits-android/src/main/AndroidManifest.xml +++ b/android/uhabits-android/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ + package="org.isoron.uhabits"> @@ -8,37 +8,37 @@ + android:name=".HabitsApplication" + android:allowBackup="true" + android:backupAgent=".HabitsBackupAgent" + android:icon="@mipmap/ic_launcher" + android:label="@string/main_activity_title" + android:supportsRtl="true" + android:theme="@style/AppBaseTheme"> + android:name=".activities.habits.edit.EditHabitActivity" + android:exported="true"> + android:name="android.support.PARENT_ACTIVITY" + android:value=".activities.habits.list.ListHabitsActivity" /> + android:name="com.google.android.backup.api_key" + android:value="AEdPqrEAAAAI6aeWncbnMNo8E5GWeZ44dlc5cQ7tCROwFhOtiw" /> + android:name=".activities.habits.list.ListHabitsActivity" + android:exported="true" + android:label="@string/main_activity_title" + android:launchMode="singleTop" /> + android:name=".MainActivity" + android:label="@string/main_activity_title" + android:launchMode="singleTop" + android:targetActivity=".activities.habits.list.ListHabitsActivity"> @@ -47,109 +47,131 @@ + android:name=".activities.habits.show.ShowHabitActivity" + android:label="@string/title_activity_show_habit"> + android:name="android.support.PARENT_ACTIVITY" + android:value=".activities.habits.list.ListHabitsActivity" /> + + android:name=".activities.settings.SettingsActivity" + android:label="@string/settings"> + android:name="android.support.PARENT_ACTIVITY" + android:value=".activities.habits.list.ListHabitsActivity" /> + + android:name=".activities.intro.IntroActivity" + android:label="" + android:theme="@style/Theme.AppCompat.Light.NoActionBar" /> + + android:name=".widgets.HabitPickerDialog" + android:theme="@style/Theme.AppCompat.Light.Dialog"> + + android:name=".activities.about.AboutActivity" + android:label="@string/about"> + android:name="android.support.PARENT_ACTIVITY" + android:value=".activities.habits.list.ListHabitsActivity" /> + + android:name=".notifications.SnoozeDelayPickerActivity" + android:excludeFromRecents="true" + android:launchMode="singleInstance" + android:theme="@android:style/Theme.Translucent.NoTitleBar" /> + android:name=".widgets.CheckmarkWidgetProvider" + android:label="@string/checkmark"> + android:name="android.appwidget.provider" + android:resource="@xml/widget_checkmark_info" /> + android:name=".widgets.StackWidgetService" + android:exported="false" + android:permission="android.permission.BIND_REMOTEVIEWS" /> + + + + + + + + + android:name=".widgets.ScoreWidgetProvider" + android:label="@string/habit_strength"> + android:name="android.appwidget.provider" + android:resource="@xml/widget_score_info" /> + + android:name=".widgets.StreakWidgetProvider" + android:label="@string/streaks"> + android:name="android.appwidget.provider" + android:resource="@xml/widget_streak_info" /> + + android:name=".widgets.FrequencyWidgetProvider" + android:label="@string/frequency"> + android:name="android.appwidget.provider" + android:resource="@xml/widget_frequency_info" /> + + android:name=".widgets.TargetWidgetProvider" + android:label="@string/target"> + android:name="android.appwidget.provider" + android:resource="@xml/widget_frequency_info" /> + + @@ -157,8 +179,8 @@ + android:host="org.isoron.uhabits" + android:scheme="content" /> @@ -166,8 +188,8 @@ + android:host="org.isoron.uhabits" + android:scheme="content" /> @@ -175,41 +197,46 @@ + android:host="org.isoron.uhabits" + android:scheme="content" /> - + + + + android:name=".automation.EditSettingActivity" + android:exported="true" + android:icon="@mipmap/ic_launcher" + android:label="@string/app_name"> - + + + + android:name=".automation.FireSettingReceiver" + android:exported="true"> + android:name="androidx.core.content.FileProvider" + android:authorities="org.isoron.uhabits" + android:exported="false" + android:grantUriPermissions="true"> + android:name="android.support.FILE_PROVIDER_PATHS" + android:resource="@xml/file_paths" /> + android:name=".sync.SyncService" + android:enabled="true" + android:exported="false" /> + \ No newline at end of file diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/TargetChart.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/TargetChart.java index cc1051f8d..30ec17bd9 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/TargetChart.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/TargetChart.java @@ -93,7 +93,8 @@ public class TargetChart extends View maxLabelSize = Math.max(maxLabelSize, len); } - rect.set(0, 0, getWidth(), baseSize); + float marginTop = (getHeight() - baseSize * labels.size()) / 2.0f; + rect.set(0, marginTop, getWidth(), marginTop + baseSize); for (int i = 0; i < labels.size(); i++) { drawRow(canvas, i, rect); rect.offset(0, baseSize); @@ -103,8 +104,17 @@ public class TargetChart extends View @Override protected void onMeasure(int widthSpec, int heightSpec) { + baseSize = getResources().getDimensionPixelSize(R.dimen.baseSize); + int width = getSize(widthSpec); int height = labels.size() * baseSize; + + ViewGroup.LayoutParams params = getLayoutParams(); + if (params != null && params.height == ViewGroup.LayoutParams.MATCH_PARENT) { + height = getSize(heightSpec); + if (labels.size() > 0) baseSize = height / labels.size(); + } + heightSpec = makeMeasureSpec(height, EXACTLY); widthSpec = makeMeasureSpec(width, EXACTLY); setMeasuredDimension(widthSpec, heightSpec); @@ -194,7 +204,6 @@ public class TargetChart extends View mediumContrastTextColor = res.getColor(R.attr.mediumContrastTextColor); highContrastReverseTextColor = res.getColor(R.attr.highContrastReverseTextColor); tinyTextSize = getDimension(getContext(), R.dimen.tinyTextSize); - baseSize = getResources().getDimensionPixelSize(R.dimen.baseSize); } public void setValues(List values) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.java index aaa7a30d2..464ca1955 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.java @@ -24,6 +24,8 @@ import android.content.res.*; import android.util.*; import android.widget.*; +import androidx.annotation.*; + import org.isoron.uhabits.R; import org.isoron.uhabits.*; import org.isoron.uhabits.activities.common.views.*; @@ -86,10 +88,10 @@ public class TargetCard extends HabitCard @Override protected Task createRefreshTask() { - return new RefreshTask(); + return new RefreshTask(getContext(), getHabit(), firstWeekday, targetChart, title); } - private class RefreshTask extends CancelableTask + public static class RefreshTask extends CancelableTask { double todayValue; double thisWeekValue; @@ -97,11 +99,30 @@ public class TargetCard extends HabitCard double thisQuarterValue; double thisYearValue; + private Context context; + private Habit habit; + private int firstWeekday; + private TargetChart chart; + private TextView title; + + public RefreshTask(@NonNull Context context, + @NonNull Habit habit, + int firstWeekday, + @NonNull TargetChart chart, + @Nullable TextView title) + { + this.context = context; + this.habit = habit; + this.firstWeekday = firstWeekday; + this.chart = chart; + this.title = title; + } + @Override public void doInBackground() { if (isCanceled()) return; - CheckmarkList checkmarks = getHabit().getCheckmarks(); + CheckmarkList checkmarks = habit.getCheckmarks(); todayValue = checkmarks.getTodayValue() / 1e3; thisWeekValue = checkmarks.getThisWeekValue(firstWeekday) / 1e3; thisMonthValue = checkmarks.getThisMonthValue() / 1e3; @@ -113,15 +134,14 @@ public class TargetCard extends HabitCard public void onPostExecute() { if (isCanceled()) return; - Calendar cal = DateUtils.getStartOfTodayCalendar(); int daysInMonth = cal.getActualMaximum(Calendar.DAY_OF_MONTH); int daysInQuarter = 91; int daysInYear = cal.getActualMaximum(Calendar.DAY_OF_YEAR); - int den = getHabit().getFrequency().getDenominator(); - double dailyTarget = getHabit().getTargetValue() / den; - Resources res = getResources(); + int den = habit.getFrequency().getDenominator(); + double dailyTarget = habit.getTargetValue() / den; + Resources res = context.getResources(); ArrayList values = new ArrayList<>(); if (den <= 1) values.add(todayValue); @@ -129,7 +149,7 @@ public class TargetCard extends HabitCard values.add(thisMonthValue); values.add(thisQuarterValue); values.add(thisYearValue); - targetChart.setValues(values); + chart.setValues(values); ArrayList targets = new ArrayList<>(); if (den <= 1) targets.add(dailyTarget); @@ -137,7 +157,7 @@ public class TargetCard extends HabitCard targets.add(dailyTarget * daysInMonth); targets.add(dailyTarget * daysInQuarter); targets.add(dailyTarget * daysInYear); - targetChart.setTargets(targets); + chart.setTargets(targets); ArrayList labels = new ArrayList<>(); if (den <= 1) labels.add(res.getString(R.string.today)); @@ -145,15 +165,15 @@ public class TargetCard extends HabitCard labels.add(res.getString(R.string.month)); labels.add(res.getString(R.string.quarter)); labels.add(res.getString(R.string.year)); - targetChart.setLabels(labels); + chart.setLabels(labels); } @Override public void onPreExecute() { - int color = PaletteUtils.getColor(getContext(), getHabit().getColor()); - title.setTextColor(color); - targetChart.setColor(color); + int color = PaletteUtils.getColor(context, habit.getColor()); + if(title != null) title.setTextColor(color); + chart.setColor(color); } } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.java index a5aeebb82..7a014f394 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.java @@ -12,7 +12,8 @@ public enum StackWidgetType { FREQUENCY(1), SCORE(2), // habit strength widget HISTORY(3), - STREAKS(4); + STREAKS(4), + TARGET(5); private int value; StackWidgetType(int value) { @@ -34,6 +35,8 @@ public enum StackWidgetType { return HISTORY; } else if (STREAKS.getValue() == value) { return STREAKS; + } else if (TARGET.getValue() == value) { + return TARGET; } return null; } @@ -50,6 +53,8 @@ public enum StackWidgetType { return R.layout.history_stackview_widget; case STREAKS: return R.layout.streak_stackview_widget; + case TARGET: + return R.layout.target_stackview_widget; } return 0; } @@ -66,6 +71,8 @@ public enum StackWidgetType { return R.id.historyStackWidgetView; case STREAKS: return R.id.streakStackWidgetView; + case TARGET: + return R.id.targetStackWidgetView; } return 0; } @@ -82,6 +89,8 @@ public enum StackWidgetType { return R.id.historyStackWidgetEmptyView; case STREAKS: return R.id.streakStackWidgetEmptyView; + case TARGET: + return R.id.targetStackWidgetEmptyView; } return 0; } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt new file mode 100644 index 000000000..e38e25f9e --- /dev/null +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +package org.isoron.uhabits.widgets + +import android.content.* +import android.view.* +import android.view.ViewGroup.* +import android.view.ViewGroup.LayoutParams.* +import org.isoron.uhabits.activities.common.views.* +import org.isoron.uhabits.activities.habits.show.views.* +import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.widgets.views.* + +class TargetWidget( + context: Context, + id: Int, + private val habit: Habit +) : BaseWidget(context, id) { + + override fun getOnClickPendingIntent(context: Context) = + pendingIntentFactory.showHabit(habit) + + override fun refreshData(view: View) { + val widgetView = view as GraphWidgetView + widgetView.setBackgroundAlpha(preferedBackgroundAlpha) + val chart = (widgetView.dataView as TargetChart) + with(TargetCard.RefreshTask(context, habit, prefs.firstWeekday, chart, null)) { + onPreExecute() + doInBackground() + onPostExecute() + } + } + + override fun buildView(): View { + return GraphWidgetView(context, TargetChart(context)).apply { + setTitle(habit.name) + layoutParams = LayoutParams(MATCH_PARENT, MATCH_PARENT) + } + } + + override fun getDefaultHeight() = 200 + override fun getDefaultWidth() = 200 +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidgetProvider.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidgetProvider.kt new file mode 100644 index 000000000..90524c890 --- /dev/null +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidgetProvider.kt @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ +package org.isoron.uhabits.widgets + +import android.content.* + +class TargetWidgetProvider : BaseWidgetProvider() { + override fun getWidgetFromId(context: Context, id: Int): BaseWidget { + val habits = getHabitsFromWidgetId(id) + if (habits.size == 1) return TargetWidget(context, id, habits[0]) + else return StackWidget(context, id, StackWidgetType.TARGET, habits) + } +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt index b8293582a..17d6d5d77 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt @@ -67,6 +67,7 @@ class WidgetUpdater updateWidgets(modifiedHabitId, ScoreWidgetProvider::class.java) updateWidgets(modifiedHabitId, StreakWidgetProvider::class.java) updateWidgets(modifiedHabitId, FrequencyWidgetProvider::class.java) + updateWidgets(modifiedHabitId, TargetWidgetProvider::class.java) } } diff --git a/android/uhabits-android/src/main/res/layout/target_stackview_widget.xml b/android/uhabits-android/src/main/res/layout/target_stackview_widget.xml new file mode 100644 index 000000000..99ab7eefa --- /dev/null +++ b/android/uhabits-android/src/main/res/layout/target_stackview_widget.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file