From 2535347d5a1397d96df252fc08645fd1aeecc125 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Wed, 17 Aug 2022 05:36:37 -0500 Subject: [PATCH 1/9] Always update widgets on launch Helps mitigate situations where the widgets mysteriously fail to render. The user can always force a refresh by opening the app. --- .../uhabits/activities/habits/list/ListHabitsActivity.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.kt index 19d8cf7ea..e14bdefd5 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsActivity.kt @@ -102,8 +102,9 @@ class ListHabitsActivity : AppCompatActivity(), Preferences.Listener { taskRunner.run { try { AutoBackup(this@ListHabitsActivity).run() + appComponent.widgetUpdater.updateWidgets() } catch (e: Exception) { - Log.e("ListHabitActivity", "AutoBackup task failed", e) + Log.e("ListHabitActivity", "TaskRunner failed", e) } } if (prefs.theme == THEME_DARK && prefs.isPureBlackEnabled != pureBlack) { From f7c6bc716c42fa1377ffb4650c35c44f408ad31a Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Sat, 3 Sep 2022 19:52:13 -0500 Subject: [PATCH 2/9] Fix ListHabitsScreen.showColorPicker --- .../isoron/uhabits/activities/habits/list/ListHabitsScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt index fa74b0a49..731342974 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt @@ -225,7 +225,7 @@ class ListHabitsScreen override fun showColorPicker(defaultColor: PaletteColor, callback: OnColorPickedCallback) { val picker = colorPickerFactory.create(defaultColor, themeSwitcher.currentTheme!!) picker.setListener(callback) - picker.dialog?.dismissCurrentAndShow() + picker.dismissCurrentAndShow(activity.supportFragmentManager, "picker") } override fun showNumberPopup( From fc402fd81b23613417f7c24c0564616b87c56e5a Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Sat, 3 Sep 2022 20:26:21 -0500 Subject: [PATCH 3/9] Minor fix to BarChart --- .../jvmMain/java/org/isoron/uhabits/core/ui/views/BarChart.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/BarChart.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/BarChart.kt index 7e240eecb..493ec68dc 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/BarChart.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/BarChart.kt @@ -92,7 +92,7 @@ class BarChart( val r = round(barWidth * 0.15) if (2 * r < barHeight) { canvas.fillRect(x, y + r, barWidth, barHeight - r) - canvas.fillRect(x + r, y, barWidth - 2 * r, r) + canvas.fillRect(x + r, y, barWidth - 2 * r, r + 1) canvas.fillCircle(x + r, y + r, r) canvas.fillCircle(x + barWidth - r, y + r, r) } else { From 16c65f19fd2b856841dfbff16a3425f15fe5e3fe Mon Sep 17 00:00:00 2001 From: Eduardo Esparza <92958867+eduebernal@users.noreply.github.com> Date: Thu, 8 Sep 2022 18:01:12 -0700 Subject: [PATCH 4/9] fix marker scaling for numerical habits in frequency display (#1489) --- .../activities/common/views/FrequencyChart.kt | 24 ++++++++++++++++--- .../habits/show/views/FrequencyCardView.kt | 1 + .../isoron/uhabits/widgets/FrequencyWidget.kt | 1 + .../habits/show/views/FrequencyCard.kt | 2 ++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/FrequencyChart.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/FrequencyChart.kt index 417ab21f2..41c67ff27 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/FrequencyChart.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/FrequencyChart.kt @@ -63,7 +63,9 @@ class FrequencyChart : ScrollableChart { private var primaryColor = 0 private var isBackgroundTransparent = false private lateinit var frequency: HashMap> + private var maxFreq = 0 private var firstWeekday = Calendar.SUNDAY + private var isNumerical: Boolean = false constructor(context: Context?) : super(context) { init() @@ -80,8 +82,14 @@ class FrequencyChart : ScrollableChart { postInvalidate() } + fun setIsNumerical(type: Boolean) { + isNumerical = type + postInvalidate() + } + fun setFrequency(frequency: java.util.HashMap>) { this.frequency = frequency + maxFreq = getMaxFreq(frequency) postInvalidate() } @@ -90,6 +98,15 @@ class FrequencyChart : ScrollableChart { postInvalidate() } + private fun getMaxFreq(frequency: HashMap>): Int { + var maxValue = 1 + for (values in frequency.values) for (value in values) maxValue = max( + value, + maxValue + ) + return maxValue + } + fun setIsBackgroundTransparent(isBackgroundTransparent: Boolean) { this.isBackgroundTransparent = isBackgroundTransparent initColors() @@ -213,7 +230,7 @@ class FrequencyChart : ScrollableChart { canvas.drawLine(rGrid.left, rGrid.top, rGrid.right, rGrid.top, pGrid!!) } - private fun drawMarker(canvas: Canvas, rect: RectF?, value: Int?, frequency: Int) { + private fun drawMarker(canvas: Canvas, rect: RectF?, value: Int?, weekdayFrequency: Int) { // value can be negative when the entry is skipped val valueCopy = value?.let { max(0, it) } @@ -221,8 +238,8 @@ class FrequencyChart : ScrollableChart { // maximal allowed mark radius val maxRadius = (rect.height() - 2 * padding) / 2.0f // the real mark radius is scaled down by a factor depending on the maximal frequency - - val scale = 1.0f / frequency * valueCopy!! + val scalingFactor = if (isNumerical) maxFreq else weekdayFrequency + val scale = 1.0f / scalingFactor * valueCopy!! val radius = maxRadius * scale val colorIndex = min((colors.size - 1), ((colors.size - 1) * scale).roundToInt()) pGraph!!.color = colors[colorIndex] @@ -285,5 +302,6 @@ class FrequencyChart : ScrollableChart { frequency[Timestamp(date)] = values date.add(Calendar.MONTH, -1) } + maxFreq = getMaxFreq(frequency) } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardView.kt index cf7daf769..f31b23408 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardView.kt @@ -33,6 +33,7 @@ class FrequencyCardView(context: Context, attrs: AttributeSet) : LinearLayout(co fun setState(state: FrequencyCardState) { val androidColor = state.theme.color(state.color).toInt() binding.frequencyChart.setFrequency(state.frequency) + binding.frequencyChart.setIsNumerical(state.isNumerical) binding.frequencyChart.setFirstWeekday(state.firstWeekday) binding.title.setTextColor(androidColor) binding.frequencyChart.setColor(androidColor) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt index 8ef1b4a48..8b76cb1b3 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt @@ -49,6 +49,7 @@ class FrequencyWidget( (widgetView.dataView as FrequencyChart).apply { setFirstWeekday(firstWeekday) setColor(WidgetTheme().color(habit.color).toInt()) + setIsNumerical(habit.isNumerical) setFrequency(habit.originalEntries.computeWeekdayFrequency(habit.isNumerical)) } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/FrequencyCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/FrequencyCard.kt index fd46c3473..cdb12d32d 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/FrequencyCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/FrequencyCard.kt @@ -30,6 +30,7 @@ data class FrequencyCardState( val firstWeekday: Int, val frequency: HashMap>, val theme: Theme, + val isNumerical: Boolean ) class FrequencyCardPresenter { @@ -40,6 +41,7 @@ class FrequencyCardPresenter { theme: Theme ) = FrequencyCardState( color = habit.color, + isNumerical = habit.isNumerical, frequency = habit.originalEntries.computeWeekdayFrequency( isNumerical = habit.isNumerical ), From eeacc5eef80054cfe4d48efbc016c5741f90c286 Mon Sep 17 00:00:00 2001 From: cheer <31635100+cheeeeer@users.noreply.github.com> Date: Thu, 8 Sep 2022 21:06:57 -0400 Subject: [PATCH 5/9] Support for Android 13 Themed Icons (#1497) --- .../main/res/mipmap-anydpi-v26/ic_launcher.xml | 1 + .../res/mipmap-hdpi/ic_launcher_monochrome.png | Bin 0 -> 1816 bytes .../res/mipmap-mdpi/ic_launcher_monochrome.png | Bin 0 -> 1816 bytes .../res/mipmap-xhdpi/ic_launcher_monochrome.png | Bin 0 -> 2441 bytes .../res/mipmap-xxhdpi/ic_launcher_monochrome.png | Bin 0 -> 3761 bytes .../mipmap-xxxhdpi/ic_launcher_monochrome.png | Bin 0 -> 7579 bytes 6 files changed, 1 insertion(+) create mode 100644 uhabits-android/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png create mode 100644 uhabits-android/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png create mode 100644 uhabits-android/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png create mode 100644 uhabits-android/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png create mode 100644 uhabits-android/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png diff --git a/uhabits-android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/uhabits-android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index 06bdca668..ef49fafa3 100644 --- a/uhabits-android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/uhabits-android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -21,4 +21,5 @@ + \ No newline at end of file diff --git a/uhabits-android/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png b/uhabits-android/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000000000000000000000000000000000000..a8f9e9409a6933afbdb1de80fc82f30ed425fc08 GIT binary patch literal 1816 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 YGDG~^@HY2?ox}iOo!lMo9mCW920EIBrT_o{ literal 0 HcmV?d00001 diff --git a/uhabits-android/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png b/uhabits-android/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000000000000000000000000000000000000..b19b8bd5d92fffa26c2a20dd8184628fcba3c53f GIT binary patch literal 3761 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 B#a#dZ literal 0 HcmV?d00001 diff --git a/uhabits-android/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png b/uhabits-android/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png new file mode 100644 index 0000000000000000000000000000000000000000..3eeb6ebefa3f76197527be7b32518805759577a4 GIT binary patch literal 7579 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 Date: Thu, 8 Sep 2022 20:09:47 -0500 Subject: [PATCH 6/9] Update CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 845d81ec3..167da5a52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Improve number picker (@hiqua, @iSoron, #1082, #1370) - Add new checkmark and number picker (@iSoron, #1370) - Allow user to import numerical habits from HabitBull (@hiqua, #1278) +- Add support for Android 13 themed icons (@cheeeeer, #1497) ### Removed - Hide snooze button Android 12 notifications (@hiqua, #1226) @@ -28,6 +29,7 @@ - Fix small issues in calendar chart (@kalina559, #1314) - Resort habit list after edit (@hiqua, #1350) - Fix marker scaling in frequency display (@eduebernal, #1425) +- Fix widgets not working correctly on API 33 (@iSoron, #1488) ### Refactoring & Testing - Replace raster icons by vector assets (@kalina559) From 11f726064ab03d9e4cb255f86b5ed6bb7a3cf2ec Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Thu, 8 Sep 2022 20:35:59 -0500 Subject: [PATCH 7/9] StackWidget: Avoid storing RemoteViews reference --- .../uhabits/widgets/StackWidgetService.kt | 44 +++++++++---------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.kt index c8eabcc1c..91663671e 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.kt @@ -88,8 +88,26 @@ internal class StackRemoteViewsFactory(private val context: Context, intent: Int } override fun getViewAt(position: Int): RemoteViews? { - Log.i("StackRemoteViewsFactory", "getViewAt $position") - return if (0 <= position && position < remoteViews.size) remoteViews[position] else null + Log.i("StackRemoteViewsFactory", "getViewAt $position started") + if (position < 0 || position >= remoteViews.size) return null + val app = context.applicationContext as HabitsApplication + val prefs = app.component.preferences + val habitList = app.component.habitList + val options = AppWidgetManager.getInstance(context).getAppWidgetOptions(widgetId) + if (Looper.myLooper() == null) Looper.prepare() + val habits = habitIds.map { habitList.getById(it) ?: throw HabitNotFoundException() } + val h = habits[position] + val widget = constructWidget(h, prefs) + widget.setDimensions(getDimensionsFromOptions(context, options)) + val landscapeViews = widget.landscapeRemoteViews + val portraitViews = widget.portraitRemoteViews + val factory = PendingIntentFactory(context, IntentFactory()) + val intent = StackWidgetType.getIntentFillIn(factory, widgetType, h, habits, getToday()) + landscapeViews.setOnClickFillInIntent(R.id.button, intent) + portraitViews.setOnClickFillInIntent(R.id.button, intent) + val remoteViews = RemoteViews(landscapeViews, portraitViews) + Log.i("StackRemoteViewsFactory", "getViewAt $position ended") + return remoteViews } private fun constructWidget( @@ -134,28 +152,6 @@ internal class StackRemoteViewsFactory(private val context: Context, intent: Int } override fun onDataSetChanged() { - Log.i("StackRemoteViewsFactory", "onDataSetChanged started") - val app = context.applicationContext as HabitsApplication - val prefs = app.component.preferences - val habitList = app.component.habitList - val options = AppWidgetManager.getInstance(context).getAppWidgetOptions(widgetId) - val newRemoteViews = ArrayList() - if (Looper.myLooper() == null) Looper.prepare() - val habits = habitIds.map { habitList.getById(it) ?: throw HabitNotFoundException() } - for (h in habits) { - val widget = constructWidget(h, prefs) - widget.setDimensions(getDimensionsFromOptions(context, options)) - val landscapeViews = widget.landscapeRemoteViews - val portraitViews = widget.portraitRemoteViews - val factory = PendingIntentFactory(context, IntentFactory()) - val intent = StackWidgetType.getIntentFillIn(factory, widgetType, h, habits, getToday()) - landscapeViews.setOnClickFillInIntent(R.id.button, intent) - portraitViews.setOnClickFillInIntent(R.id.button, intent) - newRemoteViews.add(RemoteViews(landscapeViews, portraitViews)) - Log.i("StackRemoteViewsFactory", "onDataSetChanged constructed widget ${h.id}") - } - remoteViews = newRemoteViews - Log.i("StackRemoteViewsFactory", "onDataSetChanged ended") } init { From 961fb7618f526f33e67a9b818cba292ae0f47035 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Thu, 8 Sep 2022 20:43:14 -0500 Subject: [PATCH 8/9] splitLongs: Handle NumberFormatException --- .../kotlin/org/isoron/platform/utils/StringUtils.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/uhabits-core/src/commonMain/kotlin/org/isoron/platform/utils/StringUtils.kt b/uhabits-core/src/commonMain/kotlin/org/isoron/platform/utils/StringUtils.kt index 8f3cf62d0..f6105b4cc 100644 --- a/uhabits-core/src/commonMain/kotlin/org/isoron/platform/utils/StringUtils.kt +++ b/uhabits-core/src/commonMain/kotlin/org/isoron/platform/utils/StringUtils.kt @@ -25,6 +25,12 @@ class StringUtils { fun joinLongs(values: LongArray): String = values.joinToString(separator = ",") - fun splitLongs(str: String): LongArray = str.split(",").map { it.toLong() }.toLongArray() + fun splitLongs(str: String): LongArray { + return try { + str.split(",").map { it.toLong() }.toLongArray() + } catch (e: NumberFormatException) { + LongArray(0) + } + } } } From ec1f0c535660cc90f1621e1ab51c5086057a8535 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Fri, 9 Sep 2022 05:57:13 -0500 Subject: [PATCH 9/9] StackWidget: Remove unused remoteViews; fix invalid check --- .../main/java/org/isoron/uhabits/widgets/StackWidgetService.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.kt index 91663671e..d23005c96 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.kt @@ -57,7 +57,6 @@ internal class StackRemoteViewsFactory(private val context: Context, intent: Int ) private val habitIds: LongArray private val widgetType: StackWidgetType - private var remoteViews = ArrayList() override fun onCreate() {} override fun onDestroy() {} override fun getCount(): Int { @@ -89,7 +88,7 @@ internal class StackRemoteViewsFactory(private val context: Context, intent: Int override fun getViewAt(position: Int): RemoteViews? { Log.i("StackRemoteViewsFactory", "getViewAt $position started") - if (position < 0 || position >= remoteViews.size) return null + if (position < 0 || position >= habitIds.size) return null val app = context.applicationContext as HabitsApplication val prefs = app.component.preferences val habitList = app.component.habitList