Skip to content

Commit 577860c

Browse files
committed
Added date time format customization
Fixes #133
1 parent e9c175e commit 577860c

File tree

15 files changed

+243
-57
lines changed

15 files changed

+243
-57
lines changed
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading

src/main/kotlin/com/jetpackduba/gitnuro/App.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ class App {
135135
val scale by appSettingsRepository.scaleUiFlow.collectAsState()
136136
val linesHeightType by appSettingsRepository.linesHeightTypeState.collectAsState()
137137
val avatarProviderType by appSettingsRepository.avatarProviderTypeFlow.collectAsState()
138+
val dateTimeFormat by appSettingsRepository.dateTimeFormatFlow.collectAsState()
138139

139140
val windowState = rememberWindowState(
140141
placement = windowPlacement,
@@ -166,6 +167,7 @@ class App {
166167
}
167168

168169
compositionValues.add(LocalAvatarProvider provides avatarProvider)
170+
compositionValues.add(LocalDateTimeFormat provides dateTimeFormat)
169171

170172
CompositionLocalProvider(
171173
values = compositionValues.toTypedArray()

src/main/kotlin/com/jetpackduba/gitnuro/AppConstants.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.jetpackduba.gitnuro
22

3+
import com.jetpackduba.gitnuro.models.DateTimeFormat
34
import com.jetpackduba.gitnuro.preferences.AvatarProviderType
45

56
object AppConstants {
@@ -50,4 +51,10 @@ object NetworkConstants {
5051

5152
object SettingsDefaults {
5253
val defaultAvatarProviderType = AvatarProviderType.GRAVATAR
54+
val defaultDateTimeFormat = DateTimeFormat(
55+
useSystemDefault = true,
56+
customFormat = "dd MMM yyyy",
57+
is24hours = true,
58+
useRelativeDate = true,
59+
)
5360
}

src/main/kotlin/com/jetpackduba/gitnuro/CompositionLocals.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ import com.jetpackduba.gitnuro.avatarproviders.NoneAvatarProvider
77

88
val LocalTabFocusRequester = compositionLocalOf { FocusRequester() }
99
val LocalAvatarProvider = compositionLocalOf<AvatarProvider> { NoneAvatarProvider() }
10+
val LocalDateTimeFormat = compositionLocalOf { SettingsDefaults.defaultDateTimeFormat }
Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,72 @@
11
package com.jetpackduba.gitnuro.extensions
22

3-
import java.text.DateFormat
3+
import androidx.compose.runtime.Composable
4+
import com.jetpackduba.gitnuro.LocalDateTimeFormat
5+
import java.time.Instant
46
import java.time.LocalDate
57
import java.time.ZoneId
8+
import java.time.format.DateTimeFormatter
9+
import java.time.format.FormatStyle
610
import java.util.*
711

8-
fun Date.toSmartSystemString(): String {
9-
val systemLocale = System.getProperty("user.language")
10-
val locale = Locale(systemLocale)
11-
val sdf = DateFormat.getDateInstance(DateFormat.MEDIUM, locale)
12+
@Composable
13+
fun Instant.toSmartSystemString(
14+
allowRelative: Boolean = true,
15+
useSystemDefaultFormat: Boolean? = null,
16+
showTime: Boolean = false,
17+
): String {
18+
val dateTimeFormat = LocalDateTimeFormat.current
19+
val useSystemDefault = useSystemDefaultFormat ?: dateTimeFormat.useSystemDefault
1220

1321
val zoneId = ZoneId.systemDefault()
14-
val localDate = this.toInstant().atZone(zoneId).toLocalDate()
22+
val localDate = atZone(zoneId).toLocalDate()
1523
val currentTime = LocalDate.now(zoneId)
1624

17-
var result = sdf.format(this)
18-
if (localDate.year == currentTime.year &&
19-
localDate.month == currentTime.month
25+
val formattedDate = if (
26+
dateTimeFormat.useRelativeDate &&
27+
allowRelative &&
28+
localDate.isTodayOrYesterday(currentTime)
2029
) {
2130
if (localDate.dayOfMonth == currentTime.dayOfMonth)
22-
result = "Today"
23-
else if (localDate.dayOfMonth == currentTime.dayOfMonth - 1)
24-
result = "Yesterday"
31+
"Today"
32+
else
33+
"Yesterday"
34+
} else {
35+
val systemLocale = System.getProperty("user.language")
36+
val locale = Locale(systemLocale)
37+
38+
val formatter = if (useSystemDefault) {
39+
DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
40+
} else {
41+
DateTimeFormatter.ofPattern(dateTimeFormat.customFormat, locale)
42+
}
43+
44+
formatter.format(localDate)
2545
}
2646

27-
return result
28-
}
47+
val formattedTime = if (showTime) {
48+
val localDateTime = atZone(zoneId).toLocalDateTime()
2949

30-
fun Date.toSystemString(): String {
31-
val systemLocale = System.getProperty("user.language")
32-
val locale = Locale(systemLocale)
33-
val sdf = DateFormat.getDateInstance(DateFormat.MEDIUM, locale)
50+
val timeFormatter = if (useSystemDefault) {
51+
DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
52+
} else if (dateTimeFormat.is24hours) {
53+
DateTimeFormatter.ofPattern("HH:mm")
54+
} else {
55+
DateTimeFormatter.ofPattern("hh:mm a")
56+
}
3457

35-
return sdf.format(this)
36-
}
58+
timeFormatter.format(localDateTime)
59+
} else {
60+
""
61+
}
3762

38-
fun Date.toSystemDateTimeString(): String {
39-
val systemLocale = System.getProperty("user.language")
40-
val locale = Locale(systemLocale)
41-
val sdf = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, locale)
63+
return "${formattedDate.trim()} ${formattedTime.trim()}".trim()
64+
}
4265

43-
return sdf.format(this)
66+
private fun LocalDate.isTodayOrYesterday(
67+
currentTime: LocalDate,
68+
): Boolean {
69+
return this.year == currentTime.year &&
70+
this.month == currentTime.month &&
71+
this.dayOfMonth in (currentTime.dayOfMonth - 1)..currentTime.dayOfMonth
4472
}

src/main/kotlin/com/jetpackduba/gitnuro/main.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.jetpackduba.gitnuro
22

3-
import com.jetpackduba.gitnuro.extensions.sha256
43
import com.jetpackduba.gitnuro.repositories.initPreferencesPath
54
import org.bouncycastle.jce.provider.BouncyCastleProvider
65
import java.security.Security
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.jetpackduba.gitnuro.models
2+
3+
data class DateTimeFormat(
4+
val useSystemDefault: Boolean,
5+
val customFormat: String,
6+
val is24hours: Boolean,
7+
val useRelativeDate: Boolean,
8+
)

src/main/kotlin/com/jetpackduba/gitnuro/repositories/AppSettingsRepository.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.jetpackduba.gitnuro.repositories
22

33
import com.jetpackduba.gitnuro.SettingsDefaults
44
import com.jetpackduba.gitnuro.extensions.defaultWindowPlacement
5+
import com.jetpackduba.gitnuro.models.DateTimeFormat
56
import com.jetpackduba.gitnuro.preferences.AvatarProviderType
67
import com.jetpackduba.gitnuro.preferences.WindowsPlacementPreference
78
import com.jetpackduba.gitnuro.system.OS
@@ -38,6 +39,10 @@ private const val PREF_TERMINAL_PATH = "terminalPath"
3839
private const val PREF_SHOW_CHANGES_AS_TREE = "showChangesAsTree"
3940
private const val PREF_USE_PROXY = "useProxy"
4041
private const val PREF_AVATAR_PROVIDER = "avatarProvider"
42+
private const val PREF_DATE_FORMAT_USE_DEFAULT = "dateFormatUseSystemDefault"
43+
private const val PREF_DATE_FORMAT_CUSTOM_FORMAT = "dateFormatCustomFormat"
44+
private const val PREF_DATE_FORMAT_IS_24H = "dateFormatIs24h"
45+
private const val PREF_DATE_FORMAT_USE_RELATIVE = "dateFormatUseRelative"
4146
private const val PREF_PROXY_TYPE = "proxyType"
4247
private const val PREF_PROXY_HOST_NAME = "proxyHostName"
4348
private const val PREF_PROXY_PORT = "proxyPort"
@@ -111,6 +116,9 @@ class AppSettingsRepository @Inject constructor() {
111116
private val _avatarProviderFlow = MutableStateFlow(avatarProviderType)
112117
val avatarProviderTypeFlow = _avatarProviderFlow.asStateFlow()
113118

119+
private val _dateTimeFormatFlow = MutableStateFlow(dateTimeFormat)
120+
val dateTimeFormatFlow = _dateTimeFormatFlow.asStateFlow()
121+
114122
private val _proxyFlow = MutableStateFlow(
115123
ProxySettings(
116124
useProxy,
@@ -319,6 +327,26 @@ class AppSettingsRepository @Inject constructor() {
319327
_avatarProviderFlow.value = newValue
320328
}
321329

330+
var dateTimeFormat: DateTimeFormat
331+
get() {
332+
val default = SettingsDefaults.defaultDateTimeFormat
333+
334+
val useSystemDefault = preferences.getBoolean(PREF_DATE_FORMAT_USE_DEFAULT, default.useSystemDefault)
335+
val customFormat = preferences.get(PREF_DATE_FORMAT_CUSTOM_FORMAT, default.customFormat)
336+
val is24h = preferences.getBoolean(PREF_DATE_FORMAT_IS_24H, default.is24hours)
337+
val useRelativeDate = preferences.getBoolean(PREF_DATE_FORMAT_USE_RELATIVE, default.useRelativeDate)
338+
339+
return DateTimeFormat(useSystemDefault, customFormat, is24h, useRelativeDate)
340+
}
341+
set(newValue) {
342+
preferences.putBoolean(PREF_DATE_FORMAT_USE_DEFAULT, newValue.useSystemDefault)
343+
preferences.put(PREF_DATE_FORMAT_CUSTOM_FORMAT, newValue.customFormat)
344+
preferences.putBoolean(PREF_DATE_FORMAT_IS_24H, newValue.is24hours)
345+
preferences.putBoolean(PREF_DATE_FORMAT_USE_RELATIVE, newValue.useRelativeDate)
346+
347+
_dateTimeFormatFlow.value = newValue
348+
}
349+
322350
var useProxy: Boolean
323351
get() {
324352
return preferences.getBoolean(PREF_USE_PROXY, false)

src/main/kotlin/com/jetpackduba/gitnuro/ui/CommitChanges.kt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -383,21 +383,23 @@ fun Author(
383383

384384
Spacer(modifier = Modifier.weight(1f, fill = true))
385385

386-
val smartDate = remember(author) {
387-
author.`when`.toSmartSystemString()
388-
}
386+
val smartDate = author.whenAsInstant.toSmartSystemString(
387+
allowRelative = true,
388+
showTime = true,
389+
)
389390

390-
val systemDate = remember(author) {
391-
author.`when`.toSystemDateTimeString()
392-
}
391+
val smartDateTooltip = author.whenAsInstant.toSmartSystemString(
392+
allowRelative = false,
393+
showTime = true,
394+
)
393395

394396
TooltipText(
395397
text = smartDate,
396398
color = MaterialTheme.colors.onBackgroundSecondary,
397399
maxLines = 1,
398400
modifier = Modifier.padding(horizontal = 16.dp),
399401
style = MaterialTheme.typography.body2,
400-
tooltipTitle = systemDate
402+
tooltipTitle = smartDateTooltip,
401403
)
402404
}
403405
}

0 commit comments

Comments
 (0)