diff --git a/lawnchair/res/values/config.xml b/lawnchair/res/values/config.xml index 530955f4e8..3cba97b869 100644 --- a/lawnchair/res/values/config.xml +++ b/lawnchair/res/values/config.xml @@ -67,6 +67,9 @@ true false false + true + false + false 1.0 1.0 diff --git a/lawnchair/res/values/strings.xml b/lawnchair/res/values/strings.xml index 7b11917c33..f9270c7885 100644 --- a/lawnchair/res/values/strings.xml +++ b/lawnchair/res/values/strings.xml @@ -235,7 +235,10 @@ %1$s, %2$s - EEEMMMd + EEEMMMd + HH:mm + hh:mm aa + dd MMMM l، j F Charging Charged @@ -249,6 +252,10 @@ Preview Calendar + Date & Time + Date + Time + 24-Hour Format Weather Battery Status Now Playing diff --git a/lawnchair/src/app/lawnchair/preferences2/PreferenceManager2.kt b/lawnchair/src/app/lawnchair/preferences2/PreferenceManager2.kt index 883ff2c03e..ef4b03861f 100644 --- a/lawnchair/src/app/lawnchair/preferences2/PreferenceManager2.kt +++ b/lawnchair/src/app/lawnchair/preferences2/PreferenceManager2.kt @@ -282,6 +282,21 @@ class PreferenceManager2(private val context: Context) : PreferenceManager { defaultValue = true ) + val smartspaceShowDate = preference( + key = booleanPreferencesKey("smartspace_show_date"), + defaultValue = context.resources.getBoolean(R.bool.config_default_smartspace_show_date), + ) + + val smartspaceShowTime = preference( + key = booleanPreferencesKey("smartspace_show_time"), + defaultValue = context.resources.getBoolean(R.bool.config_default_smartspace_show_time), + ) + + val smartspace24HourFormat = preference( + key = booleanPreferencesKey("smartspace_24_hour_format"), + defaultValue = context.resources.getBoolean(R.bool.config_default_smartspace_24_hour_format), + ) + val smartspaceCalendar = preference( key = stringPreferencesKey(name = "smartspace_calendar"), defaultValue = SmartspaceCalendar.fromString(context.getString(R.string.config_default_smart_space_calendar)), diff --git a/lawnchair/src/app/lawnchair/smartspace/IcuDateTextView.kt b/lawnchair/src/app/lawnchair/smartspace/IcuDateTextView.kt index 1ae1c12764..cf9bffdbef 100644 --- a/lawnchair/src/app/lawnchair/smartspace/IcuDateTextView.kt +++ b/lawnchair/src/app/lawnchair/smartspace/IcuDateTextView.kt @@ -24,6 +24,10 @@ class IcuDateTextView @JvmOverloads constructor( private lateinit var preferenceManager2: PreferenceManager2 private var calendar: SmartspaceCalendar? = null + private var showDate: Boolean = true + private var showTime: Boolean = false + private var time24HourFormat: Boolean = false + private var formatterUpdateRequired = true private var formatterGregorian: DateFormat? = null private var formatterPersian: PersianDateFormat? = null private val ticker = this::onTimeTick @@ -50,8 +54,8 @@ class IcuDateTextView @JvmOverloads constructor( private fun onTimeChanged(updateFormatter: Boolean) { if (isShown) { val timeText = when (calendar) { - SmartspaceCalendar.Persian -> getTimeTextPersian(updateFormatter = updateFormatter) - else -> getTimeTextGregorian(updateFormatter = updateFormatter) + SmartspaceCalendar.Persian -> getTimeTextPersian(updateFormatter = updateFormatter || formatterUpdateRequired) + else -> getTimeTextGregorian(updateFormatter = updateFormatter || formatterUpdateRequired) } if (text != timeText) { textAlignment = @@ -67,21 +71,35 @@ class IcuDateTextView @JvmOverloads constructor( context.getString(R.string.smartspace_icu_date_pattern_persian), PersianDateFormat.PersianDateNumberCharacter.FARSI, ).also { formatterPersian = it } + formatterUpdateRequired = false return formatter.format(PersianDate(System.currentTimeMillis())) } private fun getTimeTextGregorian(updateFormatter: Boolean): String { - val formatter = formatterGregorian.takeIf { updateFormatter.not() } - ?: DateFormat.getInstanceForSkeleton( - context.getString(R.string.smartspace_icu_date_pattern_gregorian), - Locale.getDefault() - ).also { - it.setContext(DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE) - formatterGregorian = it - } + val formatter = getGregorianFormatter(updateFormatter = updateFormatter) return formatter.format(System.currentTimeMillis()) } + private fun getGregorianFormatter(updateFormatter: Boolean): DateFormat { + var formatter = formatterGregorian.takeIf { updateFormatter.not() } ?: DateFormat.getInstanceForSkeleton( + context.getString(R.string.smartspace_icu_date_pattern_gregorian_wday_month_day_no_year), + Locale.getDefault() + ) + formatter.setContext(DisplayContext.CAPITALIZATION_FOR_STANDALONE) + if (showTime) { + var format = context.getString( + if (time24HourFormat) R.string.smartspace_icu_date_pattern_gregorian_time + else R.string.smartspace_icu_date_pattern_gregorian_time_12h + ) + if (showDate) format += context.getString(R.string.smartspace_icu_date_pattern_gregorian_date) + DateFormat.getInstanceForSkeleton(format, Locale.getDefault()).also { + formatter = it + }.setContext(DisplayContext.CAPITALIZATION_FOR_STANDALONE) + } + formatterUpdateRequired = false + return formatter + } + private fun onTimeTick() { onTimeChanged(false) val uptimeMillis: Long = SystemClock.uptimeMillis() @@ -91,6 +109,7 @@ class IcuDateTextView @JvmOverloads constructor( override fun onFinishInflate() { super.onFinishInflate() preferenceManager2 = PreferenceManager2.getInstance(context) + val calendarSelectionEnabled = preferenceManager2.enableSmartspaceCalendarSelection.firstBlocking() if (calendarSelectionEnabled) { @@ -100,6 +119,25 @@ class IcuDateTextView @JvmOverloads constructor( } else { calendar = preferenceManager2.smartspaceCalendar.defaultValue } + + preferenceManager2.smartspaceShowDate.subscribeBlocking(scope = viewAttachedScope) { + if (it != showDate) { + formatterUpdateRequired = true + showDate = it + } + } + preferenceManager2.smartspaceShowTime.subscribeBlocking(scope = viewAttachedScope) { + if (it != showTime) { + formatterUpdateRequired = true + showTime = it + } + } + preferenceManager2.smartspace24HourFormat.subscribeBlocking(scope = viewAttachedScope) { + if (it != time24HourFormat) { + formatterUpdateRequired = true + time24HourFormat = it + } + } } override fun onVisibilityAggregated(isVisible: Boolean) { diff --git a/lawnchair/src/app/lawnchair/ui/preferences/SmartspacePreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/SmartspacePreferences.kt index ced93cef90..e73ea8ffab 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/SmartspacePreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/SmartspacePreferences.kt @@ -4,7 +4,12 @@ import android.app.Activity import android.view.ContextThemeWrapper import android.view.ViewGroup import android.view.ViewGroup.LayoutParams.MATCH_PARENT +import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.Crossfade +import androidx.compose.animation.expandVertically +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable @@ -62,11 +67,6 @@ fun SmartspacePreferences(fromWidget: Boolean) { heading = stringResource(id = R.string.what_to_show), modifier = Modifier.padding(top = 8.dp), ) { - val calendarSelectionEnabled = - preferenceManager2.enableSmartspaceCalendarSelection.getAdapter() - if (calendarSelectionEnabled.state.value) { - SmartspaceCalendarPreference() - } smartspaceProvider.dataSources .filter { it.isAvailable } .forEach { @@ -78,6 +78,7 @@ fun SmartspacePreferences(fromWidget: Boolean) { } } } + SmartspaceDateAndTimePreferences() } } } @@ -114,6 +115,62 @@ fun SmartspacePreview() { } } +@Composable +fun SmartspaceDateAndTimePreferences() { + PreferenceGroup( + heading = stringResource(id = R.string.smartspace_date_and_time), + modifier = Modifier.padding(top = 8.dp), + ) { + val preferenceManager2 = preferenceManager2() + + val calendarAdapter = preferenceManager2.smartspaceCalendar.getAdapter() + val showDateAdapter = preferenceManager2.smartspaceShowDate.getAdapter() + val showTimeAdapter = preferenceManager2.smartspaceShowTime.getAdapter() + val use24HourFormatAdapter = preferenceManager2.smartspace24HourFormat.getAdapter() + + val calendarHasMinimumContent = !showDateAdapter.state.value || !showTimeAdapter.state.value + val isGregorian = calendarAdapter.state.value != SmartspaceCalendar.Persian + + AnimatedVisibility( + visible = isGregorian, + enter = expandVertically() + fadeIn(), + exit = shrinkVertically() + fadeOut() + ) { + SwitchPreference( + adapter = showDateAdapter, + label = stringResource(id = R.string.smartspace_date), + enabled = if (showDateAdapter.state.value) !calendarHasMinimumContent else true, + ) + } + AnimatedVisibility( + visible = isGregorian, + enter = expandVertically() + fadeIn(), + exit = shrinkVertically() + fadeOut() + ) { + SwitchPreference( + adapter = showTimeAdapter, + label = stringResource(id = R.string.smartspace_time), + enabled = if (showTimeAdapter.state.value) !calendarHasMinimumContent else true, + ) + } + AnimatedVisibility( + visible = isGregorian && showTimeAdapter.state.value, + enter = expandVertically() + fadeIn(), + exit = shrinkVertically() + fadeOut() + ) { + SwitchPreference( + adapter = use24HourFormatAdapter, + label = stringResource(id = R.string.smartspace_time_24_hour_format), + ) + } + val calendarSelectionEnabled = + preferenceManager2.enableSmartspaceCalendarSelection.getAdapter() + if (calendarSelectionEnabled.state.value) { + SmartspaceCalendarPreference() + } + } +} + @Composable fun SmartspaceCalendarPreference() {