diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index 3b45fd55a..442ec4da3 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -741,10 +741,10 @@ object LocalCache { // Already processed this event. if (version.event?.id() == event.id()) return - if (version.event == null) { - // makes sure the OTS has a valid certificate - if (event.cacheVerify() == null) return // no valid OTS + // makes sure the OTS has a valid certificate + if (event.cacheVerify() == null) return // no valid OTS + if (version.event == null) { version.loadEvent(event, author, emptyList()) version.liveSet?.innerOts?.invalidateData() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt index 35929b150..7725b9ead 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt @@ -241,6 +241,8 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.io.File import java.net.URL +import java.text.SimpleDateFormat +import java.util.Date import java.util.Locale @OptIn(ExperimentalFoundationApi::class) @@ -2560,15 +2562,27 @@ fun DisplayOts( LoadOts( note, accountViewModel, - whenConfirmed = { + whenConfirmed = { unixtimestamp -> val context = LocalContext.current - val timeStr by remember(note) { mutableStateOf(timeAgo(it, context = context)) } + val timeStr by remember(unixtimestamp) { mutableStateOf(timeAgoNoDot(unixtimestamp, context = context)) } - Text( - stringResource(id = R.string.existed_since, timeStr), - color = MaterialTheme.colorScheme.lessImportantLink, - fontSize = Font14SP, - fontWeight = FontWeight.Bold, + ClickableText( + text = buildAnnotatedString { append(stringResource(id = R.string.existed_since, timeStr)) }, + onClick = { + val fullDateTime = + SimpleDateFormat.getDateTimeInstance().format(Date(unixtimestamp * 1000)) + + accountViewModel.toast( + context.getString(R.string.ots_info_title), + context.getString(R.string.ots_info_description, fullDateTime), + ) + }, + style = + LocalTextStyle.current.copy( + color = MaterialTheme.colorScheme.lessImportantLink, + fontSize = Font14SP, + fontWeight = FontWeight.Bold, + ), maxLines = 1, ) }, @@ -2688,11 +2702,12 @@ fun LoadOts( LaunchedEffect(key1 = noteStatus) { accountViewModel.findOtsEventsForNote(noteStatus?.note ?: note) { newOts -> - if (newOts == null) { - earliestDate = GenericLoadable.Empty() - } else { - earliestDate = GenericLoadable.Loaded(newOts) - } + earliestDate = + if (newOts == null) { + GenericLoadable.Empty() + } else { + GenericLoadable.Loaded(newOts) + } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/TimeAgoFormatter.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/TimeAgoFormatter.kt index aa381ac24..d2040b21a 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/TimeAgoFormatter.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/TimeAgoFormatter.kt @@ -71,6 +71,46 @@ fun timeAgo( } } +fun timeAgoNoDot( + time: Long?, + context: Context, +): String { + if (time == null) return " " + if (time == 0L) return " ${context.getString(R.string.never)}" + + val timeDifference = TimeUtils.now() - time + + return if (timeDifference > TimeUtils.ONE_YEAR) { + // Dec 12, 2022 + + if (locale != Locale.getDefault()) { + locale = Locale.getDefault() + yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale) + monthFormatter = SimpleDateFormat("MMM dd", locale) + } + + yearFormatter.format(time * 1000) + } else if (timeDifference > TimeUtils.ONE_MONTH) { + // Dec 12 + if (locale != Locale.getDefault()) { + locale = Locale.getDefault() + yearFormatter = SimpleDateFormat("MMM dd, yyyy", locale) + monthFormatter = SimpleDateFormat("MMM dd", locale) + } + + monthFormatter.format(time * 1000) + } else if (timeDifference > TimeUtils.ONE_DAY) { + // 2 days + (timeDifference / TimeUtils.ONE_DAY).toString() + context.getString(R.string.d) + } else if (timeDifference > TimeUtils.ONE_HOUR) { + (timeDifference / TimeUtils.ONE_HOUR).toString() + context.getString(R.string.h) + } else if (timeDifference > TimeUtils.ONE_MINUTE) { + (timeDifference / TimeUtils.ONE_MINUTE).toString() + context.getString(R.string.m) + } else { + context.getString(R.string.now) + } +} + fun timeAgoShort( mills: Long?, stringForNow: String, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThreadFeedView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThreadFeedView.kt index 511a8caa4..2d3153de5 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThreadFeedView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/ThreadFeedView.kt @@ -104,6 +104,7 @@ import com.vitorpamplona.amethyst.ui.note.BlankNote import com.vitorpamplona.amethyst.ui.note.CreateImageHeader import com.vitorpamplona.amethyst.ui.note.DisplayHighlight import com.vitorpamplona.amethyst.ui.note.DisplayLocation +import com.vitorpamplona.amethyst.ui.note.DisplayOts import com.vitorpamplona.amethyst.ui.note.DisplayPeopleList import com.vitorpamplona.amethyst.ui.note.DisplayRelaySet import com.vitorpamplona.amethyst.ui.note.FileHeaderDisplay @@ -449,6 +450,8 @@ fun NoteMaster( if (pow > 20) { DisplayPoW(pow) } + + DisplayOts(note, accountViewModel) } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5451e48e9..d36dbb21a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -787,4 +787,7 @@ Web: Clone: OTS: %1$s + + Timestamp Proof + There\'s proof this post was signed sometime before %1$s. The proof was stamped in the Bitcoin blockchain at that date and time.