Skip to content

Commit

Permalink
feat: support for changing widget text color (closes #364)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bnyro committed Feb 8, 2025
1 parent aed3f4d commit b3d49a9
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.bnyro.clock.domain.model

import com.bnyro.clock.util.widgets.TextColor

data class ClockWidgetOptions(
var showDate: Boolean = true,
var showTime: Boolean = true,
Expand All @@ -8,6 +10,8 @@ data class ClockWidgetOptions(
var showBackground: Boolean = true,
var dateTextSize: Float,
var timeTextSize: Float,
var timeColor: TextColor = TextColor.Primary,
var dateColor: TextColor = TextColor.Secondary
) {
companion object {
val dateSizeOptions = listOf(
Expand Down Expand Up @@ -38,5 +42,7 @@ data class ClockWidgetOptions(
96f,
100f
)

val textColorOptions = TextColor.entries.toList()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.bnyro.clock.presentation.widgets

import android.app.Activity
import android.appwidget.AppWidgetManager
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.widget.RemoteViews
Expand All @@ -13,14 +14,21 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.rounded.CalendarToday
import androidx.compose.material.icons.rounded.ExpandMore
import androidx.compose.material.icons.rounded.FormatSize
Expand All @@ -35,6 +43,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
Expand All @@ -44,6 +53,8 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
Expand All @@ -57,13 +68,16 @@ import com.bnyro.clock.presentation.screens.clock.model.ClockModel
import com.bnyro.clock.presentation.screens.settings.model.SettingsModel
import com.bnyro.clock.ui.theme.ClockYouTheme
import com.bnyro.clock.util.ThemeUtil
import com.bnyro.clock.util.widgets.TextColor
import com.bnyro.clock.util.widgets.getColorValue
import com.bnyro.clock.util.widgets.loadClockWidgetSettings
import com.bnyro.clock.util.widgets.saveClockWidgetSettings


abstract class ClockWidgetConfig : ComponentActivity() {

abstract val defaultOptions: ClockWidgetOptions

@get:LayoutRes
abstract val widgetLayoutResource: Int

Expand Down Expand Up @@ -100,6 +114,7 @@ abstract class ClockWidgetConfig : ComponentActivity() {
darkTheme
)
) {
val context = LocalContext.current
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
Expand All @@ -109,20 +124,22 @@ abstract class ClockWidgetConfig : ComponentActivity() {
}) { pV ->
DigitalClockWidgetSettings(
modifier = Modifier.padding(pV),
options = options, onComplete = this::complete
)
options = options
) {
complete(context, options)
}
}
}
}
}
}

