Android recent tags: reuse ui/Time.kt's epochMillis (#5931)
CI & Build / Python lint (push) Successful in 2s
CI & Build / Build now, or wait for Android? (push) Successful in 3s
Android / Build, or is the channel already serving this? (push) Successful in 3s
Desktop (Tauri) / Build, or is the channel already serving this? (push) Successful in 2s
Desktop (Tauri) / Web tests, clippy, Rust tests and rustfmt (push) Skipped
Desktop (Tauri) / Tauri desktop (Linux) (push) Skipped
Desktop (Tauri) / Windows installer (cross-compiled) (push) Skipped
Desktop (Tauri) / Update manifest (push) Skipped
CI & Build / Web typecheck and unit tests (push) Successful in 9s
CI & Build / Python tests (push) Successful in 14s
Android / Core and FFI clippy and tests (push) Successful in 25s
CI & Build / integration (push) Successful in 1m30s
CI & Build / Build & push image (push) Skipped
Android / Kotlin + Rust (APK) (push) Successful in 6m40s
Android / Build the server image (push) Successful in 1s

RecentTags.kt declared a second epochMillis(String?): Long beside Time.kt's
epochMillis(String): Long?. A string literal resolved to the existing one, so
the test asserted 0 against its null.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-16 15:16:29 -04:00
co-authored by Claude Opus 5.5
parent 7cb05b77c6
commit 142fafe0ed
2 changed files with 8 additions and 9 deletions
@@ -10,7 +10,6 @@ import androidx.compose.ui.platform.LocalContext
import com.fabledsword.inkwell.TagViews import com.fabledsword.inkwell.TagViews
import com.fabledsword.inkwell.core.Label import com.fabledsword.inkwell.core.Label
import com.fabledsword.inkwell.core.Note import com.fabledsword.inkwell.core.Note
import java.time.OffsetDateTime
/** /**
* The drawer lists the few tags in use rather than every tag (#5931), so a long * The drawer lists the few tags in use rather than every tag (#5931), so a long
@@ -47,17 +46,16 @@ fun tagRecency(
notes: List<Note>, notes: List<Note>,
views: Map<String, Long>, views: Map<String, Long>,
): Map<String, Long> { ): Map<String, Long> {
val latest = labels.associate { it.id to maxOf(epochMillis(it.lastUsed), views[it.id] ?: 0L) }.toMutableMap() // A missing or unreadable stamp counts as 0: such a tag simply ranks last.
val latest = labels.associate { it.id to maxOf(it.lastUsed.millis(), views[it.id] ?: 0L) }.toMutableMap()
for (note in notes) { for (note in notes) {
val at = epochMillis(note.updatedAt) val at = note.updatedAt.millis()
for (label in note.labels) latest.computeIfPresent(label.id) { _, was -> maxOf(was, at) } for (label in note.labels) latest.computeIfPresent(label.id) { _, was -> maxOf(was, at) }
} }
return latest return latest
} }
/** 0 for a missing or unreadable stamp: such a tag simply ranks last. */ private fun String?.millis(): Long = this?.let(::epochMillis) ?: 0L
fun epochMillis(stamp: String?): Long =
stamp?.let { runCatching { OffsetDateTime.parse(it).toInstant().toEpochMilli() }.getOrNull() } ?: 0L
/** /**
* When each tag's lens was last opened here. Opening one counts as using it, * When each tag's lens was last opened here. Opening one counts as using it,
@@ -1,6 +1,7 @@
package com.fabledsword.inkwell.ui package com.fabledsword.inkwell.ui
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Assert.assertSame import org.junit.Assert.assertSame
import org.junit.Test import org.junit.Test
@@ -32,10 +33,10 @@ class RecentTagsTest {
} }
@Test @Test
fun `reads both stamp forms the store holds`() { fun `the shared epochMillis reads both stamp forms tag recency is built from`() {
// The core writes `Z` with milliseconds; a pulled server row may carry +00:00.
assertEquals(1_760_000_000_000L, epochMillis("2025-10-09T08:53:20.000Z")) assertEquals(1_760_000_000_000L, epochMillis("2025-10-09T08:53:20.000Z"))
assertEquals(1_760_000_000_000L, epochMillis("2025-10-09T08:53:20+00:00")) assertEquals(1_760_000_000_000L, epochMillis("2025-10-09T08:53:20+00:00"))
assertEquals(0L, epochMillis(null)) assertNull(epochMillis("not a time"))
assertEquals(0L, epochMillis("not a time"))
} }
} }