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/39] 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 62a0489e2..49fb4c8b7 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/39] 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 c3a464311..f918fb267 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/39] 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 46bed95e5..94d30ad44 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/39] 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 e14bdefd5..875cdb941 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 b993d0d20..b68dc1f36 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 855f865c7..00a17aa9a 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/39] 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 fbbb7ffd1..60110ea3a 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 d23005c96..b8e2ba49b 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 35e459a27..43dad6954 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 5bace9378..4c1f73133 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 c7d1e92cae90ea911e65d3777fbf32662d553f46 Mon Sep 17 00:00:00 2001 From: Jakub Kalinowski Date: Mon, 12 Dec 2022 00:55:58 +0100 Subject: [PATCH 06/39] Issue 1589: Fixed crash after choosing Settings/Rate app when there's no Play Store on the device (#1590) * Using startActivitySafely when launching Play Store * Returning true for rateApp click --- .../activities/settings/SettingsFragment.kt | 30 ++++++++++++------- .../src/main/res/xml/preferences.xml | 4 +-- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.kt index 28fbd63d8..e67f6a567 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsFragment.kt @@ -22,6 +22,7 @@ import android.app.backup.BackupManager import android.content.Intent import android.content.SharedPreferences import android.content.SharedPreferences.OnSharedPreferenceChangeListener +import android.net.Uri import android.os.Bundle import android.provider.Settings import android.util.Log @@ -43,6 +44,7 @@ import org.isoron.uhabits.core.utils.DateUtils.Companion.getLongWeekdayNames import org.isoron.uhabits.notifications.AndroidNotificationTray.Companion.createAndroidNotificationChannel import org.isoron.uhabits.notifications.RingtoneManager import org.isoron.uhabits.utils.StyledResources +import org.isoron.uhabits.utils.startActivitySafely import org.isoron.uhabits.widgets.WidgetUpdater import java.util.Calendar @@ -92,16 +94,24 @@ class SettingsFragment : PreferenceFragmentCompat(), OnSharedPreferenceChangeLis override fun onPreferenceTreeClick(preference: Preference): Boolean { val key = preference.key ?: return false - if (key == "reminderSound") { - showRingtonePicker() - return true - } else if (key == "reminderCustomize") { - createAndroidNotificationChannel(requireContext()) - val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) - intent.putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName) - intent.putExtra(Settings.EXTRA_CHANNEL_ID, NotificationTray.REMINDERS_CHANNEL_ID) - startActivity(intent) - return true + when (key) { + "reminderSound" -> { + showRingtonePicker() + return true + } + "reminderCustomize" -> { + createAndroidNotificationChannel(requireContext()) + val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) + intent.putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName) + intent.putExtra(Settings.EXTRA_CHANNEL_ID, NotificationTray.REMINDERS_CHANNEL_ID) + startActivity(intent) + return true + } + "rateApp" -> { + val intent = Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.playStoreURL))) + activity?.startActivitySafely(intent) + return true + } } return super.onPreferenceTreeClick(preference) } diff --git a/uhabits-android/src/main/res/xml/preferences.xml b/uhabits-android/src/main/res/xml/preferences.xml index 5da126053..ad381b502 100644 --- a/uhabits-android/src/main/res/xml/preferences.xml +++ b/uhabits-android/src/main/res/xml/preferences.xml @@ -160,11 +160,9 @@ - Date: Sun, 18 Dec 2022 11:05:14 +0100 Subject: [PATCH 07/39] Issue 1576: Solving problems with habitbull import (#1591) * Recomputing the habit after import, corrected order of magnitude * Corrected HabitBullCSV3 test and added a new one --- uhabits-core/assets/test/habitbull4.csv | 3 +++ .../uhabits/core/io/HabitBullCSVImporter.kt | 4 +++- .../org/isoron/uhabits/core/io/ImportTest.kt | 19 +++++++++++++++++-- 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 uhabits-core/assets/test/habitbull4.csv diff --git a/uhabits-core/assets/test/habitbull4.csv b/uhabits-core/assets/test/habitbull4.csv new file mode 100644 index 000000000..b2fdf504a --- /dev/null +++ b/uhabits-core/assets/test/habitbull4.csv @@ -0,0 +1,3 @@ +HabitName,HabitDescription,HabitCategory,CalendarDate,Value,CommentText +Caffeine,,Coffee Consumption,2022-11-21,80, +Caffeine,,Coffee Consumption,2022-11-22,80, diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.kt index 4d47ca8c2..63f359115 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.kt @@ -86,10 +86,12 @@ class HabitBullCSVImporter logger.info("Found a value of $value, considering this habit as numerical.") h.type = HabitType.NUMERICAL } - h.originalEntries.add(Entry(timestamp, value, notes)) + h.originalEntries.add(Entry(timestamp, value * 1000, notes)) } } } + + map.forEach { (_, habit) -> habit.recompute() } } private fun parseTimestamp(rawValue: String): Timestamp { diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/io/ImportTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/io/ImportTest.kt index b8949d4b0..9c53d149c 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/io/ImportTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/io/ImportTest.kt @@ -85,8 +85,8 @@ class ImportTest : BaseUnitTest() { assertThat(habit.type, equalTo(HabitType.NUMERICAL)) assertThat(habit.description, equalTo("")) assertThat(habit.frequency, equalTo(Frequency.DAILY)) - assertThat(getValue(habit, 2021, 9, 1), equalTo(30)) - assertThat(getValue(habit, 2022, 1, 8), equalTo(100)) + assertThat(getValue(habit, 2021, 9, 1), equalTo(30000)) + assertThat(getValue(habit, 2022, 1, 8), equalTo(100000)) val habit2 = habitList.getByPosition(1) assertThat(habit2.name, equalTo("run")) @@ -98,6 +98,21 @@ class ImportTest : BaseUnitTest() { assertTrue(isChecked(habit2, 2022, 1, 19)) } + @Test + @Throws(IOException::class) + fun testHabitBullCSV4() { + importFromFile("habitbull4.csv") + assertThat(habitList.size(), equalTo(1)) + + val habit = habitList.getByPosition(0) + assertThat(habit.name, equalTo("Caffeine")) + assertThat(habit.type, equalTo(HabitType.NUMERICAL)) + assertThat(habit.description, equalTo("")) + assertThat(habit.frequency, equalTo(Frequency.DAILY)) + assertThat(getValue(habit, 2022, 11, 21), equalTo(80000)) + assertThat(getValue(habit, 2022, 11, 22), equalTo(80000)) + } + @Test @Throws(IOException::class) fun testLoopDB() { From c423d2b3ca26be635b60f479ae0749b39fd13d7d Mon Sep 17 00:00:00 2001 From: Jakub Kalinowski Date: Sun, 18 Dec 2022 11:25:06 +0100 Subject: [PATCH 08/39] Issue 1574: Fixed the almost invisible watch hands in snooze activity (#1592) * Setting the current theme correctly * Ktlint correction --- .../SnoozeDelayPickerActivity.kt | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.kt index 42514b118..f1723ee16 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.kt @@ -33,7 +33,8 @@ import org.isoron.uhabits.HabitsApplication import org.isoron.uhabits.R import org.isoron.uhabits.activities.AndroidThemeSwitcher import org.isoron.uhabits.core.models.Habit -import org.isoron.uhabits.core.ui.ThemeSwitcher.Companion.THEME_LIGHT +import org.isoron.uhabits.core.ui.views.DarkTheme +import org.isoron.uhabits.core.ui.views.LightTheme import org.isoron.uhabits.receivers.ReminderController import org.isoron.uhabits.utils.SystemUtils import java.util.Calendar @@ -51,11 +52,8 @@ class SnoozeDelayPickerActivity : FragmentActivity(), OnItemClickListener { val app = applicationContext as HabitsApplication val appComponent = app.component val themeSwitcher = AndroidThemeSwitcher(this, appComponent.preferences) - if (themeSwitcher.getSystemTheme() == THEME_LIGHT) { - setTheme(R.style.BaseDialog) - } else { - setTheme(R.style.BaseDialogDark) - } + themeSwitcher.setTheme() + val data = intent.data if (data == null) { finish() @@ -75,6 +73,16 @@ class SnoozeDelayPickerActivity : FragmentActivity(), OnItemClickListener { SystemUtils.unlockScreen(this) } + private fun AndroidThemeSwitcher.setTheme() { + if (this.isNightMode) { + setTheme(R.style.BaseDialogDark) + this.currentTheme = DarkTheme() + } else { + setTheme(R.style.BaseDialog) + this.currentTheme = LightTheme() + } + } + private fun showTimePicker() { val calendar = Calendar.getInstance() val dialog = TimePickerDialog.newInstance( From 6f7215b46f2c99fd03dd762212fdad312a5b85fe Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Sun, 18 Dec 2022 04:39:01 -0600 Subject: [PATCH 09/39] Update dependencies --- build.gradle.kts | 2 +- uhabits-android/build.gradle.kts | 8 ++++---- uhabits-core/build.gradle.kts | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 8bf47ca61..ebfccb5e6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,6 @@ plugins { val kotlinVersion = "1.7.21" - id("com.android.application") version ("7.3.0-rc01") apply (false) + id("com.android.application") version ("7.3.1") apply (false) id("org.jetbrains.kotlin.android") version kotlinVersion apply (false) id("org.jetbrains.kotlin.kapt") version kotlinVersion apply (false) id("org.jetbrains.kotlin.android.extensions") version kotlinVersion apply (false) diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index 4c9ba6348..103eb4e2a 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -92,10 +92,10 @@ dependencies { androidTestImplementation("com.linkedin.dexmaker:dexmaker-mockito:2.28.3") androidTestImplementation("io.ktor:ktor-client-mock:$ktorVersion") androidTestImplementation("io.ktor:ktor-jackson:$ktorVersion") - androidTestImplementation("androidx.annotation:annotation:1.4.0") - androidTestImplementation("androidx.test.ext:junit:1.1.3") + androidTestImplementation("androidx.annotation:annotation:1.5.0") + androidTestImplementation("androidx.test.ext:junit:1.1.4") androidTestImplementation("androidx.test.uiautomator:uiautomator:2.2.0") - androidTestImplementation("androidx.test:rules:1.4.0") + androidTestImplementation("androidx.test:rules:1.5.0") androidTestImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0") compileOnly("javax.annotation:jsr250-api:1.0") coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.2.2") @@ -113,7 +113,7 @@ dependencies { implementation("androidx.appcompat:appcompat:1.5.1") implementation("androidx.legacy:legacy-preference-v14:1.0.0") implementation("androidx.legacy:legacy-support-v4:1.0.0") - implementation("com.google.android.material:material:1.6.1") + implementation("com.google.android.material:material:1.7.0") implementation("com.opencsv:opencsv:5.7.1") implementation(project(":uhabits-core")) kapt("com.google.dagger:dagger-compiler:$daggerVersion") diff --git a/uhabits-core/build.gradle.kts b/uhabits-core/build.gradle.kts index de02b2fb8..9617c2569 100644 --- a/uhabits-core/build.gradle.kts +++ b/uhabits-core/build.gradle.kts @@ -45,9 +45,9 @@ kotlin { implementation(kotlin("stdlib-jdk8")) compileOnly("com.google.dagger:dagger:2.43.2") implementation("com.google.guava:guava:31.1-android") - implementation("org.jetbrains.kotlin:kotlin-stdlib:1.7.10") + implementation("org.jetbrains.kotlin:kotlin-stdlib:1.7.21") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4") - implementation("androidx.annotation:annotation:1.4.0") + implementation("androidx.annotation:annotation:1.5.0") implementation("com.google.code.findbugs:jsr305:3.0.2") implementation("com.opencsv:opencsv:5.7.1") implementation("commons-codec:commons-codec:1.15") @@ -59,7 +59,7 @@ kotlin { dependencies { implementation(kotlin("test")) implementation(kotlin("test-junit")) - implementation("org.xerial:sqlite-jdbc:3.39.3.0") + implementation("org.xerial:sqlite-jdbc:3.40.0.0") implementation("org.hamcrest:hamcrest:2.2") implementation("org.apache.commons:commons-io:1.3.2") implementation("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0") From d95084500ffef7b45e3a7d7e655d5d9c7a543a30 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Dec 2022 04:10:18 -0600 Subject: [PATCH 10/39] Bump daggerVersion from 2.43.2 to 2.44.2 (#1582) Bumps `daggerVersion` from 2.43.2 to 2.44.2. Updates `dagger` from 2.43.2 to 2.44.2 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.43.2...dagger-2.44.2) Updates `dagger-compiler` from 2.43.2 to 2.44.2 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.43.2...dagger-2.44.2) --- updated-dependencies: - dependency-name: com.google.dagger:dagger dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.google.dagger:dagger-compiler dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uhabits-android/build.gradle.kts | 2 +- uhabits-core/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index 103eb4e2a..4c6075c22 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -80,7 +80,7 @@ android { } dependencies { - val daggerVersion = "2.43.2" + val daggerVersion = "2.44.2" val kotlinVersion = "1.7.21" val kxCoroutinesVersion = "1.6.4" val ktorVersion = "1.6.8" diff --git a/uhabits-core/build.gradle.kts b/uhabits-core/build.gradle.kts index 9617c2569..232951d4e 100644 --- a/uhabits-core/build.gradle.kts +++ b/uhabits-core/build.gradle.kts @@ -43,7 +43,7 @@ kotlin { val jvmMain by getting { dependencies { implementation(kotlin("stdlib-jdk8")) - compileOnly("com.google.dagger:dagger:2.43.2") + compileOnly("com.google.dagger:dagger:2.44.2") implementation("com.google.guava:guava:31.1-android") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.7.21") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4") From dc678e59df029b829381ad290b6b133394861f24 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Fri, 23 Dec 2022 10:31:30 -0600 Subject: [PATCH 11/39] GH Actions: Set job timeout --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b42512d32..4a301299f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,6 +9,7 @@ on: jobs: Test: runs-on: self-hosted + timeout-minutes: 30 steps: - name: Check out source code uses: actions/checkout@v1 From 1470dcd560938398cab74b1e3039c4d005324024 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Mon, 23 Jan 2023 03:50:38 -0600 Subject: [PATCH 12/39] 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 f37cc1838..32df08758 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 f09c48dba..de955deb8 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 176cec62a..39faa0283 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 35f639691..525dac5ad 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 424aae50b..189c5c532 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 13/39] 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 2d9662b21..774181e7d 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 9c7de4bb3..c1f1bde2d 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 14/39] 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 000000000..5df8ffd7b --- /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 731342974..8dda56a3d 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 b68dc1f36..b92f3a5b1 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 00a17aa9a..a1aefe16f 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 72dc79786..e21c2fb54 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: Sun, 1 Jan 2023 03:02:42 +0000 Subject: [PATCH 15/39] Bump espressoVersion from 3.4.0 to 3.5.0 Bumps `espressoVersion` from 3.4.0 to 3.5.0. Updates `espresso-contrib` from 3.4.0 to 3.5.0 Updates `espresso-core` from 3.4.0 to 3.5.0 --- updated-dependencies: - dependency-name: androidx.test.espresso:espresso-contrib dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: androidx.test.espresso:espresso-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- uhabits-android/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index 4c6075c22..641161d2b 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -84,7 +84,7 @@ dependencies { val kotlinVersion = "1.7.21" val kxCoroutinesVersion = "1.6.4" val ktorVersion = "1.6.8" - val espressoVersion = "3.4.0" + val espressoVersion = "3.5.0" androidTestImplementation("androidx.test.espresso:espresso-contrib:$espressoVersion") androidTestImplementation("androidx.test.espresso:espresso-core:$espressoVersion") From 856a0726f72ddb9efb64fbd5f5ed209e102a4080 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Jan 2023 03:03:08 +0000 Subject: [PATCH 16/39] Bump logback-classic from 1.4.4 to 1.4.5 Bumps [logback-classic](https://github.com/qos-ch/logback) from 1.4.4 to 1.4.5. - [Release notes](https://github.com/qos-ch/logback/releases) - [Commits](https://github.com/qos-ch/logback/compare/v_1.4.4...v_1.4.5) --- updated-dependencies: - dependency-name: ch.qos.logback:logback-classic dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- uhabits-server/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uhabits-server/build.gradle.kts b/uhabits-server/build.gradle.kts index 6de8c8836..9a59b33a8 100644 --- a/uhabits-server/build.gradle.kts +++ b/uhabits-server/build.gradle.kts @@ -35,7 +35,7 @@ application { dependencies { val ktorVersion = "1.6.8" val kotlinVersion = "1.7.21" - val logbackVersion = "1.4.4" + val logbackVersion = "1.4.5" implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion") implementation("io.ktor:ktor-server-netty:$ktorVersion") implementation("ch.qos.logback:logback-classic:$logbackVersion") From 908eb4ac9912ae4b1cb2cb668ddac13ec2552e30 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Sat, 18 Mar 2023 05:04:43 -0500 Subject: [PATCH 17/39] 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 fb7f43d51..000000000 --- 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 000000000..7e10baa51 --- /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 f918fb267..000000000 --- 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 8dda56a3d..acbb8c102 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 b92f3a5b1..beb488095 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 7cde6f0d1..8b6126090 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 18/39] GH Actions: Fix build.sh --- build.sh | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/build.sh b/build.sh index 5c27503fa..4dac8964f 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 19/39] 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 57cff3ddb..a0e455688 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 85a219479..6756b8acd 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 9187c326a..a5d8b5fbf 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 a96e90209..6ee9cfb8b 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, 20 Mar 2023 12:31:10 +0000 Subject: [PATCH 20/39] Bump com.google.android.material:material from 1.7.0 to 1.8.0 Bumps [com.google.android.material:material](https://github.com/material-components/material-components-android) from 1.7.0 to 1.8.0. - [Release notes](https://github.com/material-components/material-components-android/releases) - [Commits](https://github.com/material-components/material-components-android/compare/1.7.0...1.8.0) --- updated-dependencies: - dependency-name: com.google.android.material:material dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- uhabits-android/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index 641161d2b..c16a070a0 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -113,7 +113,7 @@ dependencies { implementation("androidx.appcompat:appcompat:1.5.1") implementation("androidx.legacy:legacy-preference-v14:1.0.0") implementation("androidx.legacy:legacy-support-v4:1.0.0") - implementation("com.google.android.material:material:1.7.0") + implementation("com.google.android.material:material:1.8.0") implementation("com.opencsv:opencsv:5.7.1") implementation(project(":uhabits-core")) kapt("com.google.dagger:dagger-compiler:$daggerVersion") From eb68220b8dbcc48ebee364a7f3ba5dcc133b1c06 Mon Sep 17 00:00:00 2001 From: Quentin Hibon Date: Sun, 26 Mar 2023 19:48:12 +0200 Subject: [PATCH 21/39] Remove dependency on kotlin stdlib (#1669) According to: https://kotlinlang.org/docs/whatsnew14.html#dependency-on-the-standard-library-added-by-default the explicit dependency is no longer needed. --- uhabits-core/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/uhabits-core/build.gradle.kts b/uhabits-core/build.gradle.kts index 232951d4e..cdb6c65ad 100644 --- a/uhabits-core/build.gradle.kts +++ b/uhabits-core/build.gradle.kts @@ -45,7 +45,6 @@ kotlin { implementation(kotlin("stdlib-jdk8")) compileOnly("com.google.dagger:dagger:2.44.2") implementation("com.google.guava:guava:31.1-android") - implementation("org.jetbrains.kotlin:kotlin-stdlib:1.7.21") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4") implementation("androidx.annotation:annotation:1.5.0") implementation("com.google.code.findbugs:jsr305:3.0.2") From c609eceefc8a3a903587c018cbc34de34fc1fb6e Mon Sep 17 00:00:00 2001 From: Adrian Miozga Date: Sun, 26 Mar 2023 19:48:53 +0200 Subject: [PATCH 22/39] Update Play Store and F-Droid badges (#1668) * Update Play Store and F-Droid badges * Increase size of badges --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 19e411c3a..9ebbb7380 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ show you how your habits improved over time. It is completely ad-free and open source.