private fun complete(options: ClockWidgetOptions) {
private fun complete(context: Context, options: ClockWidgetOptions) {
saveClockWidgetSettings(appWidgetId, options)

val appWidgetManager = AppWidgetManager.getInstance(this)
val views = RemoteViews(packageName, widgetLayoutResource)
updateClockWidget(views, options)
updateClockWidget(context, views, options)
appWidgetManager.updateAppWidget(appWidgetId, views)

// return the result
Expand All @@ -131,7 +148,11 @@ abstract class ClockWidgetConfig : ComponentActivity() {
finish()
}

abstract fun updateClockWidget(views: RemoteViews, options: ClockWidgetOptions)
abstract fun updateClockWidget(
context: Context,
views: RemoteViews,
options: ClockWidgetOptions
)
}

@Composable
Expand All @@ -153,6 +174,9 @@ fun DigitalClockWidgetSettings(
var showBackgroundOption by remember { mutableStateOf(options.showBackground) }
var selectedDateSize by remember { mutableFloatStateOf(options.dateTextSize) }
var selectedTimeSize by remember { mutableFloatStateOf(options.timeTextSize) }
var selectedTimeColor by remember { mutableStateOf(options.timeColor) }
var selectedDateColor by remember { mutableStateOf(options.dateColor) }

Column(
modifier = modifier.padding(8.dp),
horizontalAlignment = Alignment.CenterHorizontally,
Expand Down Expand Up @@ -194,6 +218,20 @@ fun DigitalClockWidgetSettings(
) {
selectedTimeSize = it
}
ColorSelectSetting(
label = stringResource(R.string.date_text_color),
availableColors = ClockWidgetOptions.textColorOptions,
currentColor = selectedDateColor
) {
selectedDateColor = it
}
ColorSelectSetting(
label = stringResource(R.string.time_text_color),
availableColors = ClockWidgetOptions.textColorOptions,
currentColor = selectedTimeColor
) {
selectedTimeColor = it
}
SwitchWithDivider(
title = stringResource(R.string.timezone),
description = stringResource(R.string.use_a_different_time_zone_for_the_widget),
Expand All @@ -219,6 +257,8 @@ fun DigitalClockWidgetSettings(
showTime = showTimeOption
dateTextSize = selectedDateSize
timeTextSize = selectedTimeSize
dateColor = selectedDateColor
timeColor = selectedTimeColor
timeZone = customTimeZone
timeZoneName = customTimeZoneName
showBackground = showBackgroundOption
Expand Down Expand Up @@ -314,6 +354,50 @@ fun TextSizeSelectSetting(
}
}

@Composable
fun ColorSelectSetting(
label: String,
availableColors: List<TextColor>,
currentColor: TextColor,
onColorSelected: (TextColor) -> Unit
) {
val context = LocalContext.current

Column(
Modifier.padding(horizontal = 12.dp, vertical = 8.dp)
) {
Text(label)
Spacer(modifier = Modifier.height(6.dp))
LazyRow(
verticalAlignment = Alignment.CenterVertically
) {
items(availableColors) { textColor ->
val colorValue = Color(textColor.getColorValue(context))

Box(
modifier = Modifier
.padding(horizontal = 8.dp)
.clip(CircleShape)
.size(36.dp)
.background(colorValue)
.clickable {
onColorSelected(textColor)
}
) {
if (currentColor == textColor) {
Icon(
modifier = Modifier.align(Alignment.Center),
imageVector = Icons.Default.Check,
contentDescription = null,
tint = MaterialTheme.colorScheme.contentColorFor(colorValue)
)
}
}
}
}
}
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import android.view.View
import android.widget.RemoteViews
import com.bnyro.clock.R
import com.bnyro.clock.domain.model.ClockWidgetOptions
import com.bnyro.clock.util.widgets.getColorValue
import com.bnyro.clock.util.widgets.loadClockWidgetSettings

class DigitalClockWidget : TextWidgetProvider() {
override val widgetLayoutResource = R.layout.digital_clock

override fun applyClockWidgetOptions(context: Context, appWidgetId: Int, views: RemoteViews) {
val options = context.loadClockWidgetSettings(appWidgetId, DefaultConfig)
views.applyDigitalClockWidgetOptions(options)
views.applyDigitalClockWidgetOptions(context, options)
}

companion object {
Expand All @@ -23,6 +24,7 @@ class DigitalClockWidget : TextWidgetProvider() {
)

fun RemoteViews.applyDigitalClockWidgetOptions(
context: Context,
options: ClockWidgetOptions
) {
val dateVisibility = when (options.showDate) {
Expand Down Expand Up @@ -53,6 +55,14 @@ class DigitalClockWidget : TextWidgetProvider() {
setString(R.id.textClock, "setTimeZone", options.timeZone)
setString(R.id.textClock2, "setTimeZone", options.timeZone)

val timeColor = options.timeColor.getColorValue(context)
val dateColor = options.dateColor.getColorValue(context)
if (timeColor != -1 && dateColor != -1) {
setTextColor(R.id.textClock, dateColor)
setTextColor(R.id.cityName, dateColor)
setTextColor(R.id.textClock2, timeColor)
}

setInt(R.id.frameLayout, "setBackgroundResource", backgroundResource)

setViewVisibility(R.id.cityName, timeZoneVisibility)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bnyro.clock.presentation.widgets

import android.content.Context
import android.widget.RemoteViews
import com.bnyro.clock.R
import com.bnyro.clock.domain.model.ClockWidgetOptions
Expand All @@ -9,7 +10,7 @@ class DigitalClockWidgetConfig: ClockWidgetConfig() {
override val defaultOptions: ClockWidgetOptions = DigitalClockWidget.DefaultConfig
override val widgetLayoutResource: Int = R.layout.digital_clock

override fun updateClockWidget(views: RemoteViews, options: ClockWidgetOptions) {
views.applyDigitalClockWidgetOptions(options)
override fun updateClockWidget(context: Context, views: RemoteViews, options: ClockWidgetOptions) {
views.applyDigitalClockWidgetOptions(context, options)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import android.view.View
import android.widget.RemoteViews
import com.bnyro.clock.R
import com.bnyro.clock.domain.model.ClockWidgetOptions
import com.bnyro.clock.presentation.widgets.DigitalClockWidget.Companion.applyDigitalClockWidgetOptions
import com.bnyro.clock.util.widgets.getColorValue
import com.bnyro.clock.util.widgets.loadClockWidgetSettings

class VerticalClockWidget : TextWidgetProvider() {
override val widgetLayoutResource = R.layout.vertical_clock

override fun applyClockWidgetOptions(context: Context, appWidgetId: Int, views: RemoteViews) {
val options = context.loadClockWidgetSettings(appWidgetId, DefaultConfig)
views.applyDigitalClockWidgetOptions(options)
views.applyVerticalClockWidgetOptions(context, options)
}

companion object {
Expand All @@ -24,6 +24,7 @@ class VerticalClockWidget : TextWidgetProvider() {
)

fun RemoteViews.applyVerticalClockWidgetOptions(
context: Context,
options: ClockWidgetOptions
) {
val dateVisibility = when (options.showDate) {
Expand Down Expand Up @@ -51,12 +52,21 @@ class VerticalClockWidget : TextWidgetProvider() {
setTextViewTextSize(R.id.textClockDate, TypedValue.COMPLEX_UNIT_SP, options.dateTextSize)
setTextViewTextSize(R.id.textClockHours, TypedValue.COMPLEX_UNIT_SP, options.timeTextSize)
setTextViewTextSize(R.id.textClockMinutes, TypedValue.COMPLEX_UNIT_SP, options.timeTextSize)
setTextViewTextSize(R.id.cityName, TypedValue.COMPLEX_UNIT_SP, options.dateTextSize - 4)
setTextViewTextSize(R.id.cityName, TypedValue.COMPLEX_UNIT_SP, options.dateTextSize)

setString(R.id.textClockHours, "setTimeZone", options.timeZone)
setString(R.id.textClockMinutes, "setTimeZone", options.timeZone)
setString(R.id.textClockDate, "setTimeZone", options.timeZone)

val timeColor = options.timeColor.getColorValue(context)
val dateColor = options.dateColor.getColorValue(context)
if (timeColor != -1 && dateColor != -1) {
setTextColor(R.id.textClockHours, timeColor)
setTextColor(R.id.textClockMinutes, timeColor)
setTextColor(R.id.textClockDate, dateColor)
setTextColor(R.id.cityName, dateColor)
}

setInt(R.id.frameLayout, "setBackgroundResource", backgroundResource)

setViewVisibility(R.id.cityName, timeZoneVisibility)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bnyro.clock.presentation.widgets

import android.content.Context
import android.widget.RemoteViews
import com.bnyro.clock.R
import com.bnyro.clock.domain.model.ClockWidgetOptions
Expand All @@ -9,7 +10,7 @@ class VerticalClockWidgetConfig: ClockWidgetConfig() {
override val defaultOptions: ClockWidgetOptions = VerticalClockWidget.DefaultConfig
override val widgetLayoutResource: Int = R.layout.vertical_clock

override fun updateClockWidget(views: RemoteViews, options: ClockWidgetOptions) {
views.applyVerticalClockWidgetOptions(options)
override fun updateClockWidget(context: Context, views: RemoteViews, options: ClockWidgetOptions) {
views.applyVerticalClockWidgetOptions(context, options)
}
}
20 changes: 20 additions & 0 deletions app/src/main/java/com/bnyro/clock/util/widgets/TextClockWIdget.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ fun Context.saveClockWidgetSettings(
putString(PREF_TIME_ZONE + appWidgetId, options.timeZone)
putString(PREF_TIME_ZONE_NAME + appWidgetId, options.timeZoneName)
putBoolean(PREF_SHOW_BACKGROUND + appWidgetId, options.showBackground)
putInt(PREF_DATE_TEXT_COLOR + appWidgetId, options.dateColor.attrInt)
putInt(PREF_TIME_TEXT_COLOR + appWidgetId, options.timeColor.attrInt)
}

fun Context.loadClockWidgetSettings(
Expand Down Expand Up @@ -53,11 +55,27 @@ fun Context.loadClockWidgetSettings(
defaultClockWidgetOptions.showBackground
)

val dateColor = getInt(
PREF_DATE_TEXT_COLOR + appWidgetId,
defaultClockWidgetOptions.dateColor.attrInt
).let { attrInt ->
ClockWidgetOptions.textColorOptions.find { it.attrInt == attrInt }
} ?: defaultClockWidgetOptions.dateColor

val timeColor = getInt(
PREF_TIME_TEXT_COLOR + appWidgetId,
defaultClockWidgetOptions.timeColor.attrInt
).let { attrInt ->
ClockWidgetOptions.textColorOptions.find { it.attrInt == attrInt }
} ?: defaultClockWidgetOptions.timeColor

return ClockWidgetOptions(
showDate = showDate,
showTime = showTime,
dateTextSize = dateTextSize,
timeTextSize = timeTextSize,
dateColor = dateColor,
timeColor = timeColor,
timeZone = timeZone,
timeZoneName = timeZoneName,
showBackground = showBackground
Expand All @@ -73,4 +91,6 @@ fun Context.deleteClockWidgetPref(appWidgetId: Int) =
remove(PREF_TIME_TEXT_SIZE + appWidgetId)
remove(PREF_TIME_ZONE + appWidgetId)
remove(PREF_TIME_ZONE_NAME + appWidgetId)
remove(PREF_DATE_TEXT_COLOR + appWidgetId)
remove(PREF_TIME_TEXT_COLOR + appWidgetId)
}
Loading

0 comments on commit b3d49a9

Please sign in to comment.