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:
@@ -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>
|
||||
|
||||
@@ -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 & 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),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user