From d5a5273607a461c0f74d2fb98d7c3c5d13d1a55e Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Sat, 22 Oct 2022 15:25:42 -0500 Subject: [PATCH 01/16] Bump version to 2.1.2 --- uhabits-android/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index 62a0489e..49fb4c8b 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -35,8 +35,8 @@ android { compileSdk = 31 defaultConfig { - versionCode = 20101 - versionName = "2.1.1" + versionCode = 20102 + versionName = "2.1.2" minSdk = 23 targetSdk = 31 applicationId = "org.isoron.uhabits" From 0bb82a48a52409e886e9557598e0a0de048d25ff Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Sat, 22 Oct 2022 15:43:54 -0500 Subject: [PATCH 02/16] NumberPopup: Accept comma (instead of dot) in certain locales Fixes #1532 --- .../activities/common/dialogs/NumberPopup.kt | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPopup.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPopup.kt index c3a46431..f918fb26 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPopup.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPopup.kt @@ -21,6 +21,7 @@ package org.isoron.uhabits.activities.common.dialogs import android.app.Dialog import android.content.Context +import android.text.method.DigitsKeyListener import android.view.KeyEvent.KEYCODE_ENTER import android.view.LayoutInflater import android.view.MotionEvent.ACTION_DOWN @@ -35,6 +36,9 @@ import org.isoron.uhabits.utils.dismissCurrentAndShow import org.isoron.uhabits.utils.dp import org.isoron.uhabits.utils.requestFocusWithKeyboard import java.text.DecimalFormat +import java.text.DecimalFormatSymbols +import java.text.NumberFormat +import java.text.ParseException class NumberPopup( private val context: Context, @@ -55,10 +59,17 @@ class NumberPopup( init { view.numberButtons.visibility = VISIBLE + fixDecimalSeparator() hideDisabledButtons() populate() } + private fun fixDecimalSeparator() { + // https://stackoverflow.com/a/34256139 + val separator = DecimalFormatSymbols.getInstance().decimalSeparator + view.value.keyListener = DigitsKeyListener.getInstance("0123456789$separator") + } + private fun hideDisabledButtons() { if (!prefs.isSkipEnabled) view.skipBtnNumber.visibility = GONE } @@ -108,7 +119,14 @@ class NumberPopup( } fun save() { - val value = view.value.text.toString().toDoubleOrNull() ?: originalValue + var value = originalValue + try { + val numberFormat = NumberFormat.getInstance() + val valueStr = view.value.text.toString() + value = numberFormat.parse(valueStr)!!.toDouble() + } catch (e: ParseException) { + // NOP + } val notes = view.notes.text.toString() onToggle(value, notes) dialog.dismiss() From 4de67bd27a8ed166126bffcdd214f160f0aca61a Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Sat, 22 Oct 2022 16:01:36 -0500 Subject: [PATCH 03/16] GH Actions: Remove API 27 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 46bed95e..94d30ad4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,7 +17,7 @@ jobs: run: ./build.sh build - name: Run Android tests - run: ./build.sh android-tests-parallel 23 24 25 26 27 28 30 31 + run: ./build.sh android-tests-parallel 23 24 25 26 28 30 31 - name: Upload artifacts if: always() From 2ba5f5fb985679f8e4042a9bf431ae9ab5bd80c5 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Sat, 22 Oct 2022 16:18:55 -0500 Subject: [PATCH 04/16] Dismiss current dialog onPause Fixes #1545 --- .../uhabits/activities/habits/list/ListHabitsActivity.kt | 2 ++ .../uhabits/activities/habits/show/ShowHabitActivity.kt | 2 ++ .../src/main/java/org/isoron/uhabits/utils/DialogUtils.kt | 4 ++++ 3 files changed, 8 insertions(+) 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 e14bdefd..875cdb94 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 @@ -40,6 +40,7 @@ import org.isoron.uhabits.inject.ActivityContextModule import org.isoron.uhabits.inject.DaggerHabitsActivityComponent import org.isoron.uhabits.inject.HabitsActivityComponent import org.isoron.uhabits.inject.HabitsApplicationComponent +import org.isoron.uhabits.utils.dismissCurrentDialog import org.isoron.uhabits.utils.restartWithFade class ListHabitsActivity : AppCompatActivity(), Preferences.Listener { @@ -91,6 +92,7 @@ class ListHabitsActivity : AppCompatActivity(), Preferences.Listener { midnightTimer.onPause() screen.onDetached() adapter.cancelRefresh() + dismissCurrentDialog() super.onPause() } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt index b993d0d2..b68dc1f3 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt @@ -51,6 +51,7 @@ import org.isoron.uhabits.core.ui.views.OnDateClickedListener import org.isoron.uhabits.intents.IntentFactory import org.isoron.uhabits.utils.currentTheme import org.isoron.uhabits.utils.dismissCurrentAndShow +import org.isoron.uhabits.utils.dismissCurrentDialog import org.isoron.uhabits.utils.showMessage import org.isoron.uhabits.utils.showSendFileScreen import org.isoron.uhabits.widgets.WidgetUpdater @@ -129,6 +130,7 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener { } override fun onPause() { + dismissCurrentDialog() commandRunner.removeListener(this) super.onPause() } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/utils/DialogUtils.kt b/uhabits-android/src/main/java/org/isoron/uhabits/utils/DialogUtils.kt index 855f865c..00a17aa9 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/utils/DialogUtils.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/utils/DialogUtils.kt @@ -7,6 +7,10 @@ import java.lang.ref.WeakReference var currentDialog: WeakReference = WeakReference(null) +fun dismissCurrentDialog() { + currentDialog.get()?.dismiss() +} + fun Dialog.dismissCurrentAndShow() { currentDialog.get()?.dismiss() currentDialog = WeakReference(this) From 471f97720969b0cf7de9aa08f96f83d44ab6dd53 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Sat, 22 Oct 2022 17:11:59 -0500 Subject: [PATCH 05/16] Replace some incorrect usages of getToday by getTodayWithOffset Fixes #1541 --- .../main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt | 2 +- .../java/org/isoron/uhabits/widgets/StackWidgetService.kt | 4 ++-- .../java/org/isoron/uhabits/core/io/HabitsCSVExporter.kt | 2 +- .../uhabits/core/ui/screens/habits/show/views/BarCard.kt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt index fbbb7ffd..60110ea3 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt @@ -43,7 +43,7 @@ open class CheckmarkWidget( override fun getOnClickPendingIntent(context: Context): PendingIntent? { return if (habit.isNumerical) { - pendingIntentFactory.showNumberPicker(habit, DateUtils.getToday()) + pendingIntentFactory.showNumberPicker(habit, DateUtils.getTodayWithOffset()) } else { pendingIntentFactory.toggleCheckmark(habit, null) } 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 d23005c9..b8e2ba49 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 @@ -33,7 +33,7 @@ import org.isoron.uhabits.R import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.models.HabitNotFoundException import org.isoron.uhabits.core.preferences.Preferences -import org.isoron.uhabits.core.utils.DateUtils.Companion.getToday +import org.isoron.uhabits.core.utils.DateUtils.Companion.getTodayWithOffset import org.isoron.uhabits.intents.IntentFactory import org.isoron.uhabits.intents.PendingIntentFactory import org.isoron.uhabits.utils.InterfaceUtils.dpToPixels @@ -101,7 +101,7 @@ internal class StackRemoteViewsFactory(private val context: Context, intent: Int val landscapeViews = widget.landscapeRemoteViews val portraitViews = widget.portraitRemoteViews val factory = PendingIntentFactory(context, IntentFactory()) - val intent = StackWidgetType.getIntentFillIn(factory, widgetType, h, habits, getToday()) + val intent = StackWidgetType.getIntentFillIn(factory, widgetType, h, habits, getTodayWithOffset()) landscapeViews.setOnClickFillInIntent(R.id.button, intent) portraitViews.setOnClickFillInIntent(R.id.button, intent) val remoteViews = RemoteViews(landscapeViews, portraitViews) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitsCSVExporter.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitsCSVExporter.kt index 35e459a2..43dad695 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitsCSVExporter.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitsCSVExporter.kt @@ -149,7 +149,7 @@ class HabitsCSVExporter( val timeframe = getTimeframe() val oldest = timeframe[0] - val newest = DateUtils.getToday() + val newest = DateUtils.getTodayWithOffset() val checkmarks: MutableList> = ArrayList() val scores: MutableList> = ArrayList() for (habit in selectedHabits) { diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/BarCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/BarCard.kt index 5bace937..4c1f7313 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/BarCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/BarCard.kt @@ -57,7 +57,7 @@ class BarCardPresenter( } else { boolBucketSizes[boolSpinnerPosition] } - val today = DateUtils.getToday() + val today = DateUtils.getTodayWithOffset() val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today val entries = habit.computedEntries.getByInterval(oldest, today).groupedSum( truncateField = ScoreCardPresenter.getTruncateField(bucketSize), From 1470dcd560938398cab74b1e3039c4d005324024 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Mon, 23 Jan 2023 03:50:38 -0600 Subject: [PATCH 06/16] Remove toggle delay --- .../habits/list/views/EntryButtonViewTest.kt | 2 +- .../habits/list/views/EntryPanelViewTest.kt | 4 +-- .../habits/list/views/CheckmarkButtonView.kt | 12 +++---- .../habits/list/views/CheckmarkPanelView.kt | 4 +-- .../habits/list/views/HabitCardView.kt | 36 ++----------------- 5 files changed, 13 insertions(+), 45 deletions(-) diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt index f37cc183..32df0875 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt @@ -44,7 +44,7 @@ class EntryButtonViewTest : BaseViewTest() { view = component.getEntryButtonViewFactory().create().apply { value = Entry.NO color = PaletteUtils.getAndroidTestColor(5) - onToggle = { _, _, _ -> toggled = true } + onToggle = { _, _ -> toggled = true } onEdit = { edited = true } } measureView(view, dpToPixels(48), dpToPixels(48)) diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryPanelViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryPanelViewTest.kt index f09c48db..de955deb 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryPanelViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryPanelViewTest.kt @@ -77,7 +77,7 @@ class EntryPanelViewTest : BaseViewTest() { @Test fun testToggle() { val timestamps = mutableListOf() - view.onToggle = { t, _, _, _ -> timestamps.add(t) } + view.onToggle = { t, _, _ -> timestamps.add(t) } view.buttons[0].performLongClick() view.buttons[2].performLongClick() view.buttons[3].performLongClick() @@ -88,7 +88,7 @@ class EntryPanelViewTest : BaseViewTest() { fun testToggle_withOffset() { val timestamps = mutableListOf() view.dataOffset = 3 - view.onToggle = { t, _, _, _ -> timestamps += t } + view.onToggle = { t, _, _ -> timestamps += t } view.buttons[0].performLongClick() view.buttons[2].performLongClick() view.buttons[3].performLongClick() diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt index 176cec62..39faa028 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt @@ -44,8 +44,6 @@ import org.isoron.uhabits.utils.sres import org.isoron.uhabits.utils.toMeasureSpec import javax.inject.Inject -const val TOGGLE_DELAY_MILLIS = 2000L - class CheckmarkButtonViewFactory @Inject constructor( @ActivityContext val context: Context, @@ -79,7 +77,7 @@ class CheckmarkButtonView( invalidate() } - var onToggle: (Int, String, Long) -> Unit = { _, _, _ -> } + var onToggle: (Int, String) -> Unit = { _, _ -> } var onEdit: () -> Unit = { } @@ -90,25 +88,25 @@ class CheckmarkButtonView( setOnLongClickListener(this) } - fun performToggle(delay: Long) { + fun performToggle() { value = Entry.nextToggleValue( value = value, isSkipEnabled = preferences.isSkipEnabled, areQuestionMarksEnabled = preferences.areQuestionMarksEnabled ) - onToggle(value, notes, delay) + onToggle(value, notes) performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) invalidate() } override fun onClick(v: View) { - if (preferences.isShortToggleEnabled) performToggle(TOGGLE_DELAY_MILLIS) + if (preferences.isShortToggleEnabled) performToggle() else onEdit() } override fun onLongClick(v: View): Boolean { if (preferences.isShortToggleEnabled) onEdit() - else performToggle(TOGGLE_DELAY_MILLIS) + else performToggle() return true } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt index 35f63969..525dac5a 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt @@ -60,7 +60,7 @@ class CheckmarkPanelView( setupButtons() } - var onToggle: (Timestamp, Int, String, Long) -> Unit = { _, _, _, _ -> } + var onToggle: (Timestamp, Int, String) -> Unit = { _, _, _ -> } set(value) { field = value setupButtons() @@ -89,7 +89,7 @@ class CheckmarkPanelView( else -> "" } button.color = color - button.onToggle = { value, notes, delay -> onToggle(timestamp, value, notes, delay) } + button.onToggle = { value, notes -> onToggle(timestamp, value, notes) } button.onEdit = { onEdit(timestamp) } } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt index 424aae50..189c5c53 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt @@ -57,13 +57,6 @@ class HabitCardViewFactory fun create() = HabitCardView(context, checkmarkPanelFactory, numberPanelFactory, behavior) } -data class DelayedToggle( - var habit: Habit, - var timestamp: Timestamp, - var value: Int, - var notes: String -) - class HabitCardView( @ActivityContext context: Context, checkmarkPanelFactory: CheckmarkPanelViewFactory, @@ -136,7 +129,6 @@ class HabitCardView( private var scoreRing: RingView private var currentToggleTaskId = 0 - private var queuedToggles = mutableListOf() init { scoreRing = RingView(context).apply { @@ -160,12 +152,9 @@ class HabitCardView( } checkmarkPanel = checkmarkPanelFactory.create().apply { - onToggle = { timestamp, value, notes, delay -> - if (delay > 0) triggerRipple(timestamp) - habit?.let { - val taskId = queueToggle(it, timestamp, value, notes); - { runPendingToggles(taskId) }.delay(delay) - } + onToggle = { timestamp, value, notes -> + triggerRipple(timestamp) + habit?.let { behavior.onToggle(it, timestamp, value, notes) } } onEdit = { timestamp -> triggerRipple(timestamp) @@ -205,25 +194,6 @@ class HabitCardView( addView(innerFrame) } - @Synchronized - private fun runPendingToggles(id: Int) { - if (currentToggleTaskId != id) return - for ((h, t, v, n) in queuedToggles) behavior.onToggle(h, t, v, n) - queuedToggles.clear() - } - - @Synchronized - private fun queueToggle( - it: Habit, - timestamp: Timestamp, - value: Int, - notes: String, - ): Int { - currentToggleTaskId += 1 - queuedToggles.add(DelayedToggle(it, timestamp, value, notes)) - return currentToggleTaskId - } - override fun onModelChange() { Handler(Looper.getMainLooper()).post { habit?.let { copyAttributesFrom(it) } From 2131fb3a3ddff7ff9a4239259880c117c1bde657 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Tue, 24 Jan 2023 05:58:26 -0600 Subject: [PATCH 07/16] EntryList: Copy notes from original entries Fixes #1566 --- .../java/org/isoron/uhabits/core/models/EntryList.kt | 11 +++++++++-- .../org/isoron/uhabits/core/models/EntryListTest.kt | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/EntryList.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/EntryList.kt index 2d9662b2..774181e7 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/EntryList.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/EntryList.kt @@ -204,9 +204,16 @@ open class EntryList { // Copy original entries original.forEach { entry -> val offset = entry.timestamp.daysUntil(to) - if (result[offset].value == UNKNOWN || entry.value == SKIP || entry.value == YES_MANUAL) { - result[offset] = entry + val value = if ( + result[offset].value == UNKNOWN || + entry.value == SKIP || + entry.value == YES_MANUAL + ) { + entry.value + } else { + YES_AUTO } + result[offset] = Entry(entry.timestamp, value, entry.notes) } return result diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/EntryListTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/EntryListTest.kt index 9c7de4bb..c1f1bde2 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/EntryListTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/EntryListTest.kt @@ -217,7 +217,7 @@ class EntryListTest { fun testAddFromInterval() { val entries = listOf( Entry(day(1), YES_MANUAL), - Entry(day(2), NO), + Entry(day(2), NO, "Test"), Entry(day(4), NO), Entry(day(5), YES_MANUAL), Entry(day(10), YES_MANUAL), @@ -230,7 +230,7 @@ class EntryListTest { ) val expected = listOf( Entry(day(1), YES_MANUAL), - Entry(day(2), YES_AUTO), + Entry(day(2), YES_AUTO, "Test"), Entry(day(3), UNKNOWN), Entry(day(4), YES_AUTO), Entry(day(5), YES_MANUAL), From 71a05d598a483c1c28c2947e26d4b87d421df65a Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Mon, 30 Jan 2023 05:59:42 -0600 Subject: [PATCH 08/16] CheckmarkDialog: Switch to AppCompatDialogFragment Fixes issues with the soft keyboard covering the popup. --- .../common/dialogs/CheckmarkDialog.kt | 79 +++++++++++++++++++ .../habits/list/ListHabitsScreen.kt | 23 +++--- .../habits/show/ShowHabitActivity.kt | 21 +++-- .../org/isoron/uhabits/utils/DialogUtils.kt | 10 ++- .../src/main/res/layout/checkmark_popup.xml | 8 +- 5 files changed, 111 insertions(+), 30 deletions(-) create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt new file mode 100644 index 00000000..5df8ffd7 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2016-2021 Á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.activities.common.dialogs + +import android.app.Dialog +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View.GONE +import android.view.View.VISIBLE +import androidx.appcompat.app.AppCompatDialogFragment +import org.isoron.uhabits.HabitsApplication +import org.isoron.uhabits.R +import org.isoron.uhabits.core.models.Entry.Companion.NO +import org.isoron.uhabits.core.models.Entry.Companion.SKIP +import org.isoron.uhabits.core.models.Entry.Companion.UNKNOWN +import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL +import org.isoron.uhabits.databinding.CheckmarkPopupBinding +import org.isoron.uhabits.utils.InterfaceUtils.getFontAwesome +import org.isoron.uhabits.utils.sres + +class CheckmarkDialog : AppCompatDialogFragment() { + var onToggle: (Int, String) -> Unit = { _, _ -> } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val appComponent = (requireActivity().application as HabitsApplication).component + val prefs = appComponent.preferences + val view = CheckmarkPopupBinding.inflate(LayoutInflater.from(context)) + arrayOf(view.yesBtn, view.skipBtn).forEach { + it.setTextColor(requireArguments().getInt("color")) + } + arrayOf(view.noBtn, view.unknownBtn).forEach { + it.setTextColor(view.root.sres.getColor(R.attr.contrast60)) + } + arrayOf(view.yesBtn, view.noBtn, view.skipBtn, view.unknownBtn).forEach { + it.typeface = getFontAwesome(requireContext()) + } + view.notes.setText(requireArguments().getString("notes")!!) + if (!prefs.isSkipEnabled) view.skipBtn.visibility = GONE + if (!prefs.areQuestionMarksEnabled) view.unknownBtn.visibility = GONE + view.booleanButtons.visibility = VISIBLE + val dialog = Dialog(requireContext()) + dialog.setContentView(view.root) + dialog.window?.apply { + setBackgroundDrawableResource(android.R.color.transparent) + } + fun onClick(v: Int) { + val notes = view.notes.text.toString().trim() + onToggle(v, notes) + requireDialog().dismiss() + } + view.yesBtn.setOnClickListener { onClick(YES_MANUAL) } + view.noBtn.setOnClickListener { onClick(NO) } + view.skipBtn.setOnClickListener { onClick(SKIP) } + view.unknownBtn.setOnClickListener { onClick(UNKNOWN) } + view.notes.setOnEditorActionListener { v, actionId, event -> + onClick(requireArguments().getInt("value")) + true + } + + return dialog + } +} 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 73134297..8dda56a3 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 @@ -22,11 +22,12 @@ package org.isoron.uhabits.activities.habits.list import android.app.Activity import android.content.Context import android.content.Intent +import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import dagger.Lazy import org.isoron.platform.gui.toInt import org.isoron.uhabits.R -import org.isoron.uhabits.activities.common.dialogs.CheckmarkPopup +import org.isoron.uhabits.activities.common.dialogs.CheckmarkDialog import org.isoron.uhabits.activities.common.dialogs.ColorPickerDialogFactory import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialog import org.isoron.uhabits.activities.common.dialogs.NumberPopup @@ -252,18 +253,16 @@ class ListHabitsScreen color: PaletteColor, callback: ListHabitsBehavior.CheckMarkDialogCallback ) { - val view = rootView.get() - CheckmarkPopup( - context = context, - prefs = preferences, - anchor = view, - color = view.currentTheme().color(color).toInt(), - notes = notes, - value = selectedValue, - ).apply { - onToggle = { value, notes -> callback.onNotesSaved(value, notes) } - show() + val theme = rootView.get().currentTheme() + val fm = (context as AppCompatActivity).supportFragmentManager + val dialog = CheckmarkDialog() + dialog.arguments = Bundle().apply { + putInt("color", theme.color(color).toInt()) + putInt("value", selectedValue) + putString("notes", notes) } + dialog.onToggle = { v, n -> callback.onNotesSaved(v, n) } + dialog.dismissCurrentAndShow(fm, "checkmarkDialog") } private fun getExecuteString(command: Command): String? { diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt index b68dc1f3..b92f3a5b 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt @@ -34,7 +34,7 @@ import org.isoron.uhabits.HabitsApplication import org.isoron.uhabits.R import org.isoron.uhabits.activities.AndroidThemeSwitcher import org.isoron.uhabits.activities.HabitsDirFinder -import org.isoron.uhabits.activities.common.dialogs.CheckmarkPopup +import org.isoron.uhabits.activities.common.dialogs.CheckmarkDialog import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialog import org.isoron.uhabits.activities.common.dialogs.HistoryEditorDialog import org.isoron.uhabits.activities.common.dialogs.NumberPopup @@ -195,18 +195,15 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener { color: PaletteColor, callback: ListHabitsBehavior.CheckMarkDialogCallback ) { - val anchor = getPopupAnchor() ?: return - CheckmarkPopup( - context = this@ShowHabitActivity, - prefs = preferences, - notes = notes, - color = view.currentTheme().color(color).toInt(), - anchor = anchor, - value = selectedValue, - ).apply { - onToggle = { v, n -> callback.onNotesSaved(v, n) } - show() + val theme = view.currentTheme() + val dialog = CheckmarkDialog() + dialog.arguments = Bundle().apply { + putInt("color", theme.color(color).toInt()) + putInt("value", selectedValue) + putString("notes", notes) } + dialog.onToggle = { v, n -> callback.onNotesSaved(v, n) } + dialog.dismissCurrentAndShow(supportFragmentManager, "checkmarkDialog") } private fun getPopupAnchor(): View? { diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/utils/DialogUtils.kt b/uhabits-android/src/main/java/org/isoron/uhabits/utils/DialogUtils.kt index 00a17aa9..a1aefe16 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/utils/DialogUtils.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/utils/DialogUtils.kt @@ -6,20 +6,24 @@ import androidx.fragment.app.FragmentManager import java.lang.ref.WeakReference var currentDialog: WeakReference = WeakReference(null) +var currentDialogFragment: WeakReference = WeakReference(null) fun dismissCurrentDialog() { currentDialog.get()?.dismiss() + currentDialog = WeakReference(null) + currentDialogFragment.get()?.dismiss() + currentDialogFragment = WeakReference(null) } fun Dialog.dismissCurrentAndShow() { - currentDialog.get()?.dismiss() + dismissCurrentDialog() currentDialog = WeakReference(this) show() } fun DialogFragment.dismissCurrentAndShow(fragmentManager: FragmentManager, tag: String) { - currentDialog.get()?.dismiss() + dismissCurrentDialog() + currentDialogFragment = WeakReference(this) show(fragmentManager, tag) fragmentManager.executePendingTransactions() - currentDialog = WeakReference(this.dialog) } diff --git a/uhabits-android/src/main/res/layout/checkmark_popup.xml b/uhabits-android/src/main/res/layout/checkmark_popup.xml index 72dc7978..e21c2fb5 100644 --- a/uhabits-android/src/main/res/layout/checkmark_popup.xml +++ b/uhabits-android/src/main/res/layout/checkmark_popup.xml @@ -21,8 +21,10 @@ Date: Sat, 18 Mar 2023 05:04:43 -0500 Subject: [PATCH 09/16] Convert NumberDialog to AppCompatDialogFragment; remove unused classes --- .../common/dialogs/CheckmarkPopup.kt | 128 ----------------- .../activities/common/dialogs/NumberDialog.kt | 104 ++++++++++++++ .../activities/common/dialogs/NumberPopup.kt | 134 ------------------ .../habits/list/ListHabitsScreen.kt | 19 ++- .../habits/show/ShowHabitActivity.kt | 20 +-- .../screens/habits/show/views/HistoryCard.kt | 4 - 6 files changed, 119 insertions(+), 290 deletions(-) delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkPopup.kt create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberDialog.kt delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPopup.kt diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkPopup.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkPopup.kt deleted file mode 100644 index fb7f43d5..00000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkPopup.kt +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2016-2021 Á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.activities.common.dialogs - -import android.app.Dialog -import android.content.Context -import android.view.LayoutInflater -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import org.isoron.uhabits.R -import org.isoron.uhabits.core.models.Entry.Companion.NO -import org.isoron.uhabits.core.models.Entry.Companion.SKIP -import org.isoron.uhabits.core.models.Entry.Companion.UNKNOWN -import org.isoron.uhabits.core.models.Entry.Companion.YES_AUTO -import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL -import org.isoron.uhabits.core.preferences.Preferences -import org.isoron.uhabits.databinding.CheckmarkPopupBinding -import org.isoron.uhabits.utils.InterfaceUtils.getFontAwesome -import org.isoron.uhabits.utils.dimBehind -import org.isoron.uhabits.utils.dismissCurrentAndShow -import org.isoron.uhabits.utils.dp -import org.isoron.uhabits.utils.sres - -const val POPUP_WIDTH = 4 * 48f + 16f -const val POPUP_HEIGHT = 48f * 2.5f + 8f - -class CheckmarkPopup( - private val context: Context, - private val color: Int, - private var notes: String, - private var value: Int, - private val prefs: Preferences, - private val anchor: View, -) { - var onToggle: (Int, String) -> Unit = { _, _ -> } - private lateinit var dialog: Dialog - - private val view = CheckmarkPopupBinding.inflate(LayoutInflater.from(context)).apply { - // Required for round corners - container.clipToOutline = true - } - - init { - view.booleanButtons.visibility = VISIBLE - initColors() - initTypefaces() - hideDisabledButtons() - populate() - } - - private fun initColors() { - arrayOf(view.yesBtn, view.skipBtn).forEach { - it.setTextColor(color) - } - arrayOf(view.noBtn, view.unknownBtn).forEach { - it.setTextColor(view.root.sres.getColor(R.attr.contrast60)) - } - } - - private fun initTypefaces() { - arrayOf(view.yesBtn, view.noBtn, view.skipBtn, view.unknownBtn).forEach { - it.typeface = getFontAwesome(context) - } - } - - private fun hideDisabledButtons() { - if (!prefs.isSkipEnabled) view.skipBtn.visibility = GONE - if (!prefs.areQuestionMarksEnabled) view.unknownBtn.visibility = GONE - } - - private fun populate() { - val selectedBtn = when (value) { - YES_MANUAL -> view.yesBtn - YES_AUTO -> view.noBtn - NO -> view.noBtn - UNKNOWN -> if (prefs.areQuestionMarksEnabled) view.unknownBtn else view.noBtn - SKIP -> if (prefs.isSkipEnabled) view.skipBtn else view.noBtn - else -> null - } - view.notes.setText(notes) - } - - fun show() { - dialog = Dialog(context, android.R.style.Theme_NoTitleBar) - dialog.setContentView(view.root) - dialog.window?.apply { - setLayout( - view.root.dp(POPUP_WIDTH).toInt(), - view.root.dp(POPUP_HEIGHT).toInt() - ) - setBackgroundDrawableResource(android.R.color.transparent) - } - fun onClick(v: Int) { - this.value = v - save() - } - view.yesBtn.setOnClickListener { onClick(YES_MANUAL) } - view.noBtn.setOnClickListener { onClick(NO) } - view.skipBtn.setOnClickListener { onClick(SKIP) } - view.unknownBtn.setOnClickListener { onClick(UNKNOWN) } - dialog.setCanceledOnTouchOutside(true) - dialog.dimBehind() - dialog.dismissCurrentAndShow() - } - - fun save() { - onToggle(value, view.notes.text.toString().trim()) - dialog.dismiss() - } -} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberDialog.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberDialog.kt new file mode 100644 index 00000000..7e10baa5 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberDialog.kt @@ -0,0 +1,104 @@ +package org.isoron.uhabits.activities.common.dialogs + +import android.app.Dialog +import android.os.Bundle +import android.text.method.DigitsKeyListener +import android.view.KeyEvent +import android.view.LayoutInflater +import android.view.MotionEvent +import android.view.View +import androidx.appcompat.app.AppCompatDialogFragment +import org.isoron.uhabits.HabitsApplication +import org.isoron.uhabits.R +import org.isoron.uhabits.core.models.Entry +import org.isoron.uhabits.databinding.CheckmarkPopupBinding +import org.isoron.uhabits.utils.InterfaceUtils +import org.isoron.uhabits.utils.requestFocusWithKeyboard +import org.isoron.uhabits.utils.sres +import java.text.DecimalFormat +import java.text.DecimalFormatSymbols +import java.text.NumberFormat +import java.text.ParseException + +class NumberDialog : AppCompatDialogFragment() { + + var onToggle: (Double, String) -> Unit = { _, _ -> } + var onDismiss: () -> Unit = {} + + private var originalNotes: String = "" + private var originalValue: Double = 0.0 + private lateinit var view: CheckmarkPopupBinding + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val appComponent = (requireActivity().application as HabitsApplication).component + val prefs = appComponent.preferences + view = CheckmarkPopupBinding.inflate(LayoutInflater.from(context)) + arrayOf(view.yesBtn, view.skipBtn).forEach { + it.setTextColor(requireArguments().getInt("color")) + } + arrayOf(view.noBtn, view.unknownBtn).forEach { + it.setTextColor(view.root.sres.getColor(R.attr.contrast60)) + } + arrayOf(view.yesBtn, view.noBtn, view.skipBtn, view.unknownBtn).forEach { + it.typeface = InterfaceUtils.getFontAwesome(requireContext()) + } + if (!prefs.isSkipEnabled) view.skipBtnNumber.visibility = View.GONE + view.numberButtons.visibility = View.VISIBLE + fixDecimalSeparator(view) + originalNotes = requireArguments().getString("notes")!! + originalValue = requireArguments().getDouble("value") + view.notes.setText(originalNotes) + view.value.setText( + when { + originalValue < 0.01 -> "0" + else -> DecimalFormat("#.##").format(originalValue) + } + ) + view.value.setOnKeyListener { _, keyCode, event -> + if (event.action == MotionEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER) { + save() + return@setOnKeyListener true + } + return@setOnKeyListener false + } + view.saveBtn.setOnClickListener { + save() + } + view.skipBtnNumber.setOnClickListener { + view.value.setText((Entry.SKIP.toDouble() / 1000).toString()) + save() + } + view.notes.setOnEditorActionListener { v, actionId, event -> + save() + true + } + view.value.requestFocusWithKeyboard() + val dialog = Dialog(requireContext()) + dialog.setContentView(view.root) + dialog.window?.apply { + setBackgroundDrawableResource(android.R.color.transparent) + } + dialog.setOnDismissListener { onDismiss() } + return dialog + } + + private fun fixDecimalSeparator(view: CheckmarkPopupBinding) { + // https://stackoverflow.com/a/34256139 + val separator = DecimalFormatSymbols.getInstance().decimalSeparator + view.value.keyListener = DigitsKeyListener.getInstance("0123456789$separator") + } + + fun save() { + var value = originalValue + try { + val numberFormat = NumberFormat.getInstance() + val valueStr = view.value.text.toString() + value = numberFormat.parse(valueStr)!!.toDouble() + } catch (e: ParseException) { + // NOP + } + val notes = view.notes.text.toString() + onToggle(value, notes) + requireDialog().dismiss() + } +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPopup.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPopup.kt deleted file mode 100644 index f918fb26..00000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPopup.kt +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2016-2021 Á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.activities.common.dialogs - -import android.app.Dialog -import android.content.Context -import android.text.method.DigitsKeyListener -import android.view.KeyEvent.KEYCODE_ENTER -import android.view.LayoutInflater -import android.view.MotionEvent.ACTION_DOWN -import android.view.View -import android.view.View.GONE -import android.view.View.VISIBLE -import org.isoron.uhabits.core.models.Entry -import org.isoron.uhabits.core.preferences.Preferences -import org.isoron.uhabits.databinding.CheckmarkPopupBinding -import org.isoron.uhabits.utils.dimBehind -import org.isoron.uhabits.utils.dismissCurrentAndShow -import org.isoron.uhabits.utils.dp -import org.isoron.uhabits.utils.requestFocusWithKeyboard -import java.text.DecimalFormat -import java.text.DecimalFormatSymbols -import java.text.NumberFormat -import java.text.ParseException - -class NumberPopup( - private val context: Context, - private var notes: String, - private var value: Double, - private val prefs: Preferences, - private val anchor: View, -) { - var onToggle: (Double, String) -> Unit = { _, _ -> } - var onDismiss: () -> Unit = {} - private val originalValue = value - private lateinit var dialog: Dialog - - private val view = CheckmarkPopupBinding.inflate(LayoutInflater.from(context)).apply { - // Required for round corners - container.clipToOutline = true - } - - init { - view.numberButtons.visibility = VISIBLE - fixDecimalSeparator() - hideDisabledButtons() - populate() - } - - private fun fixDecimalSeparator() { - // https://stackoverflow.com/a/34256139 - val separator = DecimalFormatSymbols.getInstance().decimalSeparator - view.value.keyListener = DigitsKeyListener.getInstance("0123456789$separator") - } - - private fun hideDisabledButtons() { - if (!prefs.isSkipEnabled) view.skipBtnNumber.visibility = GONE - } - - private fun populate() { - view.notes.setText(notes) - view.value.setText( - when { - value < 0.01 -> "0" - else -> DecimalFormat("#.##").format(value) - } - ) - } - - fun show() { - dialog = Dialog(context, android.R.style.Theme_NoTitleBar) - dialog.setContentView(view.root) - dialog.window?.apply { - setLayout( - view.root.dp(POPUP_WIDTH).toInt(), - view.root.dp(POPUP_HEIGHT).toInt() - ) - setBackgroundDrawableResource(android.R.color.transparent) - } - dialog.setOnDismissListener { - onDismiss() - } - - view.value.setOnKeyListener { _, keyCode, event -> - if (event.action == ACTION_DOWN && keyCode == KEYCODE_ENTER) { - save() - return@setOnKeyListener true - } - return@setOnKeyListener false - } - view.saveBtn.setOnClickListener { - save() - } - view.skipBtnNumber.setOnClickListener { - view.value.setText((Entry.SKIP.toDouble() / 1000).toString()) - save() - } - view.value.requestFocusWithKeyboard() - dialog.setCanceledOnTouchOutside(true) - dialog.dimBehind() - dialog.dismissCurrentAndShow() - } - - fun save() { - var value = originalValue - try { - val numberFormat = NumberFormat.getInstance() - val valueStr = view.value.text.toString() - value = numberFormat.parse(valueStr)!!.toDouble() - } catch (e: ParseException) { - // NOP - } - val notes = view.notes.text.toString() - onToggle(value, notes) - dialog.dismiss() - } -} 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 8dda56a3..acbb8c10 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 @@ -30,7 +30,7 @@ import org.isoron.uhabits.R import org.isoron.uhabits.activities.common.dialogs.CheckmarkDialog import org.isoron.uhabits.activities.common.dialogs.ColorPickerDialogFactory import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialog -import org.isoron.uhabits.activities.common.dialogs.NumberPopup +import org.isoron.uhabits.activities.common.dialogs.NumberDialog import org.isoron.uhabits.activities.habits.edit.HabitTypeDialog import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter import org.isoron.uhabits.core.commands.ArchiveHabitsCommand @@ -234,17 +234,14 @@ class ListHabitsScreen notes: String, callback: ListHabitsBehavior.NumberPickerCallback ) { - val view = rootView.get() - NumberPopup( - context = context, - prefs = preferences, - anchor = view, - notes = notes, - value = value, - ).apply { - onToggle = { value, notes -> callback.onNumberPicked(value, notes) } - show() + val fm = (context as AppCompatActivity).supportFragmentManager + val dialog = NumberDialog() + dialog.arguments = Bundle().apply { + putDouble("value", value) + putString("notes", notes) } + dialog.onToggle = { v, n -> callback.onNumberPicked(v, n) } + dialog.dismissCurrentAndShow(fm, "numberDialog") } override fun showCheckmarkPopup( diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt index b92f3a5b..beb48809 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt @@ -37,7 +37,7 @@ import org.isoron.uhabits.activities.HabitsDirFinder import org.isoron.uhabits.activities.common.dialogs.CheckmarkDialog import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialog import org.isoron.uhabits.activities.common.dialogs.HistoryEditorDialog -import org.isoron.uhabits.activities.common.dialogs.NumberPopup +import org.isoron.uhabits.activities.common.dialogs.NumberDialog import org.isoron.uhabits.core.commands.Command import org.isoron.uhabits.core.commands.CommandRunner import org.isoron.uhabits.core.models.Habit @@ -172,26 +172,20 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener { override fun showNumberPopup( value: Double, notes: String, - preferences: Preferences, callback: ListHabitsBehavior.NumberPickerCallback ) { - val anchor = getPopupAnchor() ?: return - NumberPopup( - context = this@ShowHabitActivity, - prefs = preferences, - notes = notes, - anchor = anchor, - value = value, - ).apply { - onToggle = { v, n -> callback.onNumberPicked(v, n) } - show() + val dialog = NumberDialog() + dialog.arguments = Bundle().apply { + putDouble("value", value) + putString("notes", notes) } + dialog.onToggle = { v, n -> callback.onNumberPicked(v, n) } + dialog.dismissCurrentAndShow(supportFragmentManager, "numberDialog") } override fun showCheckmarkPopup( selectedValue: Int, notes: String, - preferences: Preferences, color: PaletteColor, callback: ListHabitsBehavior.CheckMarkDialogCallback ) { diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt index 7cde6f0d..8b612609 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt @@ -91,7 +91,6 @@ class HistoryCardPresenter( screen.showCheckmarkPopup( entry.value, entry.notes, - preferences, habit.color, ) { newValue, newNotes -> commandRunner.run( @@ -130,7 +129,6 @@ class HistoryCardPresenter( screen.showNumberPopup( value = oldValue / 1000.0, notes = entry.notes, - preferences = preferences, ) { newValue: Double, newNotes: String -> val thousands = (newValue * 1000).roundToInt() commandRunner.run( @@ -203,13 +201,11 @@ class HistoryCardPresenter( fun showNumberPopup( value: Double, notes: String, - preferences: Preferences, callback: ListHabitsBehavior.NumberPickerCallback, ) fun showCheckmarkPopup( selectedValue: Int, notes: String, - preferences: Preferences, color: PaletteColor, callback: ListHabitsBehavior.CheckMarkDialogCallback, ) From abead88cebd7641ae668f036555ef3fdfea6897e Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Wed, 22 Mar 2023 04:55:35 -0500 Subject: [PATCH 10/16] GH Actions: Fix build.sh --- build.sh | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/build.sh b/build.sh index 5c27503f..4dac8964 100755 --- a/build.sh +++ b/build.sh @@ -217,20 +217,28 @@ android_test_parallel() { ( LOG=build/android-test-$API.log log_info "API $API: Running tests..." - if android_test $API 1>$LOG 2>&1; then + android_test $API 1>$LOG 2>&1 + ret_code=$? + if [ $ret_code = 0 ]; then log_info "API $API: Passed" else log_error "API $API: Failed" fi pkill -9 -f ${AVD_PREFIX}${API} + exit $ret_code )& PIDS+=" $!" done # Check exit codes - RET_CODE=0 + success=0 for pid in $PIDS; do - wait $pid || RET_CODE=1 + wait $pid + ret_code=$? + if [ $ret_code != 0 ]; then + success=1 + fi + echo pid=$pid ret_code=$ret_code success=$success done # Print all logs @@ -240,7 +248,7 @@ android_test_parallel() { echo "::endgroup::" done - return $RET_CODE + return $success } android_build() { From b76da3575254b497f7c23e8a3151c6348f713e9d Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Fri, 24 Mar 2023 05:24:58 -0500 Subject: [PATCH 11/16] Widgets: Increase corner radius to match Android 12 --- .../isoron/uhabits/widgets/views/CheckmarkWidgetView.kt | 9 ++++----- .../org/isoron/uhabits/widgets/views/HabitWidgetView.kt | 2 +- .../main/res/drawable-v21/widget_button_background.xml | 2 +- uhabits-android/src/main/res/layout/widget_graph.xml | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkWidgetView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkWidgetView.kt index 57cff3dd..a0e45568 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkWidgetView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/CheckmarkWidgetView.kt @@ -66,23 +66,21 @@ class CheckmarkWidgetView : HabitWidgetView { val res = StyledResources(context) val bgColor: Int val fgColor: Int + setShadowAlpha(0x4f) when (entryState) { YES_MANUAL, SKIP -> { bgColor = activeColor fgColor = res.getColor(R.attr.contrast0) - setShadowAlpha(0x4f) backgroundPaint!!.color = bgColor frame!!.setBackgroundDrawable(background) } YES_AUTO, NO, UNKNOWN -> { bgColor = res.getColor(R.attr.cardBgColor) fgColor = res.getColor(R.attr.contrast60) - setShadowAlpha(0x00) } else -> { bgColor = res.getColor(R.attr.cardBgColor) fgColor = res.getColor(R.attr.contrast60) - setShadowAlpha(0x00) } } ring.setPercentage(percentage) @@ -126,7 +124,7 @@ class CheckmarkWidgetView : HabitWidgetView { } else { width = min(width, height) } - val textSize = min(0.2f * width, getDimension(context, R.dimen.smallerTextSize)) + val textSize = min(0.175f * width, getDimension(context, R.dimen.smallTextSize)) label.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) if (isNumerical) { ring.setTextSize(textSize * 0.9f) @@ -141,7 +139,8 @@ class CheckmarkWidgetView : HabitWidgetView { } private fun init() { - val appComponent: HabitsApplicationComponent = (context.applicationContext as HabitsApplication).component + val appComponent: HabitsApplicationComponent = + (context.applicationContext as HabitsApplication).component preferences = appComponent.preferences ring = findViewById(R.id.scoreRing) as RingView label = findViewById(R.id.label) as TextView diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/HabitWidgetView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/HabitWidgetView.kt index 85a21947..6756b8ac 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/HabitWidgetView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/HabitWidgetView.kt @@ -69,7 +69,7 @@ abstract class HabitWidgetView : FrameLayout { val shadowRadius = dpToPixels(context, 2f).toInt() val shadowOffset = dpToPixels(context, 1f).toInt() val shadowColor = Color.argb(shadowAlpha, 0, 0, 0) - val cornerRadius = dpToPixels(context, 5f) + val cornerRadius = dpToPixels(context, 12f) val radii = FloatArray(8) Arrays.fill(radii, cornerRadius) val shape = RoundRectShape(radii, null, null) diff --git a/uhabits-android/src/main/res/drawable-v21/widget_button_background.xml b/uhabits-android/src/main/res/drawable-v21/widget_button_background.xml index 9187c326..a5d8b5fb 100644 --- a/uhabits-android/src/main/res/drawable-v21/widget_button_background.xml +++ b/uhabits-android/src/main/res/drawable-v21/widget_button_background.xml @@ -28,7 +28,7 @@ - + diff --git a/uhabits-android/src/main/res/layout/widget_graph.xml b/uhabits-android/src/main/res/layout/widget_graph.xml index a96e9020..6ee9cfb8 100644 --- a/uhabits-android/src/main/res/layout/widget_graph.xml +++ b/uhabits-android/src/main/res/layout/widget_graph.xml @@ -35,7 +35,7 @@ android:paddingTop="4dp" android:paddingLeft="8dp" android:paddingRight="8dp" - android:paddingBottom="4dp" + android:paddingBottom="8dp" tools:ignore="UselessParent"> Date: Mon, 1 May 2023 18:52:53 -0500 Subject: [PATCH 12/16] Widgets: Remove option to create StackWidgets StackWidgets have been unfortunately been very unreliable on multiple phones, and fixing it does not appear to be simple. This commit removes the ability to create new StackWidgets, but existing ones should remain functional. --- .../widgets/activities/HabitPickerDialog.kt | 16 +++------------- .../res/layout/widget_configure_activity.xml | 6 ------ 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/HabitPickerDialog.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/HabitPickerDialog.kt index ff743816..67ad8ae2 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/HabitPickerDialog.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/HabitPickerDialog.kt @@ -24,7 +24,6 @@ import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID import android.appwidget.AppWidgetManager.INVALID_APPWIDGET_ID import android.content.Intent import android.os.Bundle -import android.widget.AbsListView.CHOICE_MODE_MULTIPLE import android.widget.ArrayAdapter import android.widget.Button import android.widget.ListView @@ -34,7 +33,6 @@ import org.isoron.uhabits.R import org.isoron.uhabits.activities.AndroidThemeSwitcher import org.isoron.uhabits.core.preferences.WidgetPreferences import org.isoron.uhabits.widgets.WidgetUpdater -import java.util.ArrayList class BooleanHabitPickerDialog : HabitPickerDialog() { override fun shouldHideNumerical() = true @@ -88,20 +86,12 @@ open class HabitPickerDialog : Activity() { with(listView) { adapter = ArrayAdapter( context, - android.R.layout.simple_list_item_multiple_choice, + android.R.layout.simple_list_item_1, habitNames ) - choiceMode = CHOICE_MODE_MULTIPLE - itemsCanFocus = false - } - saveButton.setOnClickListener { - val selectedIds = mutableListOf() - for (i in 0..listView.count) { - if (listView.isItemChecked(i)) { - selectedIds.add(habitIds[i]) - } + setOnItemClickListener { parent, view, position, id -> + confirm(mutableListOf(habitIds[position])) } - confirm(selectedIds) } } diff --git a/uhabits-android/src/main/res/layout/widget_configure_activity.xml b/uhabits-android/src/main/res/layout/widget_configure_activity.xml index ac32d91e..ba705346 100644 --- a/uhabits-android/src/main/res/layout/widget_configure_activity.xml +++ b/uhabits-android/src/main/res/layout/widget_configure_activity.xml @@ -30,10 +30,4 @@ android:layout_weight="1"> -