diff --git a/lawnchair/res/values/config.xml b/lawnchair/res/values/config.xml index d83152f463..cb5827a882 100644 --- a/lawnchair/res/values/config.xml +++ b/lawnchair/res/values/config.xml @@ -44,6 +44,9 @@ circle + + gregorian + false true false diff --git a/lawnchair/res/values/strings.xml b/lawnchair/res/values/strings.xml index 0673aebc77..f92c759b49 100644 --- a/lawnchair/res/values/strings.xml +++ b/lawnchair/res/values/strings.xml @@ -233,7 +233,8 @@ %1$s, %2$s - EEEMMMd + EEEMMMd + l، j F Charging Charged Battery Low @@ -245,6 +246,7 @@ Your device is configured to have system gestures (known as Quickstep) provided by %1$s, but this version of %1$s is not compatible with your Android version. To continue using your device, please uninstall %1$s updates or disable %1$s as a system-gesture provider. Preview + Calendar Weather Battery Status Now Playing @@ -252,6 +254,9 @@ To use %1$s, enable Notification Dots. " — " + Gregorian + Persian + Add Fonts OTF & TTF supported. Delete diff --git a/lawnchair/src/app/lawnchair/preferences2/PreferenceManager2.kt b/lawnchair/src/app/lawnchair/preferences2/PreferenceManager2.kt index 0b545cb69a..b84e97d2b9 100644 --- a/lawnchair/src/app/lawnchair/preferences2/PreferenceManager2.kt +++ b/lawnchair/src/app/lawnchair/preferences2/PreferenceManager2.kt @@ -26,6 +26,7 @@ import app.lawnchair.icons.CustomAdaptiveIconDrawable import app.lawnchair.icons.shape.IconShape import app.lawnchair.icons.shape.IconShapeManager import app.lawnchair.qsb.providers.QsbSearchProvider +import app.lawnchair.smartspace.model.SmartspaceCalendar import app.lawnchair.theme.color.ColorOption import com.android.launcher3.InvariantDeviceProfile import com.android.launcher3.LauncherAppState @@ -276,6 +277,13 @@ class PreferenceManager2(private val context: Context) : PreferenceManager { defaultValue = true ) + val smartspaceCalendar = preference( + key = stringPreferencesKey(name = "smartspace_calendar"), + defaultValue = SmartspaceCalendar.fromString(context.getString(R.string.config_default_smart_space_calendar)), + parse = { SmartspaceCalendar.fromString(it) }, + save = { it.toString() }, + ) + init { initializeIconShape(iconShape.firstBlocking()) iconShape.get() diff --git a/lawnchair/src/app/lawnchair/smartspace/IcuDateTextView.kt b/lawnchair/src/app/lawnchair/smartspace/IcuDateTextView.kt index 4afcbb081d..9d446e853f 100644 --- a/lawnchair/src/app/lawnchair/smartspace/IcuDateTextView.kt +++ b/lawnchair/src/app/lawnchair/smartspace/IcuDateTextView.kt @@ -8,14 +8,23 @@ import android.icu.text.DateFormat import android.icu.text.DisplayContext import android.os.SystemClock import android.util.AttributeSet +import app.lawnchair.preferences2.PreferenceManager2 +import app.lawnchair.preferences2.subscribeBlocking +import app.lawnchair.smartspace.model.SmartspaceCalendar +import app.lawnchair.util.viewAttachedScope import com.android.launcher3.R +import saman.zamani.persiandate.PersianDate +import saman.zamani.persiandate.PersianDateFormat import java.util.* class IcuDateTextView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null ) : DoubleShadowTextView(context, attrs) { - private var formatter: DateFormat? = null + private lateinit var preferenceManager2: PreferenceManager2 + private var calendar: SmartspaceCalendar? = null + private var formatterGregorian: DateFormat? = null + private var formatterPersian: PersianDateFormat? = null private val ticker = this::onTimeTick private val intentReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { @@ -39,27 +48,50 @@ class IcuDateTextView @JvmOverloads constructor( private fun onTimeChanged(updateFormatter: Boolean) { if (isShown) { - if (formatter == null || updateFormatter) { - val formatter: DateFormat = DateFormat.getInstanceForSkeleton( - context.getString(R.string.smartspace_icu_date_pattern), Locale.getDefault() - ) - this.formatter = formatter - formatter.setContext(DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE) + val format = when (calendar) { + SmartspaceCalendar.Persian -> getTimeTextPersian(updateFormatter = updateFormatter) + else -> getTimeTextGregorian(updateFormatter = updateFormatter) } - val format = formatter!!.format(java.lang.Long.valueOf(System.currentTimeMillis())) if (text != format) { + textAlignment = + if (calendar == SmartspaceCalendar.Persian) TEXT_ALIGNMENT_TEXT_END else TEXT_ALIGNMENT_TEXT_START text = format contentDescription = format } } } + private fun getTimeTextPersian(updateFormatter: Boolean): String { + val formatter = formatterPersian.takeIf { updateFormatter.not() } ?: PersianDateFormat( + context.getString(R.string.smartspace_icu_date_pattern_persian), + PersianDateFormat.PersianDateNumberCharacter.FARSI, + ).also { formatterPersian = it } + return formatter.format(PersianDate(java.lang.Long.valueOf(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 { formatterGregorian = it } + return formatter.format(java.lang.Long.valueOf(System.currentTimeMillis())) + } + private fun onTimeTick() { onTimeChanged(false) val uptimeMillis: Long = SystemClock.uptimeMillis() handler?.postAtTime(ticker, uptimeMillis + (1000 - uptimeMillis % 1000)) } + override fun onFinishInflate() { + super.onFinishInflate() + preferenceManager2 = PreferenceManager2.getInstance(context) + preferenceManager2.smartspaceCalendar.subscribeBlocking(scope = viewAttachedScope) { + calendar = it + } + } + override fun onVisibilityAggregated(isVisible: Boolean) { super.onVisibilityAggregated(isVisible) handler?.removeCallbacks(ticker) diff --git a/lawnchair/src/app/lawnchair/smartspace/model/SmartspaceCalendar.kt b/lawnchair/src/app/lawnchair/smartspace/model/SmartspaceCalendar.kt new file mode 100644 index 0000000000..3b67e1e0fb --- /dev/null +++ b/lawnchair/src/app/lawnchair/smartspace/model/SmartspaceCalendar.kt @@ -0,0 +1,31 @@ +package app.lawnchair.smartspace.model + +import androidx.annotation.StringRes +import com.android.launcher3.R + +/** + * Contains the data of a single calendar system for smartspace. + */ +open class SmartspaceCalendar(@StringRes val nameResourceId: Int) { + + companion object { + + fun fromString(value: String): SmartspaceCalendar = when (value) { + "persian" -> Persian + else -> Gregorian + } + + /** + * @return The list of all calendars. + */ + fun values() = listOf(Gregorian, Persian) + } + + object Gregorian : SmartspaceCalendar(nameResourceId = R.string.smartspace_calendar_gregorian) { + override fun toString() = "gregorian" + } + object Persian : SmartspaceCalendar(nameResourceId = R.string.smartspace_calendar_persian) { + override fun toString() = "persian" + } + +} \ No newline at end of file diff --git a/lawnchair/src/app/lawnchair/ui/preferences/SmartspacePreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/SmartspacePreferences.kt index 6648d5a5a9..4a9630bfd0 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/SmartspacePreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/SmartspacePreferences.kt @@ -21,7 +21,10 @@ import androidx.navigation.NavGraphBuilder import app.lawnchair.preferences.getAdapter import app.lawnchair.preferences2.preferenceManager2 import app.lawnchair.smartspace.SmartspaceViewContainer +import app.lawnchair.smartspace.model.SmartspaceCalendar import app.lawnchair.smartspace.provider.SmartspaceProvider +import app.lawnchair.ui.preferences.components.ListPreference +import app.lawnchair.ui.preferences.components.ListPreferenceEntry import app.lawnchair.ui.preferences.components.PreferenceGroup import app.lawnchair.ui.preferences.components.PreferenceLayout import app.lawnchair.ui.preferences.components.SwitchPreference @@ -59,6 +62,7 @@ fun SmartspacePreferences(fromWidget: Boolean) { heading = stringResource(id = R.string.what_to_show), modifier = Modifier.padding(top = 8.dp), ) { + SmartspaceCalendarPreference() smartspaceProvider.dataSources .filter { it.isAvailable } .forEach { @@ -105,3 +109,22 @@ fun SmartspacePreview() { } } } + +@Composable +fun SmartspaceCalendarPreference() { + + val entries = remember { + SmartspaceCalendar.values().map { calendar -> + ListPreferenceEntry(calendar) { stringResource(id = calendar.nameResourceId) } + } + } + + val adapter = preferenceManager2().smartspaceCalendar.getAdapter() + + ListPreference( + adapter = adapter, + entries = entries, + label = stringResource(id = R.string.smartspace_calendar), + ) +} +