- Get it on Google Play - Get it on F-Droid + Get it on Google Play + Get it on F-Droid

## Screenshots From d0f32dfa0a23daced97dc706ab9cb7796496eaa4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Apr 2023 04:01:06 +0000 Subject: [PATCH 23/39] Bump espressoVersion from 3.5.0 to 3.5.1 Bumps `espressoVersion` from 3.5.0 to 3.5.1. Updates `androidx.test.espresso:espresso-contrib` from 3.5.0 to 3.5.1 Updates `androidx.test.espresso:espresso-core` from 3.5.0 to 3.5.1 --- updated-dependencies: - dependency-name: androidx.test.espresso:espresso-contrib dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: androidx.test.espresso:espresso-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- uhabits-android/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index c16a070a0..f974cca65 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -84,7 +84,7 @@ dependencies { val kotlinVersion = "1.7.21" val kxCoroutinesVersion = "1.6.4" val ktorVersion = "1.6.8" - val espressoVersion = "3.5.0" + val espressoVersion = "3.5.1" androidTestImplementation("androidx.test.espresso:espresso-contrib:$espressoVersion") androidTestImplementation("androidx.test.espresso:espresso-core:$espressoVersion") From 9d4df73c56d858bd3cf7baa35b10bb65e68eb554 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Apr 2023 03:56:33 +0000 Subject: [PATCH 24/39] Bump androidx.test.ext:junit from 1.1.4 to 1.1.5 Bumps androidx.test.ext:junit from 1.1.4 to 1.1.5. --- updated-dependencies: - dependency-name: androidx.test.ext:junit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- uhabits-android/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index f974cca65..8a2255c6d 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -93,7 +93,7 @@ dependencies { androidTestImplementation("io.ktor:ktor-client-mock:$ktorVersion") androidTestImplementation("io.ktor:ktor-jackson:$ktorVersion") androidTestImplementation("androidx.annotation:annotation:1.5.0") - androidTestImplementation("androidx.test.ext:junit:1.1.4") + androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.uiautomator:uiautomator:2.2.0") androidTestImplementation("androidx.test:rules:1.5.0") androidTestImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0") From 499eb467cb92665dffbb5f3a9c1e72e230c10af3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 03:56:45 +0000 Subject: [PATCH 25/39] Bump daggerVersion from 2.44.2 to 2.46 Bumps `daggerVersion` from 2.44.2 to 2.46. Updates `com.google.dagger:dagger` from 2.44.2 to 2.46 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.44.2...dagger-2.46) Updates `com.google.dagger:dagger-compiler` from 2.44.2 to 2.46 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.44.2...dagger-2.46) --- updated-dependencies: - dependency-name: com.google.dagger:dagger dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.google.dagger:dagger-compiler dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- uhabits-android/build.gradle.kts | 2 +- uhabits-core/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index 8a2255c6d..034737650 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -80,7 +80,7 @@ android { } dependencies { - val daggerVersion = "2.44.2" + val daggerVersion = "2.46" val kotlinVersion = "1.7.21" val kxCoroutinesVersion = "1.6.4" val ktorVersion = "1.6.8" diff --git a/uhabits-core/build.gradle.kts b/uhabits-core/build.gradle.kts index cdb6c65ad..c0854f067 100644 --- a/uhabits-core/build.gradle.kts +++ b/uhabits-core/build.gradle.kts @@ -43,7 +43,7 @@ kotlin { val jvmMain by getting { dependencies { implementation(kotlin("stdlib-jdk8")) - compileOnly("com.google.dagger:dagger:2.44.2") + compileOnly("com.google.dagger:dagger:2.46") implementation("com.google.guava:guava:31.1-android") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4") implementation("androidx.annotation:annotation:1.5.0") From 1df9cc7664c9f896ddedff8ecfd5f2f35afb0d1f Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Mon, 1 May 2023 18:52:53 -0500 Subject: [PATCH 26/39] 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 ff743816b..67ad8ae2d 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 ac32d91e9..ba7053467 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"> -