Refactor time formatting to use 24-hour system setting

Fixes #381
This commit is contained in:
Oscar Mira 2025-04-18 16:10:54 +02:00
parent f608ffbaa2
commit ef95e3d0e2
No known key found for this signature in database
GPG key ID: B371B98C5DC32237
4 changed files with 32 additions and 27 deletions

View file

@ -1308,6 +1308,7 @@
<receiver android:name=".notifications.LocaleChangedReceiver" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.TIME_SET"/> <!-- MOLLY: Triggered by 12/24h format change -->
<action android:name="android.intent.action.LOCALE_CHANGED"/>
</intent-filter>
</receiver>

View file

@ -1,16 +1,21 @@
package org.thoughtcrime.securesms.notifications;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import org.thoughtcrime.securesms.jobs.EmojiSearchIndexDownloadJob;
import org.thoughtcrime.securesms.service.ExportedBroadcastReceiver;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.DateUtils;
public class LocaleChangedReceiver extends ExportedBroadcastReceiver {
public class LocaleChangedReceiver extends BroadcastReceiver {
@Override
public void onReceiveUnlock(Context context, Intent intent) {
NotificationChannels.getInstance().onLocaleChanged();
EmojiSearchIndexDownloadJob.scheduleImmediately();
public void onReceive(Context context, Intent intent) {
DateUtils.updateFormat();
if (!KeyCachingService.isLocked()) {
NotificationChannels.getInstance().onLocaleChanged();
EmojiSearchIndexDownloadJob.scheduleImmediately();
}
}
}

View file

@ -26,6 +26,8 @@ import org.thoughtcrime.securesms.conversation.v2.computed.FormattedDate
import java.text.DateFormatSymbols
import java.text.ParseException
import java.text.SimpleDateFormat
import java.time.LocalTime
import java.time.format.DateTimeFormatter
import java.util.Calendar
import java.util.Date
import java.util.Locale
@ -36,7 +38,6 @@ import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds
import kotlin.time.DurationUnit
/**
@ -53,7 +54,12 @@ object DateUtils : android.text.format.DateUtils() {
private val dateFormatCache: MutableMap<TemplateLocale, SimpleDateFormat> = mutableMapOf()
private val dateFormatSymbolsCache: MutableMap<Locale, DateFormatSymbols> = mutableMapOf()
private var is24HourDateCache: Is24HourDateEntry? = null
private var is24HourFormatCache: Boolean? = null
@JvmStatic
fun updateFormat() {
is24HourFormatCache = null
}
/**
* A relative timestamp to use in space-constrained areas, like the conversation list.
@ -153,7 +159,16 @@ object DateUtils : android.text.format.DateUtils() {
*/
@JvmStatic
fun getOnlyTimeString(context: Context, timestamp: Long): String {
return timestamp.toLocalTime().formatHours(context)
return getOnlyTimeString(context, timestamp.toLocalTime())
}
@JvmStatic
fun getOnlyTimeString(context: Context, localTime: LocalTime): String {
val locale = Locale.getDefault()
val skeleton = if (context.is24HourFormat()) "HHmm" else "hhmma"
val pattern = skeleton.localizeTemplate(locale)
val formatter = DateTimeFormatter.ofPattern(pattern, locale)
return formatter.format(localTime)
}
/**
@ -391,15 +406,9 @@ object DateUtils : android.text.format.DateUtils() {
}
private fun Context.is24HourFormat(): Boolean {
is24HourDateCache?.let {
if (it.lastUpdated.isWithin(10.seconds)) {
return it.value
}
return is24HourFormatCache ?: DateFormat.is24HourFormat(this).also {
is24HourFormatCache = it
}
val result = DateFormat.is24HourFormat(this)
is24HourDateCache = Is24HourDateEntry(result, System.currentTimeMillis())
return result
}
private fun Long.convertDeltaTo(unit: DurationUnit): Int {
@ -439,6 +448,4 @@ object DateUtils : android.text.format.DateUtils() {
}
private data class TemplateLocale(val template: String, val locale: Locale)
private data class Is24HourDateEntry(val value: Boolean, val lastUpdated: Long)
}

View file

@ -1,8 +1,6 @@
package org.thoughtcrime.securesms.util
import android.content.Context
import android.os.Build
import android.text.format.DateFormat
import java.time.DayOfWeek
import java.time.Instant
import java.time.LocalDate
@ -12,8 +10,6 @@ import java.time.OffsetDateTime
import java.time.ZoneId
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
import java.time.temporal.WeekFields
import java.util.Locale
import java.util.concurrent.TimeUnit
@ -94,11 +90,7 @@ fun Long.toLocalTime(zoneId: ZoneId = ZoneId.systemDefault()): LocalTime {
* Formats [LocalTime] as localized time. For example, "8:00 AM"
*/
fun LocalTime.formatHours(context: Context): String {
return if (Build.VERSION.SDK_INT >= 26 || !DateFormat.is24HourFormat(context)) {
DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).format(this)
} else {
DateTimeFormatter.ofPattern("HH:mm", Locale.getDefault()).format(this)
}
return DateUtils.getOnlyTimeString(context, localTime = this)
}
/**