mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-08 10:08:51 -06:00
Merge branch 'master' into dev
This commit is contained in:
@@ -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() }
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -35,7 +35,12 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.android.datetimepicker.time.RadialPickerLayout
|
||||
import com.android.datetimepicker.time.TimePickerDialog
|
||||
import kotlinx.android.synthetic.main.activity_edit_habit.*
|
||||
import kotlinx.android.synthetic.main.activity_edit_habit.nameInput
|
||||
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
|
||||
@@ -56,7 +61,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)
|
||||
@@ -149,7 +153,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()
|
||||
@@ -321,7 +325,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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) })
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -109,7 +109,7 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
|
||||
}
|
||||
|
||||
protected fun getHabitsFromWidgetId(widgetId: Int): List<Habit> {
|
||||
val selectedIds = widgetPrefs.getHabitIdsFromWidgetId(widgetId)!!
|
||||
val selectedIds = widgetPrefs.getHabitIdsFromWidgetId(widgetId)
|
||||
val selectedHabits = ArrayList<Habit>(selectedIds.size)
|
||||
for (id in selectedIds) {
|
||||
val h = habits.getById(id) ?: throw HabitNotFoundException()
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<RemoteViews>()
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user