From 33468bfc1c5da2edc4e734d1e0f8919e57218b7f Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Sat, 5 Jun 2021 16:54:13 -0500 Subject: [PATCH 01/19] Improve automatic checkmarks for monthly habits Fixes #947 --- CHANGELOG.md | 4 ++ uhabits-android/build.gradle.kts | 4 +- .../common/dialogs/FrequencyPickerDialog.kt | 38 ++++++++++--------- .../habits/edit/EditHabitActivity.kt | 20 ++++++---- .../habits/show/views/SubtitleCardView.kt | 37 +++--------------- .../kotlin/org/isoron/platform/time/Dates.kt | 7 ++++ .../isoron/uhabits/core/models/EntryList.kt | 13 ++++++- 7 files changed, 62 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e87ad34a1..d93d8a7ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [2.0.3] - [Unreleased] +### Fixed +- Improve automatic checkmarks for monthly habits (@iSoron, 947) + ## [2.0.2] - 2021-05-23 ### Changed diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index 949adf793..5092498d5 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -37,8 +37,8 @@ android { compileSdkVersion(30) defaultConfig { - versionCode(20002) - versionName("2.0.2") + versionCode(20003) + versionName("2.0.3") minSdkVersion(23) targetSdkVersion(30) applicationId("org.isoron.uhabits") diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/FrequencyPickerDialog.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/FrequencyPickerDialog.kt index 0971ffab6..92754ca89 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/FrequencyPickerDialog.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/FrequencyPickerDialog.kt @@ -160,26 +160,28 @@ class FrequencyPickerDialog( private fun populateViews() { uncheckAll() - if (freqNumerator == 1) { - if (freqDenominator == 1) { - contentView.everyDayRadioButton.isChecked = true - } else { - contentView.everyXDaysRadioButton.isChecked = true - contentView.everyXDaysTextView.setText(freqDenominator.toString()) - focus(contentView.everyXDaysTextView) - } + if (freqDenominator == 30 || freqDenominator == 31) { + contentView.xTimesPerMonthRadioButton.isChecked = true + contentView.xTimesPerMonthTextView.setText(freqNumerator.toString()) + focus(contentView.xTimesPerMonthTextView) } else { - if (freqDenominator == 7) { - contentView.xTimesPerWeekRadioButton.isChecked = true - contentView.xTimesPerWeekTextView.setText(freqNumerator.toString()) - focus(contentView.xTimesPerWeekTextView) - } else if (freqDenominator == 30 || freqDenominator == 31) { - contentView.xTimesPerMonthRadioButton.isChecked = true - contentView.xTimesPerMonthTextView.setText(freqNumerator.toString()) - focus(contentView.xTimesPerMonthTextView) + if (freqNumerator == 1) { + if (freqDenominator == 1) { + contentView.everyDayRadioButton.isChecked = true + } else { + contentView.everyXDaysRadioButton.isChecked = true + contentView.everyXDaysTextView.setText(freqDenominator.toString()) + focus(contentView.everyXDaysTextView) + } } else { - Log.w("FrequencyPickerDialog", "Unknown frequency: $freqNumerator/$freqDenominator") - contentView.everyDayRadioButton.isChecked = true + if (freqDenominator == 7) { + contentView.xTimesPerWeekRadioButton.isChecked = true + contentView.xTimesPerWeekTextView.setText(freqNumerator.toString()) + focus(contentView.xTimesPerWeekTextView) + } else { + Log.w("FrequencyPickerDialog", "Unknown frequency: $freqNumerator/$freqDenominator") + contentView.everyDayRadioButton.isChecked = true + } } } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt index 289caa867..c5e432b1f 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt @@ -21,6 +21,7 @@ package org.isoron.uhabits.activities.habits.edit import android.annotation.SuppressLint import android.content.res.ColorStateList +import android.content.res.Resources import android.graphics.Color import android.os.Bundle import android.text.Html @@ -59,6 +60,16 @@ import org.isoron.uhabits.utils.formatTime import org.isoron.uhabits.utils.toFormattedString import org.isoron.uhabits.utils.toThemedAndroidColor +fun formatFrequency(freqNum: Int, freqDen: Int, resources: Resources) = when { + freqNum == 1 && (freqDen == 30 || freqDen == 31) -> resources.getString(R.string.every_month) + freqDen == 30 || freqDen == 31 -> resources.getString(R.string.x_times_per_month, freqNum) + freqNum == 1 && freqDen == 1 -> resources.getString(R.string.every_day) + freqNum == 1 && freqDen == 7 -> resources.getString(R.string.every_week) + freqNum == 1 && freqDen > 1 -> resources.getString(R.string.every_x_days, freqDen) + freqDen == 7 -> resources.getString(R.string.x_times_per_week, freqNum) + else -> "$freqNum/$freqDen" +} + class EditHabitActivity : AppCompatActivity() { private lateinit var themeSwitcher: AndroidThemeSwitcher @@ -299,14 +310,7 @@ class EditHabitActivity : AppCompatActivity() { @SuppressLint("StringFormatMatches") private fun populateFrequency() { - binding.booleanFrequencyPicker.text = when { - freqNum == 1 && freqDen == 1 -> getString(R.string.every_day) - freqNum == 1 && freqDen == 7 -> getString(R.string.every_week) - freqNum == 1 && freqDen > 1 -> getString(R.string.every_x_days, freqDen) - freqDen == 7 -> getString(R.string.x_times_per_week, freqNum) - freqDen == 30 || freqDen == 31 -> getString(R.string.x_times_per_month, freqNum) - else -> "$freqNum/$freqDen" - } + binding.booleanFrequencyPicker.text = formatFrequency(freqNum, freqDen, resources) binding.numericalFrequencyPicker.text = when (freqDen) { 1 -> getString(R.string.every_day) 7 -> getString(R.string.every_week) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardView.kt index 7b0cc407b..0673017e8 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardView.kt @@ -20,14 +20,13 @@ package org.isoron.uhabits.activities.habits.show.views import android.annotation.SuppressLint import android.content.Context -import android.content.res.Resources import android.util.AttributeSet import android.view.LayoutInflater import android.view.View import android.widget.LinearLayout import org.isoron.uhabits.R +import org.isoron.uhabits.activities.habits.edit.formatFrequency import org.isoron.uhabits.activities.habits.list.views.toShortString -import org.isoron.uhabits.core.models.Frequency import org.isoron.uhabits.core.ui.screens.habits.show.views.SubtitleCardState import org.isoron.uhabits.databinding.ShowHabitSubtitleBinding import org.isoron.uhabits.utils.InterfaceUtils @@ -49,7 +48,11 @@ class SubtitleCardView(context: Context, attrs: AttributeSet) : LinearLayout(con fun setState(state: SubtitleCardState) { val color = state.color.toThemedAndroidColor(context) val reminder = state.reminder - binding.frequencyLabel.text = state.frequency.format(resources) + binding.frequencyLabel.text = formatFrequency( + state.frequency.numerator, + state.frequency.denominator, + resources, + ) binding.questionLabel.setTextColor(color) binding.questionLabel.text = state.question binding.reminderLabel.text = if (reminder != null) { @@ -72,32 +75,4 @@ class SubtitleCardView(context: Context, attrs: AttributeSet) : LinearLayout(con postInvalidate() } - - @SuppressLint("StringFormatMatches") - private fun Frequency.format(resources: Resources): String { - val num = this.numerator - val den = this.denominator - if (num == den) { - return resources.getString(R.string.every_day) - } - if (den == 7) { - return resources.getString(R.string.x_times_per_week, num) - } - if (den == 30 || den == 31) { - return resources.getString(R.string.x_times_per_month, num) - } - if (num == 1) { - if (den == 7) { - return resources.getString(R.string.every_week) - } - if (den % 7 == 0) { - return resources.getString(R.string.every_x_weeks, den / 7) - } - if (den == 30 || den == 31) { - return resources.getString(R.string.every_month) - } - return resources.getString(R.string.every_x_days, den) - } - return "$num/$den" - } } diff --git a/uhabits-core/src/commonMain/kotlin/org/isoron/platform/time/Dates.kt b/uhabits-core/src/commonMain/kotlin/org/isoron/platform/time/Dates.kt index 5d440be90..22c2da753 100644 --- a/uhabits-core/src/commonMain/kotlin/org/isoron/platform/time/Dates.kt +++ b/uhabits-core/src/commonMain/kotlin/org/isoron/platform/time/Dates.kt @@ -72,6 +72,13 @@ data class LocalDate(val daysSince2000: Int) { return dayCache } + val monthLength: Int + get() = when (month) { + 4, 6, 9, 11 -> 30 + 2 -> if (isLeapYear(year)) 29 else 28 + else -> 31 + } + private fun updateYearMonthDayCache() { var currYear = 2000 var currDay = 0 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 76a2fabf8..b11baea24 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 @@ -248,8 +248,17 @@ open class EntryList { for (i in num - 1 until filtered.size) { val (begin, _) = filtered[i] val (center, _) = filtered[i - num + 1] - if (begin.daysUntil(center) < den) { - val end = begin.plus(den - 1) + var size = den + if (den == 30 || den == 31) { + val beginDate = begin.toLocalDate() + size = if (beginDate.day == beginDate.monthLength) { + beginDate.plus(1).monthLength + } else { + beginDate.monthLength + } + } + if (begin.daysUntil(center) < size) { + val end = begin.plus(size - 1) intervals.add(Interval(begin, center, end)) } } From 2fe3b1580650efb6794c86f13b9e5f8b399f8e32 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Sat, 5 Jun 2021 17:17:27 -0500 Subject: [PATCH 02/19] Fix small issues with the pure black theme --- CHANGELOG.md | 1 + .../org/isoron/uhabits/activities/AndroidThemeSwitcher.kt | 3 ++- .../isoron/uhabits/activities/settings/SettingsFragment.kt | 4 ++++ uhabits-android/src/main/res/values/styles.xml | 6 ++++++ .../jvmMain/java/org/isoron/uhabits/core/ui/views/Themes.kt | 6 ++++++ 5 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d93d8a7ee..33b160e22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [2.0.3] - [Unreleased] ### Fixed - Improve automatic checkmarks for monthly habits (@iSoron, 947) +- Fix small issues with the pure black theme (@iSoron) ## [2.0.2] - 2021-05-23 diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/AndroidThemeSwitcher.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/AndroidThemeSwitcher.kt index 855adaa84..be9d0eb02 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/AndroidThemeSwitcher.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/AndroidThemeSwitcher.kt @@ -30,6 +30,7 @@ import org.isoron.uhabits.core.preferences.Preferences import org.isoron.uhabits.core.ui.ThemeSwitcher import org.isoron.uhabits.core.ui.views.DarkTheme import org.isoron.uhabits.core.ui.views.LightTheme +import org.isoron.uhabits.core.ui.views.PureBlackTheme import org.isoron.uhabits.core.ui.views.Theme import org.isoron.uhabits.inject.ActivityContext import org.isoron.uhabits.inject.ActivityScope @@ -66,7 +67,7 @@ constructor( } override fun applyPureBlackTheme() { - currentTheme = DarkTheme() + currentTheme = PureBlackTheme() context.setTheme(R.style.AppBaseThemeDark_PureBlack) (context as Activity).window.navigationBarColor = ContextCompat.getColor(context, R.color.black) 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 cc8bcecfe..cf63f560c 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 @@ -27,6 +27,9 @@ import android.os.Build.VERSION import android.os.Bundle import android.provider.Settings import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup import androidx.preference.ListPreference import androidx.preference.Preference import androidx.preference.PreferenceCategory @@ -43,6 +46,7 @@ import org.isoron.uhabits.core.ui.NotificationTray 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.widgets.WidgetUpdater import java.util.Calendar diff --git a/uhabits-android/src/main/res/values/styles.xml b/uhabits-android/src/main/res/values/styles.xml index 2f8eb6e21..9bba46775 100644 --- a/uhabits-android/src/main/res/values/styles.xml +++ b/uhabits-android/src/main/res/values/styles.xml @@ -129,6 +129,7 @@ @drawable/selected_box @color/grey_100 @color/black + @style/PreferenceThemeOverlay.v14.Material.PureBlack + + +