Skip to content

Commit

Permalink
Fix datetime parse failures causing app crash (#1235)
Browse files Browse the repository at this point in the history
* Fix datetime parse failures

* Remove throws

* Remove remnants

* Fix formatting

* Add changes
  • Loading branch information
MV-GH authored Sep 15, 2023
1 parent a4beb5d commit 687adff
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 11 deletions.
63 changes: 52 additions & 11 deletions app/src/main/java/com/jerboa/ui/components/common/TimeAgo.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.jerboa.ui.components.common

import android.util.Log
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
Expand Down Expand Up @@ -29,6 +30,7 @@ import com.jerboa.formatDuration
import com.jerboa.ui.theme.SMALL_PADDING
import com.jerboa.ui.theme.muted
import java.time.Instant
import java.time.format.DateTimeParseException
import java.util.Date

@Composable
Expand All @@ -40,6 +42,11 @@ fun TimeAgo(
) {
val publishedPretty = dateStringToPretty(published, longTimeFormat)

if (publishedPretty == null) {
SmallErrorLabel(text = stringResource(R.string.time_ago_failed_to_parse))
return
}

val afterPreceding = precedingString?.let {
stringResource(R.string.time_ago_ago, it, publishedPretty)
} ?: run { publishedPretty }
Expand All @@ -52,25 +59,44 @@ fun TimeAgo(
)

updated?.also {
val updatedPretty = dateStringToPretty(it, longTimeFormat)

DotSpacer(
padding = SMALL_PADDING,
style = MaterialTheme.typography.bodyMedium,
)
Text(
text = "($updatedPretty)",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onBackground.muted,
fontStyle = FontStyle.Italic,
)
val updatedPretty = dateStringToPretty(it, longTimeFormat)

if (updatedPretty == null) {
SmallErrorLabel(text = stringResource(R.string.time_ago_failed_to_parse))
} else {
Text(
text = "($updatedPretty)",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onBackground.muted,
fontStyle = FontStyle.Italic,
)
}
}
}
}

fun dateStringToPretty(dateStr: String, longTimeFormat: Boolean = false): String {
val publishedDate = Date.from(Instant.parse(dateStr + "Z"))
return formatDuration(publishedDate, longTimeFormat)
/**
* Converts a date string to a pretty string like "2 hours" or "2h"
*
* @param dateStr The date string to convert
* @param longTimeFormat If true, use a long time format like "2 hours, 3 minutes ago"
* @return The pretty string, or null if the date string could not be parsed
*/
fun dateStringToPretty(dateStr: String, longTimeFormat: Boolean = false): String? {
return try {
// TODO: v0.18.4_deprecated Remove this hack once backward API compatibility is implemented
// pre 0.19 Datetimes didn't have a timezone, so we add one here
val withTimezone = if (dateStr.last() == 'Z') dateStr else dateStr + "Z"
val publishedDate = Date.from(Instant.parse(withTimezone))
formatDuration(publishedDate, longTimeFormat)
} catch (e: DateTimeParseException) {
Log.d("TimeAgo", "Failed to parse date string: $dateStr", e)
null
}
}

@Preview
Expand Down Expand Up @@ -180,3 +206,18 @@ fun NsfwBadge(visible: Boolean) {
fun NsfwBadgePreview() {
NsfwBadge(visible = true)
}

@Composable
fun SmallErrorLabel(text: String) {
Text(
text = text,
color = MaterialTheme.colorScheme.error,
style = MaterialTheme.typography.labelSmall,
)
}

@Preview
@Composable
fun SmallErrorLabelPreview() {
SmallErrorLabel(stringResource(id = R.string.time_ago_failed_to_parse))
}
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -418,4 +418,5 @@
<string name="matrix_send_msg">Connect on Matrix</string>
<string name="posts_failed_loading">Posts failed loading, retry</string>
<string name="failed_sharing_media">Failed to share media!</string>
<string name="time_ago_failed_to_parse">Failed to parse datetime</string>
</resources>

0 comments on commit 687adff

Please sign in to comment.