From b54711243fc025b58f8eb00b22ed9a9c93d76e76 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Sat, 31 Jul 2021 14:18:50 -0500 Subject: [PATCH] Remove color.toThemedAndroidColor Fixes #907 --- .../views/widgets/CheckmarkWidget/render.png | Bin 7153 -> 7129 bytes .../views/widgets/TargetWidget/render.png | Bin 15202 -> 15144 bytes .../activities/common/views/ScoreChartTest.kt | 12 +++++++++--- .../show/views/FrequencyCardViewTest.kt | 9 ++++++++- .../habits/show/views/OverviewCardViewTest.kt | 2 ++ .../habits/show/views/ScoreCardViewTest.kt | 10 +++++++++- .../habits/show/views/StreakCardViewTest.kt | 2 ++ .../habits/show/views/SubtitleCardViewTest.kt | 2 ++ .../uhabits/activities/about/AboutView.kt | 4 +++- .../dialogs/ColorPickerDialogFactory.kt | 7 ++++--- .../habits/edit/EditHabitActivity.kt | 6 +++--- .../habits/list/ListHabitsRootView.kt | 2 ++ .../habits/list/ListHabitsScreen.kt | 2 +- .../habits/list/views/HabitCardView.kt | 5 +++-- .../activities/habits/show/ShowHabitView.kt | 7 ++++++- .../habits/show/views/BarCardView.kt | 4 ++-- .../habits/show/views/FrequencyCardView.kt | 4 ++-- .../habits/show/views/HistoryCardView.kt | 4 ++-- .../habits/show/views/OverviewCardView.kt | 4 ++-- .../habits/show/views/ScoreCardView.kt | 4 ++-- .../habits/show/views/StreakCardView.kt | 8 ++++---- .../habits/show/views/SubtitleCardView.kt | 4 ++-- .../habits/show/views/TargetCardView.kt | 4 ++-- .../activities/settings/SettingsActivity.kt | 4 +++- .../uhabits/automation/EditSettingRootView.kt | 2 ++ .../SnoozeDelayPickerActivity.kt | 8 ++++---- .../org/isoron/uhabits/utils/PaletteUtils.kt | 11 ----------- .../isoron/uhabits/utils/ViewExtensions.kt | 14 +++++++++++++- .../isoron/uhabits/widgets/CheckmarkWidget.kt | 5 +++-- .../isoron/uhabits/widgets/FrequencyWidget.kt | 5 +++-- .../org/isoron/uhabits/widgets/ScoreWidget.kt | 8 +++++--- .../isoron/uhabits/widgets/StreakWidget.kt | 5 +++-- .../isoron/uhabits/widgets/TargetWidget.kt | 11 ++++++++--- .../core/ui/screens/habits/show/ShowHabit.kt | 8 ++++++++ .../habits/show/views/FrequencyCard.kt | 4 ++++ .../screens/habits/show/views/OverviewCard.kt | 5 ++++- .../ui/screens/habits/show/views/ScoreCard.kt | 4 ++++ .../screens/habits/show/views/StreakCart.kt | 7 +++++-- .../screens/habits/show/views/SubtitleCard.kt | 4 ++++ .../screens/habits/show/views/TargetCard.kt | 4 ++++ .../isoron/uhabits/core/ui/views/Themes.kt | 5 +++++ 41 files changed, 154 insertions(+), 66 deletions(-) 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 561cf25f8dbc571f007ec4e14e24d68c1cdd42b5..889b049198474442802e2937f6b5f6361de74f7b 100644 GIT binary patch literal 7129 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 G*#85kCX%lJ literal 7153 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 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 739e0fca3dbeacf36b5e965846842b20460b6a3a..4a8fa7f9f5d37b218791cc04fec6f5f45f26c313 100644 GIT binary patch literal 15144 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%0D`Fb`>Q}8QC6;CN@-2Vi9&* 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 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/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/habits/edit/EditHabitActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt index c5e432b1f..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 @@ -40,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 @@ -58,7 +59,6 @@ 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) @@ -148,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() @@ -320,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 0673017e8..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 @@ -24,6 +24,7 @@ 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 @@ -31,7 +32,6 @@ 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) { @@ -46,7 +46,7 @@ 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 = formatFrequency( state.frequency.numerator, 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/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/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/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-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabit.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabit.kt index 4a5c5d8bc..4dc729aa4 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabit.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabit.kt @@ -57,6 +57,7 @@ data class ShowHabitState( val frequency: FrequencyCardState, val history: HistoryCardState, val bar: BarCardState, + val theme: Theme, ) class ShowHabitPresenter( @@ -94,11 +95,14 @@ class ShowHabitPresenter( title = habit.name, color = habit.color, isNumerical = habit.isNumerical, + theme = theme, subtitle = SubtitleCardPresenter.buildState( habit = habit, + theme = theme, ), overview = OverviewCardPresenter.buildState( habit = habit, + theme = theme, ), notes = NotesCardPresenter.buildState( habit = habit, @@ -106,18 +110,22 @@ class ShowHabitPresenter( target = TargetCardPresenter.buildState( habit = habit, firstWeekday = preferences.firstWeekdayInt, + theme = theme, ), streaks = StreakCartPresenter.buildState( habit = habit, + theme = theme, ), scores = ScoreCardPresenter.buildState( spinnerPosition = preferences.scoreCardSpinnerPosition, habit = habit, firstWeekday = preferences.firstWeekdayInt, + theme = theme, ), frequency = FrequencyCardPresenter.buildState( habit = habit, firstWeekday = preferences.firstWeekdayInt, + theme = theme, ), history = HistoryCardPresenter.buildState( habit = habit, diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/FrequencyCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/FrequencyCard.kt index d7f8d1e2e..fd46c3473 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/FrequencyCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/FrequencyCard.kt @@ -22,12 +22,14 @@ package org.isoron.uhabits.core.ui.screens.habits.show.views import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.core.models.Timestamp +import org.isoron.uhabits.core.ui.views.Theme import java.util.HashMap data class FrequencyCardState( val color: PaletteColor, val firstWeekday: Int, val frequency: HashMap>, + val theme: Theme, ) class FrequencyCardPresenter { @@ -35,12 +37,14 @@ class FrequencyCardPresenter { fun buildState( habit: Habit, firstWeekday: Int, + theme: Theme ) = FrequencyCardState( color = habit.color, frequency = habit.originalEntries.computeWeekdayFrequency( isNumerical = habit.isNumerical ), firstWeekday = firstWeekday, + theme = theme, ) } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/OverviewCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/OverviewCard.kt index 3cd66fad4..d9d431112 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/OverviewCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/OverviewCard.kt @@ -22,6 +22,7 @@ package org.isoron.uhabits.core.ui.screens.habits.show.views import org.isoron.uhabits.core.models.Entry import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.ui.views.Theme import org.isoron.uhabits.core.utils.DateUtils data class OverviewCardState( @@ -30,11 +31,12 @@ data class OverviewCardState( val scoreYearDiff: Float, val scoreToday: Float, val totalCount: Long, + val theme: Theme, ) class OverviewCardPresenter { companion object { - fun buildState(habit: Habit): OverviewCardState { + fun buildState(habit: Habit, theme: Theme): OverviewCardState { val today = DateUtils.getTodayWithOffset() val lastMonth = today.minus(30) val lastYear = today.minus(365) @@ -52,6 +54,7 @@ class OverviewCardPresenter { scoreMonthDiff = scoreToday - scoreLastMonth, scoreYearDiff = scoreToday - scoreLastYear, totalCount = totalCount, + theme = theme, ) } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/ScoreCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/ScoreCard.kt index 4d487a103..92268a7c0 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/ScoreCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/ScoreCard.kt @@ -23,6 +23,7 @@ import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.core.models.Score import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.core.ui.views.Theme import org.isoron.uhabits.core.utils.DateUtils data class ScoreCardState( @@ -30,6 +31,7 @@ data class ScoreCardState( val bucketSize: Int, val spinnerPosition: Int, val color: PaletteColor, + val theme: Theme, ) class ScoreCardPresenter( @@ -53,6 +55,7 @@ class ScoreCardPresenter( habit: Habit, firstWeekday: Int, spinnerPosition: Int, + theme: Theme, ): ScoreCardState { val bucketSize = BUCKET_SIZES[spinnerPosition] val today = DateUtils.getTodayWithOffset() @@ -77,6 +80,7 @@ class ScoreCardPresenter( scores = scores, bucketSize = bucketSize, spinnerPosition = spinnerPosition, + theme = theme, ) } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/StreakCart.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/StreakCart.kt index 610a947e5..97700f633 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/StreakCart.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/StreakCart.kt @@ -22,18 +22,21 @@ package org.isoron.uhabits.core.ui.screens.habits.show.views import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.core.models.Streak +import org.isoron.uhabits.core.ui.views.Theme data class StreakCardState( val color: PaletteColor, - val bestStreaks: List + val bestStreaks: List, + val theme: Theme, ) class StreakCartPresenter { companion object { - fun buildState(habit: Habit): StreakCardState { + fun buildState(habit: Habit, theme: Theme): StreakCardState { return StreakCardState( color = habit.color, bestStreaks = habit.streaks.getBest(10), + theme = theme, ) } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/SubtitleCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/SubtitleCard.kt index 01d91f199..525f8fc7c 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/SubtitleCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/SubtitleCard.kt @@ -23,6 +23,7 @@ import org.isoron.uhabits.core.models.Frequency import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.core.models.Reminder +import org.isoron.uhabits.core.ui.views.Theme data class SubtitleCardState( val color: PaletteColor, @@ -32,12 +33,14 @@ data class SubtitleCardState( val reminder: Reminder?, val targetValue: Double, val unit: String, + val theme: Theme, ) class SubtitleCardPresenter { companion object { fun buildState( habit: Habit, + theme: Theme, ): SubtitleCardState = SubtitleCardState( color = habit.color, frequency = habit.frequency, @@ -46,6 +49,7 @@ class SubtitleCardPresenter { reminder = habit.reminder, targetValue = habit.targetValue, unit = habit.unit, + theme = theme, ) } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/TargetCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/TargetCard.kt index 47884a732..15d500def 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/TargetCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/TargetCard.kt @@ -22,6 +22,7 @@ package org.isoron.uhabits.core.ui.screens.habits.show.views import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.core.models.groupedSum +import org.isoron.uhabits.core.ui.views.Theme import org.isoron.uhabits.core.utils.DateUtils import java.util.ArrayList import java.util.Calendar @@ -31,6 +32,7 @@ data class TargetCardState( val values: List = listOf(), val targets: List = listOf(), val intervals: List = listOf(), + val theme: Theme, ) class TargetCardPresenter { @@ -38,6 +40,7 @@ class TargetCardPresenter { fun buildState( habit: Habit, firstWeekday: Int, + theme: Theme, ): TargetCardState { val today = DateUtils.getTodayWithOffset() val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today @@ -106,6 +109,7 @@ class TargetCardPresenter { values = values, targets = targets, intervals = intervals, + theme = theme, ) } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/Themes.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/Themes.kt index 7f43541f7..1b1d989e4 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/Themes.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/Themes.kt @@ -20,6 +20,7 @@ package org.isoron.uhabits.core.ui.views import org.isoron.platform.gui.Color +import org.isoron.uhabits.core.models.PaletteColor abstract class Theme { open val appBackgroundColor = Color(0xf4f4f4) @@ -35,6 +36,10 @@ abstract class Theme { open val toolbarBackgroundColor = Color(0xf4f4f4) open val toolbarColor = Color(0xffffff) + fun color(paletteColor: PaletteColor): Color { + return color(paletteColor.paletteIndex) + } + open fun color(paletteIndex: Int): Color { return when (paletteIndex) { 0 -> Color(0xD32F2F)