Add Persian Calendar support to Glance

Co-authored-by: Daria Hamrah Paytakht <info@dariarnd.ir>
Co-authored-by: Patryk Michalik <icontact@patrykmichalik.com>
Co-authored-by: Suphon Thanakornpakapong <paphonb@gmail.com>
This commit is contained in:
Yasan Ghaffarian
2022-05-23 11:04:22 +04:30
parent 74731de6f1
commit 141ee330c1
6 changed files with 111 additions and 9 deletions
+3
View File
@@ -44,6 +44,9 @@
<!-- Which icon shape to use by default -->
<string name="config_default_icon_shape" translatable="false">circle</string>
<!-- Which calendar to use on smartspace by default -->
<string name="config_default_smart_space_calendar" translatable="false">gregorian</string>
<bool name="config_default_dark_status_bar">false</bool>
<bool name="config_default_dock_search_bar">true</bool>
<bool name="config_default_show_notification_count">false</bool>
+6 -1
View File
@@ -233,7 +233,8 @@
<!-- Smartspace -->
<string name="generic_smartspace_concatenated_desc">%1$s, %2$s</string>
<string name="smartspace_icu_date_pattern" translatable="false">EEEMMMd</string>
<string name="smartspace_icu_date_pattern_gregorian" translatable="false">EEEMMMd</string>
<string name="smartspace_icu_date_pattern_persian" translatable="false">l، j F</string>
<string name="smartspace_battery_charging">Charging</string>
<string name="smartspace_battery_full">Charged</string>
<string name="smartspace_battery_low">Battery Low</string>
@@ -245,6 +246,7 @@
<string name="quickstep_incompatible_description">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.</string>
<string name="preview_label">Preview</string>
<string name="smartspace_calendar">Calendar</string>
<string name="smartspace_weather">Weather</string>
<string name="smartspace_battery_status">Battery Status</string>
<string name="smartspace_now_playing">Now Playing</string>
@@ -252,6 +254,9 @@
<string name="event_provider_missing_notification_dots">To use <xliff:g example="My Provider" id="providerName">%1$s</xliff:g>, enable Notification Dots.</string>
<string name="smartspace_media_info_separator">" — "</string>
<string name="smartspace_calendar_gregorian">Gregorian</string>
<string name="smartspace_calendar_persian">Persian</string>
<string name="pref_fonts_add_fonts">Add Fonts</string>
<string name="pref_fonts_add_fonts_summary">OTF &amp; TTF supported.</string>
<string name="delete">Delete</string>
@@ -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()
@@ -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)
@@ -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"
}
}
@@ -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),
)
}