diff --git a/CHANGELOG.md b/CHANGELOG.md index e87ad34a1..0f2e30097 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [2.0.3] - 2021-08-21 +### Fixed +- Improve automatic checkmarks for monthly habits (@iSoron, #947) +- Fix small theme issues (@iSoron) +- Fix ANR on some Samsung phones (@iSoron, #962) +- Fix dates before the year 2000 (@iSoron, #967) +- Fix notification adding checkmarks to the wrong day (@hiqua, #969) +- Fix crashes in widgets (@hiqua, @iSoron, #907, #966, #965) +- Fix crash when moving habits (@hiqua, #968) + ## [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/androidTest/assets/views/widgets/CheckmarkWidget/render.png b/uhabits-android/src/androidTest/assets/views/widgets/CheckmarkWidget/render.png index 561cf25f8..642264b62 100644 Binary files a/uhabits-android/src/androidTest/assets/views/widgets/CheckmarkWidget/render.png and b/uhabits-android/src/androidTest/assets/views/widgets/CheckmarkWidget/render.png differ diff --git a/uhabits-android/src/androidTest/assets/views/widgets/CheckmarkWidgetView/checked.png b/uhabits-android/src/androidTest/assets/views/widgets/CheckmarkWidgetView/checked.png index 9548f9994..f5a3df56e 100644 Binary files a/uhabits-android/src/androidTest/assets/views/widgets/CheckmarkWidgetView/checked.png and b/uhabits-android/src/androidTest/assets/views/widgets/CheckmarkWidgetView/checked.png differ diff --git a/uhabits-android/src/androidTest/assets/views/widgets/CheckmarkWidgetView/large_size.png b/uhabits-android/src/androidTest/assets/views/widgets/CheckmarkWidgetView/large_size.png index 5d29f56c8..ea1aab565 100644 Binary files a/uhabits-android/src/androidTest/assets/views/widgets/CheckmarkWidgetView/large_size.png and b/uhabits-android/src/androidTest/assets/views/widgets/CheckmarkWidgetView/large_size.png differ diff --git a/uhabits-android/src/androidTest/assets/views/widgets/TargetWidget/render.png b/uhabits-android/src/androidTest/assets/views/widgets/TargetWidget/render.png index 739e0fca3..4a8fa7f9f 100644 Binary files a/uhabits-android/src/androidTest/assets/views/widgets/TargetWidget/render.png and b/uhabits-android/src/androidTest/assets/views/widgets/TargetWidget/render.png differ diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/common/views/ScoreChartTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/common/views/ScoreChartTest.kt index bcd4a18dd..3d71853ec 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/common/views/ScoreChartTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/common/views/ScoreChartTest.kt @@ -23,6 +23,7 @@ import androidx.test.filters.MediumTest import org.isoron.uhabits.BaseViewTest import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.ui.screens.habits.show.views.ScoreCardPresenter.Companion.buildState +import org.isoron.uhabits.core.ui.views.LightTheme import org.isoron.uhabits.utils.toFixedAndroidColor import org.junit.Before import org.junit.Test @@ -39,7 +40,12 @@ class ScoreChartTest : BaseViewTest() { super.setUp() fixtures.purgeHabits(habitList) habit = fixtures.createLongHabit() - val state = buildState(habit, prefs.firstWeekdayInt, 0) + val state = buildState( + habit = habit, + firstWeekday = prefs.firstWeekdayInt, + spinnerPosition = 0, + theme = LightTheme(), + ) view = ScoreChart(targetContext).apply { setScores(state.scores) setColor(state.color.toFixedAndroidColor()) @@ -72,7 +78,7 @@ class ScoreChartTest : BaseViewTest() { @Test @Throws(Throwable::class) fun testRender_withMonthlyBucket() { - val (scores, bucketSize) = buildState(habit, prefs.firstWeekdayInt, 2) + val (scores, bucketSize) = buildState(habit, prefs.firstWeekdayInt, 2, LightTheme()) view.setScores(scores) view.setBucketSize(bucketSize) view.invalidate() @@ -89,7 +95,7 @@ class ScoreChartTest : BaseViewTest() { @Test @Throws(Throwable::class) fun testRender_withYearlyBucket() { - val state = buildState(habit, prefs.firstWeekdayInt, 4) + val state = buildState(habit, prefs.firstWeekdayInt, 4, LightTheme()) view.setScores(state.scores) view.setBucketSize(state.bucketSize) view.invalidate() diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardViewTest.kt index 2d9b2687c..c26b55775 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardViewTest.kt @@ -25,6 +25,7 @@ import androidx.test.filters.MediumTest import org.isoron.uhabits.BaseViewTest import org.isoron.uhabits.R import org.isoron.uhabits.core.ui.screens.habits.show.views.FrequencyCardPresenter +import org.isoron.uhabits.core.ui.views.LightTheme import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -43,7 +44,13 @@ class FrequencyCardViewTest : BaseViewTest() { .from(targetContext) .inflate(R.layout.show_habit, null) .findViewById(R.id.frequencyCard) as FrequencyCardView - view.setState(FrequencyCardPresenter.buildState(habit = habit, firstWeekday = 0)) + view.setState( + FrequencyCardPresenter.buildState( + habit = habit, + firstWeekday = 0, + theme = LightTheme(), + ) + ) measureView(view, 800f, 600f) } diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/OverviewCardViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/OverviewCardViewTest.kt index 46efbc146..9a5fc81d3 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/OverviewCardViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/OverviewCardViewTest.kt @@ -26,6 +26,7 @@ import org.isoron.uhabits.BaseViewTest import org.isoron.uhabits.R import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.core.ui.screens.habits.show.views.OverviewCardState +import org.isoron.uhabits.core.ui.views.LightTheme import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -50,6 +51,7 @@ class OverviewCardViewTest : BaseViewTest() { scoreYearDiff = 0.74f, totalCount = 44, color = PaletteColor(7), + theme = LightTheme(), ) ) measureView(view, 800f, 300f) diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/ScoreCardViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/ScoreCardViewTest.kt index b695c3a7b..8bd2bc520 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/ScoreCardViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/ScoreCardViewTest.kt @@ -25,6 +25,7 @@ import androidx.test.filters.MediumTest import org.isoron.uhabits.BaseViewTest import org.isoron.uhabits.R import org.isoron.uhabits.core.ui.screens.habits.show.views.ScoreCardPresenter.Companion.buildState +import org.isoron.uhabits.core.ui.views.LightTheme import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -43,7 +44,14 @@ class ScoreCardViewTest : BaseViewTest() { .from(targetContext) .inflate(R.layout.show_habit, null) .findViewById(R.id.scoreCard) as ScoreCardView - view.setState(buildState(habit = habit, firstWeekday = 0, spinnerPosition = 0)) + view.setState( + buildState( + habit = habit, + firstWeekday = 0, + spinnerPosition = 0, + theme = LightTheme(), + ) + ) measureView(view, 800f, 600f) } diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/StreakCardViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/StreakCardViewTest.kt index ebf581a04..2c70e3b92 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/StreakCardViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/StreakCardViewTest.kt @@ -25,6 +25,7 @@ import androidx.test.filters.MediumTest import org.isoron.uhabits.BaseViewTest import org.isoron.uhabits.R import org.isoron.uhabits.core.ui.screens.habits.show.views.StreakCardState +import org.isoron.uhabits.core.ui.views.LightTheme import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -47,6 +48,7 @@ class StreakCardViewTest : BaseViewTest() { StreakCardState( bestStreaks = habit.streaks.getBest(10), color = habit.color, + theme = LightTheme(), ) ) measureView(view, 800f, 600f) diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardViewTest.kt index 63c700404..a43543936 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardViewTest.kt @@ -28,6 +28,7 @@ import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.core.models.Reminder import org.isoron.uhabits.core.models.WeekdayList.Companion.EVERY_DAY import org.isoron.uhabits.core.ui.screens.habits.show.views.SubtitleCardState +import org.isoron.uhabits.core.ui.views.LightTheme import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -54,6 +55,7 @@ class SubtitleCardViewTest : BaseViewTest() { reminder = Reminder(8, 30, EVERY_DAY), unit = "", targetValue = 0.0, + theme = LightTheme(), ) ) measureView(view, 800f, 200f) diff --git a/uhabits-android/src/main/java/org/isoron/platform/gui/AndroidCanvas.kt b/uhabits-android/src/main/java/org/isoron/platform/gui/AndroidCanvas.kt index b4ff1d5e5..ae1d1f52f 100644 --- a/uhabits-android/src/main/java/org/isoron/platform/gui/AndroidCanvas.kt +++ b/uhabits-android/src/main/java/org/isoron/platform/gui/AndroidCanvas.kt @@ -36,6 +36,7 @@ class AndroidCanvas : Canvas { var innerDensity = 1.0 var innerWidth = 0 var innerHeight = 0 + var mHeight = 15 var paint = Paint().apply { isAntiAlias = true @@ -64,11 +65,10 @@ class AndroidCanvas : Canvas { } override fun drawText(text: String, x: Double, y: Double) { - textPaint.getTextBounds(text, 0, text.length, textBounds) innerCanvas.drawText( text, x.toDp(), - y.toDp() - textBounds.exactCenterY(), + y.toDp() + 0.6f * mHeight, textPaint, ) } @@ -126,10 +126,17 @@ class AndroidCanvas : Canvas { Font.BOLD -> Typeface.DEFAULT_BOLD Font.FONT_AWESOME -> getFontAwesome(context) } + updateMHeight() } override fun setFontSize(size: Double) { textPaint.textSize = size.toDp() + updateMHeight() + } + + private fun updateMHeight() { + textPaint.getTextBounds("m", 0, 1, textBounds) + mHeight = textBounds.height() } override fun setStrokeWidth(size: Double) { 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/about/AboutView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutView.kt index 250a3b211..5eeb67f19 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutView.kt @@ -26,6 +26,7 @@ import org.isoron.uhabits.BuildConfig import org.isoron.uhabits.R import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.databinding.AboutBinding +import org.isoron.uhabits.utils.currentTheme import org.isoron.uhabits.utils.setupToolbar @SuppressLint("ViewConstructor") @@ -41,7 +42,8 @@ class AboutView( setupToolbar( toolbar = binding.toolbar, color = PaletteColor(11), - title = resources.getString(R.string.about) + title = resources.getString(R.string.about), + theme = currentTheme(), ) val version = resources.getString(R.string.version_n) binding.tvContributors.setOnClickListener { screen.showCodeContributorsWebsite() } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/ColorPickerDialogFactory.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/ColorPickerDialogFactory.kt index ac393d506..e4cfa015b 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/ColorPickerDialogFactory.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/ColorPickerDialogFactory.kt @@ -19,20 +19,21 @@ package org.isoron.uhabits.activities.common.dialogs import android.content.Context +import org.isoron.platform.gui.toInt import org.isoron.uhabits.R import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.ui.views.Theme import org.isoron.uhabits.inject.ActivityContext import org.isoron.uhabits.inject.ActivityScope import org.isoron.uhabits.utils.StyledResources -import org.isoron.uhabits.utils.toThemedAndroidColor import javax.inject.Inject @ActivityScope class ColorPickerDialogFactory @Inject constructor(@param:ActivityContext private val context: Context) { - fun create(color: PaletteColor): ColorPickerDialog { + fun create(color: PaletteColor, theme: Theme): ColorPickerDialog { val dialog = ColorPickerDialog() val res = StyledResources(context) - val androidColor = color.toThemedAndroidColor(context) + val androidColor = theme.color(color).toInt() dialog.initialize( R.string.color_picker_default_title, res.getPalette(), 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..8fa3b6001 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 @@ -39,6 +40,7 @@ import kotlinx.android.synthetic.main.activity_edit_habit.notesInput import kotlinx.android.synthetic.main.activity_edit_habit.questionInput import kotlinx.android.synthetic.main.activity_edit_habit.targetInput import kotlinx.android.synthetic.main.activity_edit_habit.unitInput +import org.isoron.platform.gui.toInt import org.isoron.uhabits.HabitsApplication import org.isoron.uhabits.R import org.isoron.uhabits.activities.AndroidThemeSwitcher @@ -57,7 +59,16 @@ import org.isoron.uhabits.databinding.ActivityEditHabitBinding import org.isoron.uhabits.utils.ColorUtils 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() { @@ -137,7 +148,7 @@ class EditHabitActivity : AppCompatActivity() { val colorPickerDialogFactory = ColorPickerDialogFactory(this) binding.colorButton.setOnClickListener { - val dialog = colorPickerDialogFactory.create(color) + val dialog = colorPickerDialogFactory.create(color, themeSwitcher.currentTheme) dialog.setListener { paletteColor -> this.color = paletteColor updateColors() @@ -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) @@ -316,7 +320,7 @@ class EditHabitActivity : AppCompatActivity() { } private fun updateColors() { - androidColor = color.toThemedAndroidColor(this) + androidColor = themeSwitcher.currentTheme.color(color).toInt() binding.colorButton.backgroundTintList = ColorStateList.valueOf(androidColor) if (!themeSwitcher.isNightMode) { val darkerAndroidColor = ColorUtils.mixColors(Color.BLACK, androidColor, 0.15f) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.kt index 8295a41db..faa13173a 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsRootView.kt @@ -44,6 +44,7 @@ import org.isoron.uhabits.utils.addAtBottom import org.isoron.uhabits.utils.addAtTop import org.isoron.uhabits.utils.addBelow import org.isoron.uhabits.utils.buildToolbar +import org.isoron.uhabits.utils.currentTheme import org.isoron.uhabits.utils.dim import org.isoron.uhabits.utils.dp import org.isoron.uhabits.utils.setupToolbar @@ -93,6 +94,7 @@ class ListHabitsRootView @Inject constructor( title = resources.getString(R.string.main_activity_title), color = PaletteColor(17), displayHomeAsUpEnabled = false, + theme = currentTheme(), ) addView(rootView, MATCH_PARENT, MATCH_PARENT) listAdapter.setListView(listView) 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 5ede0ab44..d20cd18fe 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 @@ -217,7 +217,7 @@ class ListHabitsScreen } override fun showColorPicker(defaultColor: PaletteColor, callback: OnColorPickedCallback) { - val picker = colorPickerFactory.create(defaultColor) + val picker = colorPickerFactory.create(defaultColor, themeSwitcher.currentTheme!!) picker.setListener(callback) picker.show(activity.supportFragmentManager, "picker") } 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 2318f2ccc..c59b61ec1 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 @@ -33,6 +33,7 @@ import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.widget.FrameLayout import android.widget.LinearLayout import android.widget.TextView +import org.isoron.platform.gui.toInt import org.isoron.uhabits.R import org.isoron.uhabits.activities.common.views.RingView import org.isoron.uhabits.core.models.Habit @@ -41,9 +42,9 @@ import org.isoron.uhabits.core.models.Timestamp import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior import org.isoron.uhabits.core.utils.DateUtils import org.isoron.uhabits.inject.ActivityContext +import org.isoron.uhabits.utils.currentTheme import org.isoron.uhabits.utils.dp import org.isoron.uhabits.utils.sres -import org.isoron.uhabits.utils.toThemedAndroidColor import javax.inject.Inject class HabitCardViewFactory @@ -213,7 +214,7 @@ class HabitCardView( fun getActiveColor(habit: Habit): Int { return when (habit.isArchived) { true -> sres.getColor(R.attr.contrast60) - false -> habit.color.toThemedAndroidColor(context) + false -> currentTheme().color(habit.color).toInt() } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitView.kt index fb1e37f4c..38fba3baf 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitView.kt @@ -35,7 +35,12 @@ class ShowHabitView(context: Context) : FrameLayout(context) { } fun setState(data: ShowHabitState) { - setupToolbar(binding.toolbar, title = data.title, color = data.color) + setupToolbar( + binding.toolbar, + title = data.title, + color = data.color, + theme = data.theme, + ) binding.subtitleCard.setState(data.subtitle) binding.overviewCard.setState(data.overview) binding.notesCard.setState(data.notes) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCardView.kt index 6effbd597..fa3122ed3 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/BarCardView.kt @@ -24,12 +24,12 @@ import android.view.LayoutInflater import android.view.View import android.widget.AdapterView import android.widget.LinearLayout +import org.isoron.platform.gui.toInt import org.isoron.platform.time.JavaLocalDateFormatter import org.isoron.uhabits.core.ui.screens.habits.show.views.BarCardPresenter import org.isoron.uhabits.core.ui.screens.habits.show.views.BarCardState import org.isoron.uhabits.core.ui.views.BarChart import org.isoron.uhabits.databinding.ShowHabitBarBinding -import org.isoron.uhabits.utils.toThemedAndroidColor import java.util.Locale class BarCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { @@ -37,7 +37,7 @@ class BarCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, private var binding = ShowHabitBarBinding.inflate(LayoutInflater.from(context), this) fun setState(state: BarCardState) { - val androidColor = state.color.toThemedAndroidColor(context) + val androidColor = state.theme.color(state.color).toInt() binding.chart.view = BarChart(state.theme, JavaLocalDateFormatter(Locale.US)).apply { series = mutableListOf(state.entries.map { it.value / 1000.0 }) colors = mutableListOf(theme.color(state.color.paletteIndex)) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardView.kt index 526431f25..cf7daf769 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCardView.kt @@ -22,16 +22,16 @@ import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater import android.widget.LinearLayout +import org.isoron.platform.gui.toInt import org.isoron.uhabits.core.ui.screens.habits.show.views.FrequencyCardState import org.isoron.uhabits.databinding.ShowHabitFrequencyBinding -import org.isoron.uhabits.utils.toThemedAndroidColor class FrequencyCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { private var binding = ShowHabitFrequencyBinding.inflate(LayoutInflater.from(context), this) fun setState(state: FrequencyCardState) { - val androidColor = state.color.toThemedAndroidColor(context) + val androidColor = state.theme.color(state.color).toInt() binding.frequencyChart.setFrequency(state.frequency) binding.frequencyChart.setFirstWeekday(state.firstWeekday) binding.title.setTextColor(androidColor) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt index 7950d6195..c60e84bd1 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt @@ -22,12 +22,12 @@ import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater import android.widget.LinearLayout +import org.isoron.platform.gui.toInt import org.isoron.platform.time.JavaLocalDateFormatter import org.isoron.uhabits.core.ui.screens.habits.show.views.HistoryCardPresenter import org.isoron.uhabits.core.ui.screens.habits.show.views.HistoryCardState import org.isoron.uhabits.core.ui.views.HistoryChart import org.isoron.uhabits.databinding.ShowHabitHistoryBinding -import org.isoron.uhabits.utils.toThemedAndroidColor import java.util.Locale class HistoryCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { @@ -35,7 +35,7 @@ class HistoryCardView(context: Context, attrs: AttributeSet) : LinearLayout(cont private var binding = ShowHabitHistoryBinding.inflate(LayoutInflater.from(context), this) fun setState(state: HistoryCardState) { - val androidColor = state.color.toThemedAndroidColor(context) + val androidColor = state.theme.color(state.color).toInt() binding.title.setTextColor(androidColor) binding.chart.view = HistoryChart( today = state.today, diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCardView.kt index aa5b0cd02..62a83e412 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCardView.kt @@ -22,11 +22,11 @@ import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater import android.widget.LinearLayout +import org.isoron.platform.gui.toInt import org.isoron.uhabits.R import org.isoron.uhabits.core.ui.screens.habits.show.views.OverviewCardState import org.isoron.uhabits.databinding.ShowHabitOverviewBinding import org.isoron.uhabits.utils.StyledResources -import org.isoron.uhabits.utils.toThemedAndroidColor import kotlin.math.abs class OverviewCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { @@ -42,7 +42,7 @@ class OverviewCardView(context: Context, attrs: AttributeSet) : LinearLayout(con } fun setState(state: OverviewCardState) { - val androidColor = state.color.toThemedAndroidColor(context) + val androidColor = state.theme.color(state.color).toInt() val res = StyledResources(context) val inactiveColor = res.getColor(R.attr.contrast60) binding.monthDiffLabel.setTextColor(if (state.scoreMonthDiff >= 0) androidColor else inactiveColor) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCardView.kt index e5c740574..943e3eb07 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/ScoreCardView.kt @@ -24,16 +24,16 @@ import android.view.LayoutInflater import android.view.View import android.widget.AdapterView import android.widget.LinearLayout +import org.isoron.platform.gui.toInt import org.isoron.uhabits.core.ui.screens.habits.show.views.ScoreCardPresenter import org.isoron.uhabits.core.ui.screens.habits.show.views.ScoreCardState import org.isoron.uhabits.databinding.ShowHabitScoreBinding -import org.isoron.uhabits.utils.toThemedAndroidColor class ScoreCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { private var binding = ShowHabitScoreBinding.inflate(LayoutInflater.from(context), this) fun setState(state: ScoreCardState) { - val androidColor = state.color.toThemedAndroidColor(context) + val androidColor = state.theme.color(state.color).toInt() binding.title.setTextColor(androidColor) binding.spinner.setSelection(state.spinnerPosition) binding.scoreView.setScores(state.scores) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/StreakCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/StreakCardView.kt index 613e71fab..f2faa5f26 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/StreakCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/StreakCardView.kt @@ -22,16 +22,16 @@ import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater import android.widget.LinearLayout +import org.isoron.platform.gui.toInt import org.isoron.uhabits.core.ui.screens.habits.show.views.StreakCardState import org.isoron.uhabits.databinding.ShowHabitStreakBinding -import org.isoron.uhabits.utils.toThemedAndroidColor class StreakCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { private val binding = ShowHabitStreakBinding.inflate(LayoutInflater.from(context), this) fun setState(state: StreakCardState) { - val color = state.color.toThemedAndroidColor(context) - binding.title.setTextColor(color) - binding.streakChart.setColor(color) + val androidColor = state.theme.color(state.color).toInt() + binding.title.setTextColor(androidColor) + binding.streakChart.setColor(androidColor) binding.streakChart.setStreaks(state.bestStreaks) postInvalidate() } 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..49c67aae1 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,19 +20,18 @@ 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.platform.gui.toInt 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 import org.isoron.uhabits.utils.formatTime -import org.isoron.uhabits.utils.toThemedAndroidColor class SubtitleCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { @@ -47,9 +46,13 @@ class SubtitleCardView(context: Context, attrs: AttributeSet) : LinearLayout(con @SuppressLint("SetTextI18n") fun setState(state: SubtitleCardState) { - val color = state.color.toThemedAndroidColor(context) + val color = state.theme.color(state.color).toInt() 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-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCardView.kt index 13c71989b..b44cf2f3c 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCardView.kt @@ -23,15 +23,15 @@ import android.content.res.Resources import android.util.AttributeSet import android.view.LayoutInflater import android.widget.LinearLayout +import org.isoron.platform.gui.toInt import org.isoron.uhabits.R import org.isoron.uhabits.core.ui.screens.habits.show.views.TargetCardState import org.isoron.uhabits.databinding.ShowHabitTargetBinding -import org.isoron.uhabits.utils.toThemedAndroidColor class TargetCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { private val binding = ShowHabitTargetBinding.inflate(LayoutInflater.from(context), this) fun setState(state: TargetCardState) { - val androidColor = state.color.toThemedAndroidColor(context) + val androidColor = state.theme.color(state.color).toInt() binding.targetChart.setValues(state.values) binding.targetChart.setTargets(state.targets) binding.targetChart.setLabels(state.intervals.map { intervalToLabel(resources, it) }) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsActivity.kt index f759607ed..60a12ac17 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/settings/SettingsActivity.kt @@ -32,13 +32,15 @@ class SettingsActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val component = (application as HabitsApplication).component - AndroidThemeSwitcher(this, component.preferences).apply() + val themeSwitcher = AndroidThemeSwitcher(this, component.preferences) + themeSwitcher.apply() val binding = SettingsActivityBinding.inflate(LayoutInflater.from(this)) binding.root.setupToolbar( toolbar = binding.toolbar, title = resources.getString(R.string.settings), color = PaletteColor(11), + theme = themeSwitcher.currentTheme, ) setContentView(binding.root) } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingRootView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingRootView.kt index 442024149..30c13c95d 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingRootView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingRootView.kt @@ -33,6 +33,7 @@ import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.models.HabitList import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.databinding.AutomationBinding +import org.isoron.uhabits.utils.currentTheme import org.isoron.uhabits.utils.setupToolbar import java.util.LinkedList @@ -53,6 +54,7 @@ class EditSettingRootView( title = resources.getString(R.string.app_name), color = PaletteColor(11), displayHomeAsUpEnabled = false, + theme = currentTheme(), ) populateHabitSpinner() binding.habitSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt b/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt index 0a195d9c0..9ee9fd23e 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt @@ -63,13 +63,14 @@ class PendingIntentFactory FLAG_UPDATE_CURRENT ) - fun removeRepetition(habit: Habit): PendingIntent = + fun removeRepetition(habit: Habit, timestamp: Timestamp?): PendingIntent = getBroadcast( context, 3, Intent(context, WidgetReceiver::class.java).apply { action = WidgetReceiver.ACTION_REMOVE_REPETITION data = Uri.parse(habit.uriString) + if (timestamp != null) putExtra("timestamp", timestamp.unixTime) }, FLAG_UPDATE_CURRENT ) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt index de1c23d24..04f3d8d92 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt @@ -107,7 +107,7 @@ class AndroidNotificationTray val removeRepetitionAction = Action( R.drawable.ic_action_cancel, context.getString(R.string.no), - pendingIntents.removeRepetition(habit) + pendingIntents.removeRepetition(habit, timestamp) ) val enterAction = Action( 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 d28bb2ba5..42514b118 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 @@ -28,6 +28,7 @@ import android.widget.AdapterView.OnItemClickListener import androidx.fragment.app.FragmentActivity import com.android.datetimepicker.time.RadialPickerLayout import com.android.datetimepicker.time.TimePickerDialog +import org.isoron.platform.gui.toInt import org.isoron.uhabits.HabitsApplication import org.isoron.uhabits.R import org.isoron.uhabits.activities.AndroidThemeSwitcher @@ -35,14 +36,13 @@ import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.ui.ThemeSwitcher.Companion.THEME_LIGHT import org.isoron.uhabits.receivers.ReminderController import org.isoron.uhabits.utils.SystemUtils -import org.isoron.uhabits.utils.toThemedAndroidColor import java.util.Calendar class SnoozeDelayPickerActivity : FragmentActivity(), OnItemClickListener { private var habit: Habit? = null private var reminderController: ReminderController? = null private var dialog: AlertDialog? = null - private var color: Int = 0 + private var androidColor: Int = 0 override fun onCreate(bundle: Bundle?) { super.onCreate(bundle) @@ -63,7 +63,7 @@ class SnoozeDelayPickerActivity : FragmentActivity(), OnItemClickListener { habit = appComponent.habitList.getById(ContentUris.parseId(data)) } if (habit == null) finish() - color = habit!!.color.toThemedAndroidColor(this) + androidColor = themeSwitcher.currentTheme.color(habit!!.color).toInt() reminderController = appComponent.reminderController dialog = AlertDialog.Builder(this) .setTitle(R.string.select_snooze_delay) @@ -85,7 +85,7 @@ class SnoozeDelayPickerActivity : FragmentActivity(), OnItemClickListener { calendar[Calendar.HOUR_OF_DAY], calendar[Calendar.MINUTE], DateFormat.is24HourFormat(this), - color + androidColor ) dialog.show(supportFragmentManager, "timePicker") } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/utils/PaletteUtils.kt b/uhabits-android/src/main/java/org/isoron/uhabits/utils/PaletteUtils.kt index fe1575d25..5f120c6af 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/utils/PaletteUtils.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/utils/PaletteUtils.kt @@ -21,7 +21,6 @@ package org.isoron.uhabits.utils import android.content.Context import android.graphics.Color -import android.util.Log import org.isoron.uhabits.core.models.PaletteColor object PaletteUtils { @@ -29,16 +28,6 @@ object PaletteUtils { fun getAndroidTestColor(index: Int) = PaletteColor(index).toFixedAndroidColor() } -fun PaletteColor.toThemedAndroidColor(context: Context): Int { - val palette = StyledResources(context).getPalette() - return if (paletteIndex in palette.indices) { - palette[paletteIndex] - } else { - Log.w("ColorHelper", "Invalid color: $paletteIndex. Returning default.") - palette[0] - } -} - fun PaletteColor.toFixedAndroidColor(): Int { return intArrayOf( Color.parseColor("#D32F2F"), // 0 red diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt b/uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt index 936e58573..bfa64ebf0 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt @@ -40,8 +40,12 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar import androidx.core.content.FileProvider import com.google.android.material.snackbar.Snackbar +import org.isoron.platform.gui.toInt +import org.isoron.uhabits.HabitsApplication import org.isoron.uhabits.R +import org.isoron.uhabits.activities.AndroidThemeSwitcher import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.ui.views.Theme import java.io.File fun RelativeLayout.addBelow( @@ -157,6 +161,7 @@ fun View.setupToolbar( toolbar: Toolbar, title: String, color: PaletteColor, + theme: Theme, displayHomeAsUpEnabled: Boolean = true, ) { toolbar.elevation = InterfaceUtils.dpToPixels(context, 2f) @@ -165,7 +170,7 @@ fun View.setupToolbar( val toolbarColor = if (!res.getBoolean(R.attr.useHabitColorAsPrimary)) { StyledResources(context).getColor(R.attr.colorPrimary) } else { - color.toThemedAndroidColor(context) + theme.color(color).toInt() } val darkerColor = ColorUtils.mixColors(toolbarColor, Color.BLACK, 0.75f) toolbar.background = ColorDrawable(toolbarColor) @@ -175,6 +180,13 @@ fun View.setupToolbar( activity.supportActionBar?.setDisplayHomeAsUpEnabled(displayHomeAsUpEnabled) } +fun View.currentTheme(): Theme { + val component = (context.applicationContext as HabitsApplication).component + val themeSwitcher = AndroidThemeSwitcher(context, component.preferences) + themeSwitcher.apply() + return themeSwitcher.currentTheme +} + fun Int.toMeasureSpec(mode: Int) = View.MeasureSpec.makeMeasureSpec(this, mode) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidget.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidget.kt index dae6db9ce..bc9654529 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidget.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidget.kt @@ -32,6 +32,7 @@ import org.isoron.uhabits.core.commands.CommandRunner import org.isoron.uhabits.core.preferences.Preferences import org.isoron.uhabits.core.preferences.WidgetPreferences import org.isoron.uhabits.intents.PendingIntentFactory +import kotlin.math.max abstract class BaseWidget(val context: Context, val id: Int, val stacked: Boolean) { private val widgetPrefs: WidgetPreferences @@ -103,8 +104,8 @@ abstract class BaseWidget(val context: Context, val id: Int, val stacked: Boolea private fun getBitmapFromView(view: View): Bitmap { view.invalidate() - val width = view.measuredWidth - val height = view.measuredHeight + val width = max(1, view.measuredWidth) + val height = max(1, view.measuredHeight) val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) val canvas = Canvas(bitmap) view.draw(canvas) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.kt index 6fae9fc9c..1a41d0f4f 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.kt @@ -109,7 +109,7 @@ abstract class BaseWidgetProvider : AppWidgetProvider() { } protected fun getHabitsFromWidgetId(widgetId: Int): List { - val selectedIds = widgetPrefs.getHabitIdsFromWidgetId(widgetId)!! + val selectedIds = widgetPrefs.getHabitIdsFromWidgetId(widgetId) val selectedHabits = ArrayList(selectedIds.size) for (id in selectedIds) { val h = habits.getById(id) ?: throw HabitNotFoundException() 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 f901cb8e6..f2814ff4d 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 @@ -24,10 +24,11 @@ import android.content.Context import android.os.Build import android.view.View import androidx.annotation.RequiresApi +import org.isoron.platform.gui.toInt import org.isoron.uhabits.core.models.Entry import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.ui.views.WidgetTheme import org.isoron.uhabits.core.utils.DateUtils -import org.isoron.uhabits.utils.toThemedAndroidColor import org.isoron.uhabits.widgets.views.CheckmarkWidgetView open class CheckmarkWidget( @@ -53,7 +54,7 @@ open class CheckmarkWidget( (widgetView as CheckmarkWidgetView).apply { val today = DateUtils.getTodayWithOffset() setBackgroundAlpha(preferedBackgroundAlpha) - activeColor = habit.color.toThemedAndroidColor(context) + activeColor = WidgetTheme().color(habit.color).toInt() name = habit.name entryValue = habit.computedEntries.get(today).value if (habit.isNumerical) { diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt index 7ebba0383..8ef1b4a48 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt @@ -22,9 +22,10 @@ package org.isoron.uhabits.widgets import android.app.PendingIntent import android.content.Context import android.view.View +import org.isoron.platform.gui.toInt import org.isoron.uhabits.activities.common.views.FrequencyChart import org.isoron.uhabits.core.models.Habit -import org.isoron.uhabits.utils.toThemedAndroidColor +import org.isoron.uhabits.core.ui.views.WidgetTheme import org.isoron.uhabits.widgets.views.GraphWidgetView class FrequencyWidget( @@ -47,7 +48,7 @@ class FrequencyWidget( if (preferedBackgroundAlpha >= 255) widgetView.setShadowAlpha(0x4f) (widgetView.dataView as FrequencyChart).apply { setFirstWeekday(firstWeekday) - setColor(habit.color.toThemedAndroidColor(context)) + setColor(WidgetTheme().color(habit.color).toInt()) setFrequency(habit.originalEntries.computeWeekdayFrequency(habit.isNumerical)) } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt index 34b8f523c..14ccc1d30 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/ScoreWidget.kt @@ -22,10 +22,11 @@ package org.isoron.uhabits.widgets import android.app.PendingIntent import android.content.Context import android.view.View +import org.isoron.platform.gui.toInt import org.isoron.uhabits.activities.common.views.ScoreChart import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.ui.screens.habits.show.views.ScoreCardPresenter -import org.isoron.uhabits.utils.toThemedAndroidColor +import org.isoron.uhabits.core.ui.views.WidgetTheme import org.isoron.uhabits.widgets.views.GraphWidgetView class ScoreWidget( @@ -44,7 +45,8 @@ class ScoreWidget( val viewModel = ScoreCardPresenter.buildState( habit = habit, firstWeekday = prefs.firstWeekdayInt, - spinnerPosition = prefs.scoreCardSpinnerPosition + spinnerPosition = prefs.scoreCardSpinnerPosition, + theme = WidgetTheme(), ) val widgetView = view as GraphWidgetView widgetView.setBackgroundAlpha(preferedBackgroundAlpha) @@ -52,7 +54,7 @@ class ScoreWidget( (widgetView.dataView as ScoreChart).apply { setIsTransparencyEnabled(true) setBucketSize(viewModel.bucketSize) - setColor(habit.color.toThemedAndroidColor(context)) + setColor(WidgetTheme().color(habit.color).toInt()) setScores(viewModel.scores) } } 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 4c74ceb32..0e60914e5 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 @@ -53,7 +53,7 @@ internal class StackRemoteViewsFactory(private val context: Context, intent: Int AppWidgetManager.INVALID_APPWIDGET_ID ) private val habitIds: LongArray - private val widgetType: StackWidgetType? + private val widgetType: StackWidgetType private var remoteViews = ArrayList() override fun onCreate() {} override fun onDestroy() {} @@ -86,27 +86,27 @@ internal class StackRemoteViewsFactory(private val context: Context, intent: Int override fun getViewAt(position: Int): RemoteViews? { Log.i("StackRemoteViewsFactory", "getViewAt $position") - return if (position < 0 || position > remoteViews.size) null else remoteViews[position] + return if (0 <= position && position < remoteViews.size) remoteViews[position] else null } private fun constructWidget( habit: Habit, prefs: Preferences ): BaseWidget { - when (widgetType) { - StackWidgetType.CHECKMARK -> return CheckmarkWidget(context, widgetId, habit, true) - StackWidgetType.FREQUENCY -> return FrequencyWidget( + return when (widgetType) { + StackWidgetType.CHECKMARK -> CheckmarkWidget(context, widgetId, habit, true) + StackWidgetType.FREQUENCY -> FrequencyWidget( context, widgetId, habit, prefs.firstWeekdayInt, true ) - StackWidgetType.SCORE -> return ScoreWidget(context, widgetId, habit, true) - StackWidgetType.HISTORY -> return HistoryWidget(context, widgetId, habit, true) - StackWidgetType.STREAKS -> return StreakWidget(context, widgetId, habit, true) + StackWidgetType.SCORE -> ScoreWidget(context, widgetId, habit, true) + StackWidgetType.HISTORY -> HistoryWidget(context, widgetId, habit, true) + StackWidgetType.STREAKS -> StreakWidget(context, widgetId, habit, true) + StackWidgetType.TARGET -> TargetWidget(context, widgetId, habit, true) } - throw IllegalStateException() } override fun getLoadingView(): RemoteViews { @@ -157,6 +157,7 @@ internal class StackRemoteViewsFactory(private val context: Context, intent: Int if (widgetTypeValue < 0) throw RuntimeException("invalid widget type") if (habitIdsStr == null) throw RuntimeException("habitIdsStr is null") widgetType = StackWidgetType.getWidgetTypeFromValue(widgetTypeValue) + ?: throw RuntimeException("unknown widget type value: $widgetTypeValue") habitIds = splitLongs(habitIdsStr) } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.kt index ca120142b..68e8018aa 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetType.kt @@ -19,61 +19,59 @@ package org.isoron.uhabits.widgets import org.isoron.uhabits.R +import java.lang.IllegalStateException -/** - * Created by victoryu on 11/3/17. - */ enum class StackWidgetType(val value: Int) { CHECKMARK(0), FREQUENCY(1), SCORE(2), // habit strength widget HISTORY(3), STREAKS(4), TARGET(5); companion object { fun getWidgetTypeFromValue(value: Int): StackWidgetType? { - return when { - CHECKMARK.value == value -> CHECKMARK - FREQUENCY.value == value -> FREQUENCY - SCORE.value == value -> SCORE - HISTORY.value == value -> HISTORY - STREAKS.value == value -> STREAKS - TARGET.value == value -> TARGET + return when (value) { + CHECKMARK.value -> CHECKMARK + FREQUENCY.value -> FREQUENCY + SCORE.value -> SCORE + HISTORY.value -> HISTORY + STREAKS.value -> STREAKS + TARGET.value -> TARGET else -> null } } fun getStackWidgetLayoutId(type: StackWidgetType?): Int { - when (type) { - CHECKMARK -> return R.layout.checkmark_stackview_widget - FREQUENCY -> return R.layout.frequency_stackview_widget - SCORE -> return R.layout.score_stackview_widget - HISTORY -> return R.layout.history_stackview_widget - STREAKS -> return R.layout.streak_stackview_widget - TARGET -> return R.layout.target_stackview_widget + return when (type) { + CHECKMARK -> R.layout.checkmark_stackview_widget + FREQUENCY -> R.layout.frequency_stackview_widget + SCORE -> R.layout.score_stackview_widget + HISTORY -> R.layout.history_stackview_widget + STREAKS -> R.layout.streak_stackview_widget + TARGET -> R.layout.target_stackview_widget + else -> throw IllegalStateException() } - return 0 } fun getStackWidgetAdapterViewId(type: StackWidgetType?): Int { - when (type) { - CHECKMARK -> return R.id.checkmarkStackWidgetView - FREQUENCY -> return R.id.frequencyStackWidgetView - SCORE -> return R.id.scoreStackWidgetView - HISTORY -> return R.id.historyStackWidgetView - STREAKS -> return R.id.streakStackWidgetView - TARGET -> return R.id.targetStackWidgetView + return when (type) { + CHECKMARK -> R.id.checkmarkStackWidgetView + FREQUENCY -> R.id.frequencyStackWidgetView + SCORE -> R.id.scoreStackWidgetView + HISTORY -> R.id.historyStackWidgetView + STREAKS -> R.id.streakStackWidgetView + TARGET -> R.id.targetStackWidgetView + else -> throw IllegalStateException() } - return 0 } fun getStackWidgetEmptyViewId(type: StackWidgetType?): Int { - when (type) { - CHECKMARK -> return R.id.checkmarkStackWidgetEmptyView - FREQUENCY -> return R.id.frequencyStackWidgetEmptyView - SCORE -> return R.id.scoreStackWidgetEmptyView - HISTORY -> return R.id.historyStackWidgetEmptyView - STREAKS -> return R.id.streakStackWidgetEmptyView - TARGET -> return R.id.targetStackWidgetEmptyView + return when (type) { + CHECKMARK -> R.id.checkmarkStackWidgetEmptyView + FREQUENCY -> R.id.frequencyStackWidgetEmptyView + SCORE -> R.id.scoreStackWidgetEmptyView + HISTORY -> R.id.historyStackWidgetEmptyView + STREAKS -> R.id.streakStackWidgetEmptyView + TARGET -> R.id.targetStackWidgetEmptyView + else -> throw IllegalStateException() } - return 0 } } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StreakWidget.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StreakWidget.kt index d055c216b..e07c95359 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StreakWidget.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StreakWidget.kt @@ -24,9 +24,10 @@ import android.content.Context import android.view.View import android.view.ViewGroup.LayoutParams import android.view.ViewGroup.LayoutParams.MATCH_PARENT +import org.isoron.platform.gui.toInt import org.isoron.uhabits.activities.common.views.StreakChart import org.isoron.uhabits.core.models.Habit -import org.isoron.uhabits.utils.toThemedAndroidColor +import org.isoron.uhabits.core.ui.views.WidgetTheme import org.isoron.uhabits.widgets.views.GraphWidgetView class StreakWidget( @@ -46,7 +47,7 @@ class StreakWidget( widgetView.setBackgroundAlpha(preferedBackgroundAlpha) if (preferedBackgroundAlpha >= 255) widgetView.setShadowAlpha(0x4f) (widgetView.dataView as StreakChart).apply { - setColor(habit.color.toThemedAndroidColor(context)) + setColor(WidgetTheme().color(habit.color).toInt()) setStreaks(habit.streaks.getBest(maxStreakCount)) } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt index 5116aa78e..f98331e8f 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt @@ -25,11 +25,12 @@ import android.view.View import android.view.ViewGroup.LayoutParams import android.view.ViewGroup.LayoutParams.MATCH_PARENT import kotlinx.coroutines.runBlocking +import org.isoron.platform.gui.toInt import org.isoron.uhabits.activities.common.views.TargetChart import org.isoron.uhabits.activities.habits.show.views.TargetCardView.Companion.intervalToLabel import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.ui.screens.habits.show.views.TargetCardPresenter -import org.isoron.uhabits.utils.toThemedAndroidColor +import org.isoron.uhabits.core.ui.views.WidgetTheme import org.isoron.uhabits.widgets.views.GraphWidgetView class TargetWidget( @@ -49,8 +50,12 @@ class TargetWidget( widgetView.setBackgroundAlpha(preferedBackgroundAlpha) if (preferedBackgroundAlpha >= 255) widgetView.setShadowAlpha(0x4f) val chart = (widgetView.dataView as TargetChart) - val data = TargetCardPresenter.buildState(habit, prefs.firstWeekdayInt) - chart.setColor(data.color.toThemedAndroidColor(context)) + val data = TargetCardPresenter.buildState( + habit = habit, + firstWeekday = prefs.firstWeekdayInt, + theme = WidgetTheme(), + ) + chart.setColor(WidgetTheme().color(habit.color).toInt()) chart.setTargets(data.targets) chart.setLabels(data.intervals.map { intervalToLabel(context.resources, it) }) chart.setValues(data.values) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt index bd6d7a50e..d577727e0 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt @@ -95,7 +95,7 @@ class WidgetUpdater val modifiedWidgetIds = when (modifiedHabitId) { null -> widgetIds.toList() else -> widgetIds.filter { w -> - widgetPrefs.getHabitIdsFromWidgetId(w)!!.contains(modifiedHabitId) + widgetPrefs.getHabitIdsFromWidgetId(w).contains(modifiedHabitId) } } 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 2383b3683..ff743816b 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 @@ -31,6 +31,7 @@ import android.widget.ListView import android.widget.TextView import org.isoron.uhabits.HabitsApplication 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 @@ -58,6 +59,7 @@ open class HabitPickerDialog : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val component = (applicationContext as HabitsApplication).component + AndroidThemeSwitcher(this, component.preferences).apply() val habitList = component.habitList widgetPreferences = component.widgetPreferences widgetUpdater = component.widgetUpdater 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 1799b39c3..52bb4f731 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 @@ -39,6 +39,7 @@ import org.isoron.uhabits.utils.PaletteUtils.getAndroidTestColor import org.isoron.uhabits.utils.StyledResources import kotlin.math.max import kotlin.math.min +import kotlin.math.roundToInt class CheckmarkWidgetView : HabitWidgetView { var activeColor: Int = 0 @@ -118,19 +119,25 @@ class CheckmarkWidgetView : HabitWidgetView { get() = R.layout.widget_checkmark override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - val width = MeasureSpec.getSize(widthMeasureSpec) - val height = MeasureSpec.getSize(heightMeasureSpec) - var textSize = 0.15f * height - val maxTextSize = getDimension(context, R.dimen.smallerTextSize) - textSize = min(textSize, maxTextSize) + var width = MeasureSpec.getSize(widthMeasureSpec) + var height = MeasureSpec.getSize(heightMeasureSpec) + if (height >= width) { + height = min(height, (width * 1.5).roundToInt()) + } else { + width = min(width, height) + } + val textSize = min(0.2f * width, getDimension(context, R.dimen.smallerTextSize)) label.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) if (isNumerical) { - ring.setTextSize(textSize * 0.75f) + ring.setTextSize(textSize * 0.9f) } else { ring.setTextSize(textSize) } - ring.setThickness(0.15f * textSize) - super.onMeasure(widthMeasureSpec, heightMeasureSpec) + ring.setThickness(0.03f * width) + super.onMeasure( + MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY) + ) } private fun init() { diff --git a/uhabits-android/src/main/play/release-notes/en-US/default.txt b/uhabits-android/src/main/play/release-notes/en-US/default.txt index 70bb26533..279010497 100644 --- a/uhabits-android/src/main/play/release-notes/en-US/default.txt +++ b/uhabits-android/src/main/play/release-notes/en-US/default.txt @@ -1,4 +1,4 @@ -2.0.2: +2.0.3: * Bug fixes 2.0: * Track numeric habits (e.g. how many pages did you read?) diff --git a/uhabits-android/src/main/res/layout/widget_checkmark.xml b/uhabits-android/src/main/res/layout/widget_checkmark.xml index 75b351317..abdbf4dea 100644 --- a/uhabits-android/src/main/res/layout/widget_checkmark.xml +++ b/uhabits-android/src/main/res/layout/widget_checkmark.xml @@ -31,19 +31,19 @@ android:id="@+id/scoreRing" android:layout_width="match_parent" android:layout_height="0dp" - android:layout_weight="1" + android:layout_weight="0.9" habit:thickness="2" habit:textSize="16" habit:enableFontAwesome="true" android:layout_marginTop="8dp" - android:layout_marginLeft="12dp" - android:layout_marginRight="12dp"/> + android:layout_marginLeft="4dp" + android:layout_marginRight="4dp"/> @drawable/selected_box @color/grey_100 @color/black + @style/PreferenceThemeOverlay.v14.Material.PureBlack + + +