From bd46ff3e03c9a9f100fefcc2554be7c245a08c68 Mon Sep 17 00:00:00 2001 From: Damontecres Date: Thu, 5 Nov 2026 17:13:09 -0500 Subject: [PATCH 01/18] Fix adding Seerr server if plugin is not installed (#2179) ## Description If the server plugin is not installed, trying to add Seerr server will show an endless loading page. This PR fixes that. ### Related issues Fixes #2177 ### Testing Emulator against server with & without the plugin ## Screenshots N/A ## AI or LLM usage None --- .../wholphin/ui/setup/seerr/SwitchSeerrViewModel.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/seerr/SwitchSeerrViewModel.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/seerr/SwitchSeerrViewModel.kt index 2fde3eae..e7ec173a 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/seerr/SwitchSeerrViewModel.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/seerr/SwitchSeerrViewModel.kt @@ -52,6 +52,9 @@ class SwitchSeerrViewModel _state.update { it.copy(loading = LoadingState.Success) } } } + } else { + // Nothing to check so set success + _state.update { it.copy(loading = LoadingState.Success) } } } From 159edc875d10a667c25598a2cbfac8c123fe5bff Mon Sep 17 00:00:00 2001 From: Damontecres Date: Fri, 6 Nov 2026 15:37:29 -0500 Subject: [PATCH 02/18] Release v1.1.1 From 00e8e83bb64d7a3ea57310846ed106c9fd621f53 Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 02:31:05 +0100 Subject: [PATCH 03/18] Document upstream v1.1.1 setup fix --- docker/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docker/README.md b/docker/README.md index 2c1c4c56..3b5aa6cb 100644 --- a/docker/README.md +++ b/docker/README.md @@ -185,6 +185,15 @@ not the working tree. An uncommitted merge still builds with the old version nam Neither an upstream merge nor its validation build authorizes a release or TV installation. +## Upstream v1.1.1 integration + +The patch release makes manual Seerr setup available when the optional companion +plugin is absent: setup is marked ready immediately rather than remaining pending. +With the plugin installed, an empty settings response or a failed settings read +still reaches the existing ready-state fallback; plugin URL prefill is unchanged. +There are no new Room migrations (schema remains 41), player, layout, session, +DNS/client, dependency, branding or signing changes relative to v1.1.0. + ## Wolfskin shell Wolfskin UI lives in `app/src/wolfskin/java`, beside upstream source. The signed-in From 6d7513bd0e0c55a2308141c24006471a8ca1096b Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 15:05:07 +0100 Subject: [PATCH 04/18] Refine title episode cards, section stacking and action menus --- .../wolfskin/tv/ConductarrTitlePagesTest.kt | 2 +- .../wolfskin/tv/ConductarrTitleSurfaceTest.kt | 6 +- .../wolfskin/tv/TitleCaptureTest.kt | 11 +- .../justinvisser/wolfskin/tv/TitleKeysTest.kt | 33 --- .../wolfskin/tv/TitleRound2Test.kt | 197 ++++++++++++++++++ docker/README.md | 35 +++- .../wolfskin/design/TitleArtwork.kt | 4 +- .../wolfskin/design/TitleHeader.kt | 3 +- .../justinvisser/wolfskin/design/TitleMenu.kt | 69 ++++++ .../wolfskin/design/TitleModel.kt | 2 +- .../wolfskin/design/TitleOptionsSheet.kt | 2 +- .../justinvisser/wolfskin/design/TitlePage.kt | 10 +- .../wolfskin/design/TitlePrefetch.kt | 2 +- .../wolfskin/design/TitleShelf.kt | 27 ++- .../wolfskin/design/TitleState.kt | 43 +++- .../wolfskin/design/WolfskinTokens.kt | 4 +- wolfskin-design/title-tokens.json | 4 +- wolfskin-design/tokens.css | 4 +- wolfskin-design/tokens.sha256 | 6 +- 19 files changed, 379 insertions(+), 85 deletions(-) create mode 100644 app/src/test/java/org/justinvisser/wolfskin/tv/TitleRound2Test.kt create mode 100644 wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleMenu.kt diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/ConductarrTitlePagesTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/ConductarrTitlePagesTest.kt index 3c77fa66..d3ea3804 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/ConductarrTitlePagesTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/ConductarrTitlePagesTest.kt @@ -70,7 +70,7 @@ class ConductarrTitlePagesTest { assertEquals(TitleConnection.SignedOut, revoked.connection) assertTrue(revoked.item.ratings.isEmpty()) assertTrue(revoked.playTarget!!.ratings.isEmpty()) - assertFalse(TitleState(revoked, ShellPerson("shared", "Shared", "S", true)) {}.options.any { it.id == "add" }) + assertFalse(TitleState(revoked, ShellPerson("shared", "Shared", "S", true)) {}.menuOptions.any { it.id == "add" }) } } } diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/ConductarrTitleSurfaceTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/ConductarrTitleSurfaceTest.kt index e41862d8..27d2d214 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/ConductarrTitleSurfaceTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/ConductarrTitleSurfaceTest.kt @@ -76,6 +76,9 @@ class ConductarrTitleSurfaceTest { val directory = File(requireNotNull(System.getProperty("wolfskin.captureDirectory"))).apply { mkdirs() } rule.onRoot().captureRoboImage(File(directory, "conductarr-title-real.png").absolutePath) rule.onRoot().performKeyInput { pressKey(Key.DirectionRight); pressKey(Key.DirectionCenter) } + rule.mainClock.advanceTimeBy(300) + rule.onNodeWithText("Add for someone").assertIsDisplayed() + rule.onRoot().performKeyInput { pressKey(Key.DirectionCenter) } rule.onNodeWithText("Request for Mindel").assertIsDisplayed() rule.onRoot().performKeyInput { pressKey(Key.DirectionDown); pressKey(Key.DirectionCenter) } rule.waitUntil(30_000) { @@ -97,7 +100,8 @@ class ConductarrTitleSurfaceTest { viewModel.title?.data?.connection == TitleConnection.SignedOut && viewModel.title?.data?.status == TitleReadStatus.Unavailable } assertTrue(viewModel.title!!.data.item.ratings.isEmpty()) - assertFalse(viewModel.title!!.options.any { it.id in listOf("request", "other", "add") }) + assertFalse(viewModel.title!!.options.any { it.id == "request" }) + assertFalse(viewModel.title!!.menuOptions.any { it.id == "add" }) } finally { viewModel.viewModelScope.cancel() } } } diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/TitleCaptureTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleCaptureTest.kt index 55f9d747..270271b1 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/TitleCaptureTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleCaptureTest.kt @@ -87,7 +87,7 @@ class TitleCaptureTest { data.cast.forEach { person -> person.portrait?.let { add(Triple(it, 200, 200)) } } data.related.forEach { item -> item.poster?.let { add(Triple(it, 256, 384)) } } data.episodes.forEach { item -> - (if (item.isPosterBackdrop) item.poster else item.backdrop)?.let { add(Triple(it, (WolfskinTokens.Card.tileW.value * 2).toInt(), (WolfskinTokens.Card.tileH.value * 2).toInt())) } + (if (item.isPosterBackdrop) item.poster else item.backdrop)?.let { add(Triple(it, (WolfskinTokens.Title.episodeCardWidth.value * 2).toInt(), (WolfskinTokens.Title.episodeCardHeight.value * 2).toInt())) } } } return requests.distinctBy { it.first }.associate { (path, width, height) -> @@ -170,7 +170,10 @@ class TitleCaptureTest { @Test fun st044_versions() = capture(44) { state, shell -> open(state, shell, "version") } @Test fun st045_rememberedVersion() = capture(45) { state, _ -> state.versionId = "v2"; option(state, "version") } @Test fun st046_tracks() = capture(46) { state, shell -> open(state, shell, "tracks") } - @Test fun st047_mediaInfo() = capture(47) { state, shell -> open(state, shell, "more") } + @Test fun st047_mediaInfo() = capture(47) { state, shell -> + open(state, shell, "menu") + state.clickSheet(0) + } @Test fun st048_trailerNoApp() = capture(48) { state, _ -> option(state, "trailer"); state.toast = "No YouTube app is available to play this trailer." } @Test fun st049_watched() = capture(49, transform = { it.copy(watchTarget = it.watchTarget.copy(watched = true)) }) { state, _ -> option(state, "watched") } @Test fun st050_seriesConfirm() = capture(50, "Andor") { state, shell -> open(state, shell, "watched") } @@ -216,4 +219,8 @@ class TitleCaptureTest { @Test fun st108_resumingEpisodeRatings() = capture(108, "episode-sex-and-the-country-2001-s4e9", "mindel") @Test fun st109_noRatings() = capture(109, "The Amazing Spider-Man") @Test fun spacingCastFirstFocused() = capture(114) { state, _ -> state.focus("cast", 0) } + @Test fun round2Menu() = capture(120) { state, shell -> open(state, shell, "menu") } + @Test fun round2MussoliniResume() = capture(121, "episode-episode-1-2025-s1e1", "shared", transform = { it.copy(episodes = it.episodes.distinctBy { episode -> episode.id }) }) + @Test fun round2Episodes() = capture(122, "episode-episode-1-2025-s1e1", "shared", transform = { it.copy(episodes = it.episodes.distinctBy { episode -> episode.id }) }) { state, _ -> state.focus("episodes", 0) } + @Test fun round2NotHeldSeries() = capture(123, "90 Day Fiancé: Before the 90 Days") } diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/TitleKeysTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleKeysTest.kt index 0b6dac33..4e664da3 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/TitleKeysTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleKeysTest.kt @@ -14,9 +14,6 @@ import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.hasClickAction import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.performSemanticsAction -import androidx.compose.ui.semantics.SemanticsActions -import androidx.compose.ui.text.TextLayoutResult import org.justinvisser.wolfskin.design.WolfskinTokens import org.json.JSONArray import org.json.JSONObject @@ -36,7 +33,6 @@ import org.justinvisser.wolfskin.design.TitleSurface import org.justinvisser.wolfskin.design.WolfskinTheme import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config -import org.robolectric.annotation.GraphicsMode /** Approved title-entry suffixes replay Android keys through the rendered title and shared shell. */ @RunWith(RobolectricTestRunner::class) @@ -284,15 +280,6 @@ class TitleKeysTest { press(Key.DirectionDown) assertEquals(expected, state.row) } - @Test fun seriesOptionsKeepTheCompleteHouseholdActionLabel() { - render("Andor") - val layouts = mutableListOf() - rule.onNodeWithText("Add for someone", useUnmergedTree = true) - .performSemanticsAction(SemanticsActions.GetTextLayoutResult) { action -> action(layouts) } - val layout = layouts.single() - assertFalse("The final pill must not shrink to its icon or a clipped label", layout.didOverflowWidth) - assertEquals(1, layout.lineCount) - } @Test fun anInitialLoadNeverExposesStaleCastBelowItsSkeleton() { render(transform = { it.copy(status = TitleReadStatus.Loading) }) @@ -315,26 +302,6 @@ class TitleKeysTest { assertEquals(WolfskinTokens.Title.factsGap.value * 2, genre.left - year.right, 1f) } - @GraphicsMode(GraphicsMode.Mode.NATIVE) - @Test fun mediaInfoRowsPreserveTheirDeclaredLineBoxes() { - render() - rule.runOnIdle { state.focus("header", state.options.indexOfFirst { it.id == "more" }) } - press(Key.DirectionCenter) - val container = rule.onNodeWithText("Container", useUnmergedTree = true).fetchSemanticsNode().boundsInRoot - val size = rule.onNodeWithText("Size", useUnmergedTree = true).fetchSemanticsNode().boundsInRoot - val expectedPitch = (WolfskinTokens.Title.infoKey.lineHeight.value + WolfskinTokens.Title.infoRowGap.value) * 2 - assertEquals("Stacked facts retain the CSS line-box rhythm", expectedPitch, size.top - container.top, 1f) - val lastSubtitle = rule.onNodeWithText("Dutch", useUnmergedTree = true).fetchSemanticsNode().boundsInRoot - assertEquals("Fourteen stacked lines do not accumulate native pixel rounding", 526.2f, lastSubtitle.top - container.top, 1f) - } - - @GraphicsMode(GraphicsMode.Mode.NATIVE) - @Test fun filmHeaderKeepsItsFixedCssStack() { - render() - assertEquals(358f, rule.onNodeWithTag("title-facts").fetchSemanticsNode().boundsInRoot.top, 1f) - assertEquals(410f, rule.onNodeWithTag("title-overview").fetchSemanticsNode().boundsInRoot.top, 1f) - assertEquals(553f, rule.onNodeWithTag("title-actions").fetchSemanticsNode().boundsInRoot.top, 1f) - } @Test fun everyLongTrackChoiceAndDoneRemainInsideTheVisibleSheet() { diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/TitleRound2Test.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleRound2Test.kt new file mode 100644 index 00000000..d0c503e4 --- /dev/null +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleRound2Test.kt @@ -0,0 +1,197 @@ +package org.justinvisser.wolfskin.tv + +import android.app.Application +import android.graphics.BitmapFactory +import androidx.activity.ComponentActivity +import androidx.activity.compose.BackHandler +import androidx.compose.foundation.layout.requiredSize +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.key.Key +import androidx.compose.ui.test.* +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.unit.dp +import com.github.takahirom.roborazzi.captureRoboImage +import org.json.JSONObject +import org.junit.Assert.* +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.justinvisser.wolfskin.design.* +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode +import java.io.File + +/** Native title interactions keep secondary actions, focus and section geometry intact. */ +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [34], application = Application::class, qualifiers = "w960dp-h540dp-xhdpi") +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class TitleRound2Test { + @get:Rule val rule = createAndroidComposeRule() + private val effects = mutableListOf() + private lateinit var state: TitleState + private lateinit var shell: ShellState + + private fun fixture() = TitleFixture(rule.activity.assets.open("wolfskin-titles.json").bufferedReader().use { JSONObject(it.readText()) }) + private fun render(title: String = "Locke", person: String = "justin", transform: (TitlePageData) -> TitlePageData = { it }) { + val fixture = fixture() + shell = ShellState(fixture.people, person).apply { pickerVisible = false; pickerLaunch = false; enterDestination("title/test") } + state = TitleState(transform(fixture.title(title, person)), shell.person, effects::add) + rule.setContent { WolfskinTheme { + BackHandler { state.back(shell) } + TitleSurface(state, shell, Modifier.requiredSize(960.dp, 540.dp)) + } } + } + private fun press(key: Key) = rule.onRoot().performKeyInput { pressKey(key) } + private fun menu() { + rule.runOnIdle { state.focus("header", state.options.indexOfFirst { it.id == "menu" }) } + press(Key.DirectionCenter) + rule.mainClock.advanceTimeBy(300) + rule.waitForIdle() + rule.onNodeWithTag("title-menu", useUnmergedTree = true).assertIsDisplayed() + } + + @Test fun menuBackRestoresItsButtonAndKeepsMediaInfoAndRequestReachable() { + render() + menu() + val opener = state.column + press(Key.Back) + assertNull(state.sheet) + assertEquals(opener, state.column) + assertFalse(shell.navFocused) + press(Key.DirectionCenter) + assertEquals(TitleSheet.Menu, state.sheet) + press(Key.DirectionCenter) + assertEquals(TitleSheet.MediaInfo, state.sheet) + rule.onNodeWithText("Container", useUnmergedTree = true).assertIsDisplayed() + press(Key.Back) + assertEquals(TitleSheet.Menu, state.sheet) + press(Key.DirectionDown) + press(Key.DirectionCenter) + assertNull(state.sheet) + assertEquals(TitleAction.Request(state.data.item, true), effects.single()) + assertEquals(opener, state.column) + } + + @Test fun notHeldMovieKeepsRequestAndHideOutsideTheMenu() { + render("The Amazing Spider-Man") + rule.onNodeWithTag("title-option-request").assertIsDisplayed() + rule.onNodeWithTag("title-option-hide").assertIsDisplayed() + menu() + rule.onNodeWithText("Add for someone").assertIsDisplayed() + press(Key.DirectionCenter) + assertEquals(TitleAction.Request(state.data.item, true), effects.single()) + } + + @Test fun movieCastStacksAfterActionsInsteadOfAReservedHeaderHeight() { + render("The Amazing Spider-Man") + val actions = rule.onNodeWithTag("title-actions").fetchSemanticsNode().boundsInRoot + val cast = rule.onNodeWithTag("title-cast").fetchSemanticsNode().boundsInRoot + val gap = cast.top - actions.bottom + assertTrue("Cast must follow the action caption and normal section gap: $gap", gap in 40f..110f) + rule.runOnIdle { state.update(state.data.copy(requestedStage = "Searching", requestActor = "Justin")) } + val requestedActions = rule.onNodeWithTag("title-actions").fetchSemanticsNode().boundsInRoot + val requestedCast = rule.onNodeWithTag("title-cast").fetchSemanticsNode().boundsInRoot + assertEquals("An actual readiness line belongs in the stack, not a fixed empty header", gap, requestedCast.top - requestedActions.bottom, 1f) + } + + @Test fun mussoliniResumeHasOnlyFactsRatingsAndNoRedundantSeasonsAction() { + render("episode-episode-1-2025-s1e1", "shared") { data -> data.copy(episodes = data.episodes.distinctBy { it.id }) } + assertTrue(state.data.playTarget!!.resumeSeconds > 0) + rule.onNodeWithTag("title-progress").assertIsDisplayed() + rule.onAllNodesWithContentDescription("rtCritics", useUnmergedTree = true).assertCountEquals(1) + rule.onNodeWithText("Ep", useUnmergedTree = true).assertDoesNotExist() + rule.onNodeWithTag("title-option-seasons").assertDoesNotExist() + press(Key.DirectionDown) + assertEquals("seasons", state.row) + rule.onNode(hasText("Season 1") and hasClickAction()).assertIsDisplayed() + } + + @Test fun seriesKeepsItsSeasonsShortcutAndSecondaryRequestUsesTheMenu() { + render("Andor") + rule.onNodeWithTag("title-option-seasons").assertIsDisplayed() + menu() + rule.onNodeWithText("Add for someone").assertIsDisplayed() + press(Key.Back) + press(Key.DirectionRight) + press(Key.DirectionCenter) + assertEquals("seasons", state.row) + } + + @Test fun episodeSkeletonAndReadySlotsMatchWhileMetadataFitsOneLine() { + render("Andor") { it.copy(episodesStatus = TitleReadStatus.Loading) } + rule.runOnIdle { shell.view.listState.requestScrollToItem(2) } + rule.waitForIdle() + val skeleton = rule.onNodeWithTag("title-episode-slot-0").fetchSemanticsNode().boundsInRoot + rule.runOnIdle { state.update(state.data.copy(episodesStatus = TitleReadStatus.Ready)) } + val ready = rule.onNodeWithTag("title-episode-slot-0").fetchSemanticsNode().boundsInRoot + assertEquals(skeleton, ready) + assertEquals(16f / 9f, ready.width / ready.height, 0.01f) + rule.runOnIdle { state.focus("episodes", 0) } + val episode = state.data.episodes.first() + rule.onNodeWithText(episode.episodeLabel + " · " + episode.runtime).assertIsDisplayed() + rule.onNode(hasText(episode.seriesName!!) and hasAnyAncestor(hasTestTag("title-episode-slot-0")), useUnmergedTree = true).assertDoesNotExist() + } + + @Test fun revokedRequestsDisappearFromMenuWithoutRemovingMediaInfo() { + render() + menu() + rule.runOnIdle { state.update(state.data.copy(requestsAllowed = false)) } + rule.onNodeWithText("Add for someone").assertDoesNotExist() + press(Key.DirectionCenter) + assertEquals(TitleSheet.MediaInfo, state.sheet) + rule.onNodeWithText("Container", useUnmergedTree = true).assertIsDisplayed() + } + + @Test fun menuFadeFramesStayMonotonicAndNeverTranslate() { + render { it.copy(item = it.item.copy(backdrop = null, poster = null), cast = emptyList(), related = emptyList()) } + rule.mainClock.autoAdvance = false + val directory = File(requireNotNull(System.getProperty("wolfskin.captureDirectory")), "title-menu-motion").apply { mkdirs() } + rule.runOnIdle { state.click("header", state.options.indexOfFirst { it.id == "menu" }) } + var waited = 0 + while (rule.onAllNodesWithTag("title-menu", useUnmergedTree = true).fetchSemanticsNodes().isEmpty() && waited <= WolfskinTokens.Motion.base + 100) { + rule.mainClock.advanceTimeByFrame() + rule.waitForIdle() + waited += 16 + } + val bounds = rule.onNodeWithTag("title-menu", useUnmergedTree = true).fetchSemanticsNode().boundsInRoot + val samples = mutableListOf() + fun frame(phase: String, index: Int): Int { + val file = File(directory, "$phase-${index.toString().padStart(2, '0')}.png") + rule.onRoot().captureRoboImage(file.absolutePath) + val image = BitmapFactory.decodeFile(file.absolutePath) + val brightness = try { + val pixel = image.getPixel((bounds.left + 40).toInt(), (bounds.top + 6).toInt()) + android.graphics.Color.red(pixel) + android.graphics.Color.green(pixel) + android.graphics.Color.blue(pixel) + } finally { image.recycle() } + samples.add("$phase,${index * 16},$brightness,${bounds.left},${bounds.top}") + return brightness + } + fun assertMonotonic(values: List) { + assertNotEquals("Fade must visibly change the menu pixel", values.first(), values.last()) + val direction = if (values.last() > values.first()) 1 else -1 + values.zipWithNext().forEach { (before, after) -> + assertTrue("Menu alpha must not flicker or snap back: $values", (after - before) * direction >= -1) + } + } + val entering = List(14) { index -> + rule.waitForIdle() + assertEquals(bounds, rule.onNodeWithTag("title-menu", useUnmergedTree = true).fetchSemanticsNode().boundsInRoot) + frame("open", index).also { rule.mainClock.advanceTimeBy(16); rule.waitForIdle() } + } + assertMonotonic(entering) + rule.runOnIdle { state.back(shell) } + val leaving = mutableListOf() + repeat(9) { index -> + rule.waitForIdle() + if (rule.onAllNodesWithTag("title-menu", useUnmergedTree = true).fetchSemanticsNodes().isNotEmpty()) leaving.add(frame("close", index)) + rule.mainClock.advanceTimeBy(16) + } + assertMonotonic(leaving) + rule.onNodeWithTag("title-menu").assertDoesNotExist() + File(directory, "samples.csv").writeText("phase,timeMs,brightness,leftPx,topPx\n" + samples.joinToString("\n")) + rule.mainClock.autoAdvance = true + press(Key.DirectionCenter) + assertEquals(TitleSheet.Menu, state.sheet) + } +} diff --git a/docker/README.md b/docker/README.md index 5cd6f6fa..c342ac2f 100644 --- a/docker/README.md +++ b/docker/README.md @@ -627,18 +627,18 @@ retain the approved frames except for the requested feedback changes: that may still be cancelled; first mount restores the intended shelf item. Discover uses all six approved poster slots. Person keeps the final column at full poster width. -- Episode images choose episode Primary, then Thumb, then the already-read - series Backdrop. Episode cards are 400×280 px; cast retains its 68 px clearance. - Episode context uses the episode overview, with two summary lines on the - focused card. Held-series headers measure their copy/actions and leave 40 px - before seasons instead of reserving a fixed empty 900 px header. +- Episode images choose episode Primary, then Thumb, then the already-read series Backdrop. + Title episode cards now use 448×252 px (16:9), with a one-line focused summary, + no show-name overlay, and `S1 E3 · duration` plus the watched check on one line. + Ready title headers measure their copy/actions and leave 40 px before the + following section; series retain the empty 56 px readiness reservation. - Every Discover heading uses a 104 px band, including a 60 px title-to-card gap. Home heading geometry is unchanged. - Hero/backdrop decoding is bounded to 1920×1080; upright hero sheets request 420×630. The shared request builder replaces conflicting Jellyfin size/encoding parameters: cards use WebP quality 80, while hero backdrops/sheets retain JPEG quality 96. Poster/tile/wide/episode requests are 256×384, 400×225, 544×306 and - 400×280; Jellyfin fill preserves aspect ratio before the UI crops. Tags and + 448×252; Jellyfin fill preserves aspect ratio before the UI crops. Tags and authentication query parameters remain intact. TMDB uses w342 for posters and portraits, w780 for landscape cards and w1280 for hero backdrops, never original. Lossy WebP decoding is guaranteed below minSdk 23; API 28+ additionally checks @@ -690,6 +690,24 @@ pop a pushed title/person from content **or** nav. Initial loading has no conten target: Down stays in nav, while Back can still leave the title. A missing rating set emits no layout node, so it cannot reserve an invisible extra facts gap. +The title Menu replaces the old More/media-info icon action and contains Media +info plus Add for someone when requests are permitted. It is shared by held +movie, series and episode pages; non-held pages expose Add for someone in the +same menu while Request/status and Not interested/Show again stay in the row. +Version, tracks, watched and trailer controls keep their existing positions. +Back from Media info returns to the menu; Back from the menu restores its +opening button. The compact menu fades in for 160 ms and out for 100 ms using +the motion ease-out token, with reduced-motion fades capped at 80 ms. Only the +bounded menu panel owns an alpha layer; the scrim is static. Controls +use the shared 4 px straddle focus ring. Episode details omit the redundant +Seasons shortcut; series pages retain it. Ratings appear only in the header +facts line, not again beside progress, on movie, series and episode pages. + +Episode shelf skeletons use the same width, height and pitch as ready cards. +Person filmography and related-title shelves remain posters; Home continuation +tiles are a separate component and retain their series-name context. + + `TitleReadFacade` confines SDK reads, server/user-scoped last-good disk copies, person credits and playback mutations to one boundary. `ConductarrTitlePages` adds real detail, cast, related titles, performer/filmography, readiness/receipts @@ -714,7 +732,10 @@ headers, sheets, cast and poster captions without changing shared type tokens. Fractional stack placement rounds only the accumulated position, preventing a one-pixel-per-row drift. Focused controls share the canonical lift shadow. `TitleKeysTest` replays real Android keys, including modal Back/hold, nearest-row -entry, remembered columns, long-sheet visibility and full media-table geometry. +entry, remembered columns and long-sheet visibility. `TitleRound2Test` covers +menu Back/focus, preserved media info and household requests, movie stacking, +the Mussolini resume example, request revocation, episode skeleton geometry, +and native menu fade frames sampled in 16 ms steps. `TitleAsyncFocusTest` delays title and person replies through the real destination and view-model, then exercises content focus and hardware Back. Subtitles Off maps to the player's explicit disabled sentinel, not its unspecified default. diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleArtwork.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleArtwork.kt index 3a3efd9b..8adac820 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleArtwork.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleArtwork.kt @@ -136,13 +136,13 @@ fun TitleTileArtwork(item: TitleItem) { val filter = remember { ColorFilter.colorMatrix(ColorMatrix().apply { for (index in 0 until 15) values[index] *= D.tileAmbientBrightness }) } - TitleArtwork(item.poster, WolfskinTokens.Image.episodeRequestWidth, WolfskinTokens.Image.episodeRequestHeight, Modifier.fillMaxSize().artOverscan(D.tileAmbientInset).blur(D.tileAmbientBlur), colorFilter = filter) + TitleArtwork(item.poster, (D.episodeCardWidth.value * 2).toInt(), (D.episodeCardHeight.value * 2).toInt(), Modifier.fillMaxSize().artOverscan(D.tileAmbientInset).blur(D.tileAmbientBlur), colorFilter = filter) val height = D.episodeCardHeight - D.tileSheetInset * 2 val shape = remember { RoundedCornerShape(D.tileSheetRadius) } val shadow = remember { Shadow(radius = D.tileShadowRadius, offset = DpOffset.Zero.copy(y = D.tileShadowY), color = Color.Black.copy(alpha = D.tileShadowOpacity)) } TitleArtwork(item.poster, (height.value * 2 * 2 / 3).toInt(), (height.value * 2).toInt(), Modifier.offset(D.tileSheetLeft, D.tileSheetInset).size(height * (2f / 3), height).dropShadow(shape, shadow).clip(shape), poster = true) - } else TitleArtwork(item.backdrop, WolfskinTokens.Image.episodeRequestWidth, WolfskinTokens.Image.episodeRequestHeight, Modifier.fillMaxSize()) + } else TitleArtwork(item.backdrop, (D.episodeCardWidth.value * 2).toInt(), (D.episodeCardHeight.value * 2).toInt(), Modifier.fillMaxSize()) } } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleHeader.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleHeader.kt index 5b2a7c47..85c224bf 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleHeader.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleHeader.kt @@ -74,7 +74,7 @@ fun TitleHeader(state: TitleState, active: Boolean, modifier: Modifier = Modifie Text(if (state.data.connection == TitleConnection.SignedOut) "Requests need this TV to be signed in to Conductarr." else "Requests need Conductarr, and it can’t be reached right now.", color = C.warn, style = TitleTextStyles.body, modifier = Modifier.exactLineBox(TitleTextStyles.body, bottom = D.overviewGap)) } - state.data.playTarget?.let { target -> + state.data.playTarget?.takeIf { it.resumeSeconds > 0 || it.kind == "episode" }?.let { target -> Row(Modifier.exactLineBox(TitleTextStyles.progress, top = D.progressLift, bottom = D.progressBottom).testTag("title-progress"), horizontalArrangement = Arrangement.spacedBy(D.progressGap), verticalAlignment = Alignment.CenterVertically) { if (target.resumeSeconds > 0) { Box(Modifier.size(D.progressWidth, L.progressBar).background(C.progressTrack, RoundedCornerShape(WolfskinTokens.Radius.progress))) { @@ -83,7 +83,6 @@ fun TitleHeader(state: TitleState, active: Boolean, modifier: Modifier = Modifie } Text((if (target.kind == "episode") "${target.episodeLabel} · " else "") + "${((target.runtimeSeconds - target.resumeSeconds + 30) / 60).coerceAtLeast(1)} min left", color = C.muted, style = TitleTextStyles.progress) } else if (target.kind == "episode") Text("Up next: ${target.episodeLabel} · ${target.name}", color = C.muted, style = TitleTextStyles.progress) - if (state.data.connection != TitleConnection.SignedOut) TitleRatings(target.ratings, style = TitleTextStyles.progress) } } Row(Modifier.wrapContentWidth(Alignment.Start, unbounded = true).testTag("title-actions"), horizontalArrangement = Arrangement.spacedBy(L.buttonGap)) { diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleMenu.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleMenu.kt new file mode 100644 index 00000000..2195ff72 --- /dev/null +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleMenu.kt @@ -0,0 +1,69 @@ +package org.justinvisser.wolfskin.design + +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.tween +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.focusable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.input.key.KeyEventType +import androidx.compose.ui.input.key.onPreviewKeyEvent +import androidx.compose.ui.input.key.type +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.graphics.graphicsLayer +import androidx.tv.material3.Text +import org.justinvisser.wolfskin.design.WolfskinTokens.Color as C +import org.justinvisser.wolfskin.design.WolfskinTokens.Layout as L +import org.justinvisser.wolfskin.design.WolfskinTokens.Title as D + +/** A compact modal keeps secondary actions reachable without growing the header row. */ +@Composable +internal fun TitleMenu(state: TitleState, shell: ShellState) { + val visible = state.sheet == TitleSheet.Menu && !shell.pickerVisible + val focus = remember { FocusRequester() } + val reduced = reducedMotion() + val opacity = remember { Animatable(0f) } + LaunchedEffect(visible, reduced) { + if (visible) focus.requestFocus() + opacity.animateTo(if (visible) 1f else 0f, + tween(motionDuration(if (visible) WolfskinTokens.Motion.base else WolfskinTokens.Motion.captionOut, reduced), easing = WolfskinTokens.Motion.easeOut)) + } + if (visible || opacity.value > 0f) { + Box(Modifier.fillMaxSize().background(C.sheetScrim) + .clickable { if (visible) state.back(shell) } + .focusRequester(focus).onPreviewKeyEvent { event -> + val key = readShellKey(event) + visible && key != null && state.key(key, event.type == KeyEventType.KeyDown, event.nativeKeyEvent.repeatCount, shell) + }.focusable()) { + Column(Modifier.align(Alignment.TopEnd).offset(-L.safeSide, D.heroSheetTop).width(D.actionMenuWidth) + .graphicsLayer { alpha = opacity.value } + .background(C.surface, RoundedCornerShape(WolfskinTokens.Radius.panel)) + .padding(D.receiptSide).testTag("title-menu"), verticalArrangement = Arrangement.spacedBy(D.sheetGap)) { + Text("Menu", color = C.fg, style = WolfskinTokens.Type.rowHeading) + state.menuOptions.forEachIndexed { index, option -> + val focused = visible && state.sheetIndex == index + TitleControl(option, focused, + Modifier.fillMaxWidth(), + onFocus = { if (visible) state.sheetIndex = index }, overArtwork = false) { + if (visible) state.clickSheet(index) + } + } + } + } + } +} diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleModel.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleModel.kt index 1fb71dd9..ab6379fc 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleModel.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleModel.kt @@ -63,7 +63,7 @@ data class TitleVersion( enum class TitleReadStatus { Ready, Loading, Unavailable } enum class TitleConnection { SignedIn, SignedOut, Offline } -enum class TitleSheet { Version, Tracks, MediaInfo, ConfirmWatched, HiddenReceipt } +enum class TitleSheet { Menu, Version, Tracks, MediaInfo, ConfirmWatched, HiddenReceipt } /** A title read includes related titles and the selected season; reads happen outside composition. */ @Immutable diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleOptionsSheet.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleOptionsSheet.kt index 3a87dcdd..49039828 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleOptionsSheet.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleOptionsSheet.kt @@ -62,7 +62,7 @@ fun TitleOptionsSheet(state: TitleState, shell: ShellState) { TitleSheet.MediaInfo -> MediaInformation(state) TitleSheet.ConfirmWatched -> WatchedConfirmation(state) TitleSheet.HiddenReceipt -> HiddenReceipt(state) - null -> Unit + TitleSheet.Menu, null -> Unit } } } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePage.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePage.kt index cefe5064..44800e1b 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePage.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePage.kt @@ -69,7 +69,8 @@ fun TitleSurface(state: TitleState, shell: ShellState, modifier: Modifier = Modi androidx.compose.runtime.CompositionLocalProvider(LocalTitleFocusOwner provides focusOwner) { ShellSurface(shell, handlesContentKeys = false) { TitlePage(state, shell, it) } } - if (!shell.pickerVisible && state.sheet != null) TitleOptionsSheet(state, shell) + if (!shell.pickerVisible && state.sheet != null && state.sheet != TitleSheet.Menu) TitleOptionsSheet(state, shell) + TitleMenu(state, shell) if (!shell.pickerVisible) TitleNotice(state.toast, Modifier.align(Alignment.TopEnd)) { state.toast = null } } } @@ -91,9 +92,8 @@ fun TitlePage(state: TitleState, shell: ShellState, modifier: Modifier = Modifie var wheelPending by remember { mutableStateOf(false) } val focus = remember { FocusRequester() } var measuredHeaderHeight by remember(state.data.item.id) { mutableStateOf(L.row_dhead) } - val compactSeries = state.data.status == TitleReadStatus.Ready && state.data.item.held && - state.data.item.kind == "tv" && state.data.item.seasons > 0 - val headerHeight = if (compactSeries) measuredHeaderHeight else L.row_dhead + val compactHeader = state.data.status == TitleReadStatus.Ready + val headerHeight = if (compactHeader) measuredHeaderHeight else L.row_dhead LaunchedEffect(state.sheet, shell.navFocused, shell.pickerVisible) { if (state.sheet == null && !shell.navFocused && !shell.pickerVisible) focus.requestFocus() } @@ -154,7 +154,7 @@ fun TitlePage(state: TitleState, shell: ShellState, modifier: Modifier = Modifie val active = state.row == id && !shell.navFocused && state.sheet == null when (id) { "header" -> Box(Modifier.height(headerHeight)) { - TitleHeader(state, active, if (compactSeries) Modifier.onSizeChanged { size -> + TitleHeader(state, active, if (compactHeader) Modifier.onSizeChanged { size -> measuredHeaderHeight = L.detailCopyTop + D.lineLift + with(density) { size.height.toDp() } + D.seriesHeaderGap } else Modifier) } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePrefetch.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePrefetch.kt index d4a956fc..fdf8b69d 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePrefetch.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePrefetch.kt @@ -22,7 +22,7 @@ internal fun TitleRowPrefetch(data: TitlePageData, row: String?) { queue(data.cast[index].portrait, WolfskinTokens.Image.castRequestWidth, WolfskinTokens.Image.castRequestHeight) "episodes" -> for (index in 0 until minOf(data.episodes.size, WolfskinTokens.Card.tileSlots)) { val item = data.episodes[index] - queue(if (item.isPosterBackdrop) item.poster else item.backdrop, WolfskinTokens.Image.episodeRequestWidth, WolfskinTokens.Image.episodeRequestHeight) + queue(if (item.isPosterBackdrop) item.poster else item.backdrop, (WolfskinTokens.Title.episodeCardWidth.value * 2).toInt(), (WolfskinTokens.Title.episodeCardHeight.value * 2).toInt()) } "related" -> for (index in 0 until minOf(data.related.size, WolfskinTokens.Card.posterSlots)) queue(data.related[index].poster, WolfskinTokens.Image.posterRequestWidth, WolfskinTokens.Image.posterRequestHeight, true) diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleShelf.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleShelf.kt index 429a38ce..708bd7ca 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleShelf.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleShelf.kt @@ -51,7 +51,7 @@ fun TitleCast(state: TitleState, active: Boolean) { LaunchedEffect(state.column, active, state.data.cast.size) { if (active) track.keepColumnInWindow(state.column, WolfskinTokens.Card.personSlots, pitch, state.data.cast.size) } - Box(Modifier.height(D.castHeight)) { + Box(Modifier.height(D.castHeight).testTag("title-cast")) { Text("Cast", color = C.fg, style = WolfskinTokens.Type.rowHeading, modifier = Modifier.padding(start = L.safeSide).height(L.rowHeadingBand)) LazyRow(state = track, modifier = Modifier.fillMaxWidth().offset(y = L.rowHeadingBand - L.rowGapAfter).height(WolfskinTokens.Card.personH + L.rowGapAfter * 2).skeletonPulse(state.data.castStatus == TitleReadStatus.Loading), contentPadding = PaddingValues(horizontal = L.safeSide, vertical = L.rowGapAfter), horizontalArrangement = Arrangement.spacedBy(WolfskinTokens.Card.personGap)) { @@ -80,11 +80,11 @@ fun TitleCast(state: TitleState, active: Boolean) { fun TitleMediaShelf(state: TitleState, episodes: Boolean, active: Boolean) { val titles = if (episodes) state.data.episodes else state.data.related val id = if (episodes) "episodes" else "related" - val width = if (episodes) WolfskinTokens.Card.tileW else WolfskinTokens.Card.posterW + val width = if (episodes) D.episodeCardWidth else WolfskinTokens.Card.posterW val height = if (episodes) D.episodeCardHeight else WolfskinTokens.Card.posterH val track = rememberLazyListState() - val visible = if (episodes) WolfskinTokens.Card.tileSlots else WolfskinTokens.Card.posterSlots - val pitch = with(LocalDensity.current) { (if (episodes) WolfskinTokens.Card.tilePitch else WolfskinTokens.Card.posterPitch).toPx() } + val visible = if (episodes) ((WolfskinTokens.Shell.stageWidth - L.safeSide * 2 + WolfskinTokens.Card.tileGap) / (D.episodeCardWidth + WolfskinTokens.Card.tileGap)).toInt() else WolfskinTokens.Card.posterSlots + val pitch = with(LocalDensity.current) { (if (episodes) D.episodeCardWidth + WolfskinTokens.Card.tileGap else WolfskinTokens.Card.posterPitch).toPx() } LaunchedEffect(state.column, active, titles.size) { if (active) track.keepColumnInWindow(state.column, visible, pitch, titles.size) } @@ -92,13 +92,13 @@ fun TitleMediaShelf(state: TitleState, episodes: Boolean, active: Boolean) { Text(if (episodes) "Season ${state.season}" else "More like this", color = C.fg, style = WolfskinTokens.Type.rowHeading, modifier = Modifier.padding(start = L.safeSide).height(L.rowHeadingBand)) LazyRow(state = track, modifier = Modifier.fillMaxWidth().offset(y = L.rowHeadingBand - L.rowGapAfter) .height(height + (if (episodes) WolfskinTokens.Shell.zero else WolfskinTokens.Card.posterCaptionBand) + L.rowGapAfter * 2).skeletonPulse(episodes && state.data.episodesStatus == TitleReadStatus.Loading), - contentPadding = PaddingValues(horizontal = L.safeSide, vertical = L.rowGapAfter), horizontalArrangement = Arrangement.spacedBy(WolfskinTokens.Card.posterGap)) { + contentPadding = PaddingValues(horizontal = L.safeSide, vertical = L.rowGapAfter), horizontalArrangement = Arrangement.spacedBy(if (episodes) WolfskinTokens.Card.tileGap else WolfskinTokens.Card.posterGap)) { if (episodes && state.data.episodesStatus == TitleReadStatus.Loading) { - items(visible, key = { "episode-skeleton-$it" }, contentType = { "skeleton" }) { - Box(Modifier.size(width, height).background(C.surface2, RoundedCornerShape(WolfskinTokens.Radius.card))) + items(visible, key = { "episode-skeleton-$it" }, contentType = { "skeleton" }) { index -> + Box(Modifier.size(width, height).testTag("title-episode-slot-$index").background(C.surface2, RoundedCornerShape(WolfskinTokens.Radius.card))) } } else itemsIndexed(titles, key = { _, item -> item.id }, contentType = { _, _ -> if (episodes) "tile" else "poster" }) { index, item -> - TitlePoster(item, active && state.column == index, Modifier.width(width) + TitlePoster(item, active && state.column == index, Modifier.width(width).then(if (episodes) Modifier.testTag("title-episode-slot-$index") else Modifier) .onGloballyPositioned { state.recordCenter(id, index, it.boundsInRoot().center.x) }, episodes, state.data.connection != TitleConnection.SignedOut, onFocus = { state.focus(id, index) }) { state.click(id, index) } } @@ -117,17 +117,16 @@ fun TitlePoster(item: TitleItem, focused: Boolean, modifier: Modifier = Modifier LibraryPoster(item, focused, focused && ratingsVisible, catalogue = alwaysShowCaption, showWatchState = true, modifier = Modifier.titlePointerFocus(onFocus).clickable { focusOwner?.invoke(); onClick() }, offlineArt = offlineArt) } else TitleCard(focused, Modifier.titlePointerFocus(onFocus).clickable { focusOwner?.invoke(); onClick() }, - WolfskinTokens.Card.tileW, D.episodeCardHeight, watched = item.watched, + D.episodeCardWidth, D.episodeCardHeight, watched = item.watched, progress = item.progress.takeIf { it < 1f } ?: 0f) { TitleTileArtwork(item) Column(Modifier.align(Alignment.BottomStart).fillMaxWidth().background(Brush.verticalGradient(listOf(C.bg.copy(alpha = 0f), C.bg.copy(alpha = D.cardOverlayOpacity)))) .padding(start = D.tileOverlaySide, end = D.tileOverlaySide, top = D.tileOverlayTop, bottom = D.tileOverlayBottom)) { - Text(item.seriesName ?: item.name, color = C.fg, style = WolfskinTokens.Type.button, maxLines = 1, overflow = TextOverflow.Ellipsis) - Text("${item.episodeLabel} · ${item.name}", color = C.muted, style = WolfskinTokens.Type.caption, maxLines = 1, overflow = TextOverflow.Ellipsis) - if (focused && item.overview.isNotBlank()) Text(item.overview, color = C.muted, style = WolfskinTokens.Type.caption, maxLines = 2, overflow = TextOverflow.Ellipsis) - if (focused) CardMetadata(null, if (item.runtimeSeconds > 0) item.runtime else null, item.watched && item.resumeSeconds <= 0) + Text(item.name, color = C.fg, style = WolfskinTokens.Type.button, maxLines = 1, overflow = TextOverflow.Ellipsis) + if (focused && item.overview.isNotBlank()) Text(item.overview, color = C.muted, style = WolfskinTokens.Type.caption, maxLines = 1, overflow = TextOverflow.Ellipsis) + CardMetadata(null, item.episodeLabel + if (item.runtimeSeconds > 0) " · ${item.runtime}" else "", item.watched && item.resumeSeconds <= 0) } - androidx.compose.animation.AnimatedVisibility(focused && ratingsVisible, enter = fadeIn(tween(motionDuration(WolfskinTokens.Motion.base, reducedMotion()))), exit = fadeOut(tween(motionDuration(WolfskinTokens.Motion.base, reducedMotion())))) { + androidx.compose.animation.AnimatedVisibility(focused && ratingsVisible, enter = fadeIn(tween(motionDuration(WolfskinTokens.Motion.base, reducedMotion()), easing = WolfskinTokens.Motion.easeOut)), exit = fadeOut(tween(motionDuration(WolfskinTokens.Motion.base, reducedMotion()), easing = WolfskinTokens.Motion.easeOut))) { LibraryRatingPlate(item.ratings, Modifier.fillMaxWidth()) } } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleState.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleState.kt index d8a6d560..af484aeb 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleState.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleState.kt @@ -24,6 +24,13 @@ class TitleState( var sheet by mutableStateOf(null) private set var sheetIndex by mutableStateOf(0) + private var mediaInfoFromMenu = false + val menuOptions: List by derivedStateOf { buildList { + if (target != null) add(TitleOption("info", "Media info", "more", icon = false)) + if (data.connection == TitleConnection.SignedIn && data.requestsAllowed) { + add(TitleOption("add", "Add for someone", "users", icon = false)) + } + } } var season by mutableStateOf(initial.selectedSeason ?: initial.playTarget?.season?.takeIf { it in initial.seasonNumbers } ?: initial.seasonNumbers.firstOrNull() ?: 1) var versionId by mutableStateOf(initial.selectedVersion) var audioIndex by mutableStateOf(initial.selectedAudio) @@ -140,7 +147,7 @@ class TitleState( /** Sheets and shell overlays close first; a pushed title/person pops from content or nav. */ fun back(shell: ShellState) { when { - sheet != null -> sheet = null + sheet != null -> closeSheet() shell.pickerVisible || shell.requestsVisible -> shell.key(ShellKey.Back) else -> onAction(TitleAction.Pop) } @@ -182,13 +189,13 @@ class TitleState( "play", "restart" -> if (data.watchReady) target?.let { onAction(TitleAction.Play(it, id == "restart")) } "version" -> { sheetIndex = data.versions.indexOf(version).coerceAtLeast(0); sheet = TitleSheet.Version } "tracks" -> { sheetIndex = 0; sheet = TitleSheet.Tracks } - "more" -> { sheetIndex = 0; sheet = TitleSheet.MediaInfo } + "menu" -> { sheetIndex = 0; sheet = TitleSheet.Menu } "watched" -> if (data.watchTarget.kind == "tv") { sheetIndex = 0; sheet = TitleSheet.ConfirmWatched } else toggleWatched() "trailer" -> data.trailerUrl?.let { onAction(TitleAction.Trailer(it)) } "seasons" -> focus("seasons", data.seasonNumbers.indexOf(season).coerceAtLeast(0)) "retry" -> onAction(TitleAction.Retry) "back" -> onAction(TitleAction.Pop) - "request", "other", "add" -> onAction(TitleAction.Request(data.item, id != "request")) + "request", "add" -> onAction(TitleAction.Request(data.item, id != "request")) "status" -> onAction(TitleAction.Requests(data.item)) "hide", "unhide" -> { val hidden = id == "hide" @@ -205,9 +212,10 @@ class TitleState( } private fun sheetKey(key: ShellKey) { - if (key == ShellKey.Back) { sheet = null; return } + if (key == ShellKey.Back) { closeSheet(); return } val current = version val size = when (sheet) { + TitleSheet.Menu -> menuOptions.size TitleSheet.Version -> data.versions.size TitleSheet.Tracks -> (current?.audio?.size ?: 0) + (current?.subtitles?.size ?: 0) + 2 TitleSheet.ConfirmWatched, TitleSheet.HiddenReceipt -> 2 @@ -217,6 +225,16 @@ class TitleState( ShellKey.Up, ShellKey.Left -> sheetIndex = (sheetIndex - 1).coerceAtLeast(0) ShellKey.Down, ShellKey.Right -> sheetIndex = (sheetIndex + 1).coerceAtMost(size - 1) ShellKey.Ok -> when (sheet) { + TitleSheet.Menu -> menuOptions.getOrNull(sheetIndex)?.let { option -> + if (option.id == "info") { + mediaInfoFromMenu = true + sheetIndex = 0 + sheet = TitleSheet.MediaInfo + } else { + sheet = null + activateOption(option.id) + } + } TitleSheet.Version -> { val selected = data.versions[sheetIndex] versionId = selected.id @@ -234,11 +252,19 @@ class TitleState( onAction(TitleAction.Hide(data.item, false)) } else onAction(TitleAction.Pop) } - else -> sheet = null + else -> closeSheet() } } } + private fun closeSheet() { + if (sheet == TitleSheet.MediaInfo && mediaInfoFromMenu) { + mediaInfoFromMenu = false + sheetIndex = 0 + sheet = TitleSheet.Menu + } else sheet = null + } + private fun selectTrack(current: TitleVersion) { when { sheetIndex < current.audio.size -> audioIndex = current.audio[sheetIndex].index @@ -274,14 +300,13 @@ fun titleOptions(state: TitleState): List = buildList { val series = data.watchTarget.kind == "tv" add(TitleOption("watched", "Mark ${if (series) "series " else ""}as ${if (state.watched) "unwatched" else "watched"}", if (state.watched) "eye" else "eyeoff", if (data.watchTarget.kind == "episode") data.watchTarget.episodeLabel else "", on = state.watched)) if (data.trailerUrl != null) add(TitleOption("trailer", "Play trailer", "trailer")) - if (target != null) add(TitleOption("more", "More", "more", "Media info")) - if (item.kind == "tv" && item.seasons > 0) add(TitleOption("seasons", "Seasons", "tv", icon = false)) - if (data.connection == TitleConnection.SignedIn && data.requestsAllowed) add(TitleOption("add", "Add for someone", "users", icon = false)) + if (target != null || (data.connection == TitleConnection.SignedIn && data.requestsAllowed)) add(TitleOption("menu", "Menu", "more")) + if (item.kind == "tv" && item.seasons > 0 && data.watchTarget.kind != "episode") add(TitleOption("seasons", "Seasons", "tv", icon = false)) } else if (data.connection != TitleConnection.SignedIn || !data.requestsAllowed) { add(TitleOption("retry", "Try again", "wifi", primary = true, icon = false)) } else { add(TitleOption(if (data.requestedStage == null) "request" else "status", data.requestedStage?.let { "Requested · $it" } ?: "Request", data.requestedStage?.let(::titleStageGlyph) ?: "plus", primary = true, icon = false)) - add(TitleOption("other", "For someone else", "users", icon = false)) + add(TitleOption("menu", "Menu", "more")) if (data.hidden) add(TitleOption("unhide", "Show again", "undo", icon = false)) else if (data.pick) add(TitleOption("hide", "Not interested", "eyeoff", icon = false)) } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt index 6c014755..459fd3fc 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt @@ -451,7 +451,9 @@ object WolfskinTokens { const val sheetOpacity = 0.5f } object Title { - val episodeCardHeight = 140.0.dp + val episodeCardWidth = 224.0.dp + val episodeCardHeight = 126.0.dp + val actionMenuWidth = 260.0.dp val seriesHeaderGap = 20.0.dp val lineGap = 11.0.dp val lineLift = -2.0.dp diff --git a/wolfskin-design/title-tokens.json b/wolfskin-design/title-tokens.json index 309913d4..cdcda86e 100644 --- a/wolfskin-design/title-tokens.json +++ b/wolfskin-design/title-tokens.json @@ -1,6 +1,8 @@ { "title": { - "episodeCardHeight": {"dp": 140, "px": 280, "source": "feedback-2026-11-06: episode art height +24.4%"}, + "episodeCardWidth": {"dp": 224, "px": 448, "source": "tv-round2: episode width +12%; 16:9 art"}, + "episodeCardHeight": {"dp": 126, "px": 252, "source": "tv-round2: 16:9 episode art"}, + "actionMenuWidth": {"dp": 260, "px": 520, "source": "tv-round2: compact title action menu"}, "seriesHeaderGap": {"dp": 20, "px": 40, "source": "feedback-2026-11-06: measured series header to seasons"}, "lineGap": {"dp": 11, "px": 22, "source": "index.html:214"}, "lineLift": {"dp": -2, "px": -4, "source": "index.html:214"}, diff --git a/wolfskin-design/tokens.css b/wolfskin-design/tokens.css index cb81f2a5..8ca184ac 100644 --- a/wolfskin-design/tokens.css +++ b/wolfskin-design/tokens.css @@ -290,7 +290,9 @@ --lift-heroY: 30.0px; --lift-sheetBlur: 80.0px; --lift-sheetX: -30.0px; - --title-episodeCardHeight: 280.0px; + --title-episodeCardWidth: 448.0px; + --title-episodeCardHeight: 252.0px; + --title-actionMenuWidth: 520.0px; --title-seriesHeaderGap: 40.0px; --title-lineGap: 22.0px; --title-lineLift: -4.0px; diff --git a/wolfskin-design/tokens.sha256 b/wolfskin-design/tokens.sha256 index a45b7f17..3ef0cd19 100644 --- a/wolfskin-design/tokens.sha256 +++ b/wolfskin-design/tokens.sha256 @@ -2,7 +2,7 @@ b3f096b692c395534177cc82ac68f5b801870bc7e28f0dd5cd7c17e2103920a3 discover-token c29dc64f3c3ca900c747b3db8b270e25908948bf5f76388d2c627a612fc7c99d generate_tokens.py eef4e9f8c91306362540eda617c9efad4e19ed688f205f6f486625a5918d8105 home-tokens.json 192beb887fc34005db99c87ffbcbaf4a057ee2728475fc96224cf89445019b51 shell-tokens.json -3e2ad9a57c15c2ed4713abf383807bb567b27b38eddaaa36c00025e078864e12 src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt -062597ea50dff9e6987485f9a83d412918dba3e10109524c26d3c2332a2f5b73 title-tokens.json -d7d6b17f8258083c879365f01e06729aa0fa12b69b7cd81e1bceabbbe6ab2a7d tokens.css +12420580fed6e6977c8762fb0649f0ed22ca6a8df32d65ea69b3965cd851bb65 src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt +98054296d1de4df2f9f4808d505e512d5906f5f23f7a05e6d846391d93effa5e title-tokens.json +40d763d9023abb56c197201a6a13d3fefacb681713010f849d450c96216e37cb tokens.css ba0da02b03047fbc2f29d538d980e87aa237f8ae36545aa4234600243fe14929 tokens.json From a159c835c54564ce1b935aeda91436811bfb570f Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 15:46:56 +0100 Subject: [PATCH 05/18] Preserve episode height and fix title overlay and poster collisions --- .../wolfskin/tv/TitleCaptureTest.kt | 2 + .../wolfskin/tv/TitleRound2Test.kt | 83 ++++++++++++++++++- docker/README.md | 13 ++- .../wolfskin/design/TitleArtwork.kt | 7 +- .../justinvisser/wolfskin/design/TitleMenu.kt | 2 +- .../justinvisser/wolfskin/design/TitlePage.kt | 5 +- .../wolfskin/design/TitlePrefetch.kt | 2 +- .../wolfskin/design/TitleState.kt | 3 +- .../wolfskin/design/WolfskinTokens.kt | 5 +- .../wolfskin/design/WolfskinImagesTest.kt | 2 +- wolfskin-design/title-tokens.json | 5 +- wolfskin-design/tokens.css | 3 +- wolfskin-design/tokens.json | 4 +- wolfskin-design/tokens.sha256 | 8 +- 14 files changed, 118 insertions(+), 26 deletions(-) diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/TitleCaptureTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleCaptureTest.kt index 270271b1..01a166a0 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/TitleCaptureTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleCaptureTest.kt @@ -223,4 +223,6 @@ class TitleCaptureTest { @Test fun round2MussoliniResume() = capture(121, "episode-episode-1-2025-s1e1", "shared", transform = { it.copy(episodes = it.episodes.distinctBy { episode -> episode.id }) }) @Test fun round2Episodes() = capture(122, "episode-episode-1-2025-s1e1", "shared", transform = { it.copy(episodes = it.episodes.distinctBy { episode -> episode.id }) }) { state, _ -> state.focus("episodes", 0) } @Test fun round2NotHeldSeries() = capture(123, "90 Day Fiancé: Before the 90 Days") + @Test fun round2HeldPosterFallback() = capture(124, "The Girl Who Leapt Through Time", transform = { it.copy(item = it.item.copy(backdrop = null, isPosterBackdrop = true, overview = "Short overview.")) }) + @Test fun round2NotHeldShortOverview() = capture(125, "The Amazing Spider-Man", transform = { it.copy(item = it.item.copy(backdrop = null, isPosterBackdrop = true, overview = "Short overview.")) }) } diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/TitleRound2Test.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleRound2Test.kt index d0c503e4..ff2edf66 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/TitleRound2Test.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleRound2Test.kt @@ -88,11 +88,12 @@ class TitleRound2Test { val actions = rule.onNodeWithTag("title-actions").fetchSemanticsNode().boundsInRoot val cast = rule.onNodeWithTag("title-cast").fetchSemanticsNode().boundsInRoot val gap = cast.top - actions.bottom - assertTrue("Cast must follow the action caption and normal section gap: $gap", gap in 40f..110f) + assertTrue("Cast follows the actions without the old fixed header reservation", gap > 0 && cast.top < WolfskinTokens.Layout.row_dhead.value * 2) rule.runOnIdle { state.update(state.data.copy(requestedStage = "Searching", requestActor = "Justin")) } val requestedActions = rule.onNodeWithTag("title-actions").fetchSemanticsNode().boundsInRoot val requestedCast = rule.onNodeWithTag("title-cast").fetchSemanticsNode().boundsInRoot - assertEquals("An actual readiness line belongs in the stack, not a fixed empty header", gap, requestedCast.top - requestedActions.bottom, 1f) + assertTrue(requestedActions.bottom < requestedCast.top) + assertTrue("A readiness line cannot move Cast backwards or recreate the old reservation", requestedCast.top >= cast.top && requestedCast.top < WolfskinTokens.Layout.row_dhead.value * 2) } @Test fun mussoliniResumeHasOnlyFactsRatingsAndNoRedundantSeasonsAction() { @@ -126,7 +127,8 @@ class TitleRound2Test { rule.runOnIdle { state.update(state.data.copy(episodesStatus = TitleReadStatus.Ready)) } val ready = rule.onNodeWithTag("title-episode-slot-0").fetchSemanticsNode().boundsInRoot assertEquals(skeleton, ready) - assertEquals(16f / 9f, ready.width / ready.height, 0.01f) + assertEquals(448f, ready.width, 0.1f) + assertEquals("Wider cards retain the approved taller episode art", 280f, ready.height, 0.1f) rule.runOnIdle { state.focus("episodes", 0) } val episode = state.data.episodes.first() rule.onNodeWithText(episode.episodeLabel + " · " + episode.runtime).assertIsDisplayed() @@ -143,6 +145,81 @@ class TitleRound2Test { rule.onNodeWithText("Container", useUnmergedTree = true).assertIsDisplayed() } + @Test fun shortOverviewMoviesKeepCastBelowThePosterForHeldAndNotAddedTitles() { + render("The Amazing Spider-Man") { it.copy(item = it.item.copy(overview = "Short overview.", backdrop = null, isPosterBackdrop = true)) } + for (held in listOf(false, true)) { + rule.runOnIdle { state.update(state.data.copy(item = state.data.item.copy(held = held))) } + val poster = rule.onNodeWithTag("title-poster-backdrop").fetchSemanticsNode().boundsInRoot + val firstActor = rule.onNodeWithTag("title-cast-${state.data.cast.first().id}").fetchSemanticsNode().boundsInRoot + assertTrue("Cast clears the poster on held=$held: $firstActor vs $poster", firstActor.top >= poster.bottom + 20f - 0.5f) + } + } + + @Test fun revokingTheOnlyMenuActionClosesAnOtherwiseEmptyMenu() { + render("The Amazing Spider-Man") + menu() + rule.runOnIdle { state.update(state.data.copy(requestsAllowed = false)) } + assertNull(state.sheet) + rule.mainClock.advanceTimeBy(300) + rule.onNodeWithTag("title-menu", useUnmergedTree = true).assertDoesNotExist() + } + + @Test fun mediaInfoKeepsTableTextSeparatedInsteadOfAccumulatingOverlap() { + render() + menu() + press(Key.DirectionCenter) + rule.onNodeWithText("Container", useUnmergedTree = true).assertIsDisplayed() + rule.onNodeWithText("Dutch", useUnmergedTree = true).assertIsDisplayed() + val text = rule.onAllNodes(SemanticsMatcher.keyIsDefined(androidx.compose.ui.semantics.SemanticsActions.GetTextLayoutResult) and hasAnyAncestor(hasTestTag("title-sheet")), useUnmergedTree = true) + .fetchSemanticsNodes().map { it.boundsInRoot }.filter { it.width > 0 && it.height > 0 } + text.forEachIndexed { index, first -> text.drop(index + 1).forEach { second -> + if (minOf(first.right, second.right) > maxOf(first.left, second.left)) { + assertTrue("Media info text must never collide vertically: $first vs $second", minOf(first.bottom, second.bottom) <= maxOf(first.top, second.top)) + } + } } + } + + @Test fun menuToMediaInfoNeverDoubleDimsOrPopsAndBackKeepsOneScrim() { + render { it.copy(item = it.item.copy(backdrop = null, poster = null), cast = emptyList(), related = emptyList()) } + menu() + rule.mainClock.autoAdvance = false + val directory = File(requireNotNull(System.getProperty("wolfskin.captureDirectory")), "title-menu-info-motion").apply { mkdirs() } + rule.runOnIdle { state.clickSheet(0) } + var waited = 0 + while (rule.onAllNodesWithTag("title-sheet", useUnmergedTree = true).fetchSemanticsNodes().isEmpty() && waited <= WolfskinTokens.Motion.base + 100) { + rule.mainClock.advanceTimeByFrame() + rule.waitForIdle() + waited += 16 + } + val records = mutableListOf() + fun frame(phase: String, index: Int): Pair { + val path = File(directory, "$phase-${index.toString().padStart(2, '0')}.png") + rule.onRoot().captureRoboImage(path.absolutePath) + val bitmap = BitmapFactory.decodeFile(path.absolutePath) + fun brightness(x: Int, y: Int): Int { + val pixel = bitmap.getPixel(x, y) + return android.graphics.Color.red(pixel) + android.graphics.Color.green(pixel) + android.graphics.Color.blue(pixel) + } + return try { + (brightness(1900, 900) to brightness(100, 900)).also { records.add("$phase,${index * 16},${it.first},${it.second}") } + } finally { bitmap.recycle() } + } + val info = List(14) { index -> + rule.waitForIdle() + frame("info", index).also { rule.mainClock.advanceTimeBy(16); rule.waitForIdle() } + } + info.forEach { assertEquals("No extra scrim or disappearing overlay may darken or pop over Media info", info.last(), it) } + rule.runOnIdle { state.back(shell) } + repeat(14) { index -> + rule.mainClock.advanceTimeBy(16) + rule.waitForIdle() + assertEquals("Returning to Menu keeps exactly one scrim", info.last().second, frame("back", index).second) + } + rule.onNodeWithTag("title-menu", useUnmergedTree = true).assertExists() + File(directory, "samples.csv").writeText("phase,timeMs,sheetBrightness,leftBrightness\n" + records.joinToString("\n")) + rule.mainClock.autoAdvance = true + } + @Test fun menuFadeFramesStayMonotonicAndNeverTranslate() { render { it.copy(item = it.item.copy(backdrop = null, poster = null), cast = emptyList(), related = emptyList()) } rule.mainClock.autoAdvance = false diff --git a/docker/README.md b/docker/README.md index c342ac2f..5522ca13 100644 --- a/docker/README.md +++ b/docker/README.md @@ -628,17 +628,20 @@ retain the approved frames except for the requested feedback changes: Discover uses all six approved poster slots. Person keeps the final column at full poster width. - Episode images choose episode Primary, then Thumb, then the already-read series Backdrop. - Title episode cards now use 448×252 px (16:9), with a one-line focused summary, - no show-name overlay, and `S1 E3 · duration` plus the watched check on one line. + Title episode cards now use 448×280 px, preserving the taller approved crop. + Focused summaries ellipsise to one line, the show-name overlay is absent, and + `S1 E3 · duration` plus the watched check share one line. Ready title headers measure their copy/actions and leave 40 px before the following section; series retain the empty 56 px readiness reservation. + Poster-only movies floor that stack so Cast circles clear the poster by at + least 20 px, including held movie fallbacks and short overviews. - Every Discover heading uses a 104 px band, including a 60 px title-to-card gap. Home heading geometry is unchanged. - Hero/backdrop decoding is bounded to 1920×1080; upright hero sheets request 420×630. The shared request builder replaces conflicting Jellyfin size/encoding parameters: cards use WebP quality 80, while hero backdrops/sheets retain JPEG quality 96. Poster/tile/wide/episode requests are 256×384, 400×225, 544×306 and - 448×252; Jellyfin fill preserves aspect ratio before the UI crops. Tags and + 448×280; Jellyfin fill preserves aspect ratio before the UI crops. Tags and authentication query parameters remain intact. TMDB uses w342 for posters and portraits, w780 for landscape cards and w1280 for hero backdrops, never original. Lossy WebP decoding is guaranteed below minSdk 23; API 28+ additionally checks @@ -698,7 +701,9 @@ Version, tracks, watched and trailer controls keep their existing positions. Back from Media info returns to the menu; Back from the menu restores its opening button. The compact menu fades in for 160 ms and out for 100 ms using the motion ease-out token, with reduced-motion fades capped at 80 ms. Only the -bounded menu panel owns an alpha layer; the scrim is static. Controls +bounded menu panel owns an alpha layer; the scrim is static. Opening another +sheet immediately removes the menu panel and scrim, preventing double darkening. +An empty menu closes if its last permitted action disappears. Controls use the shared 4 px straddle focus ring. Episode details omit the redundant Seasons shortcut; series pages retain it. Ratings appear only in the header facts line, not again beside progress, on movie, series and episode pages. diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleArtwork.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleArtwork.kt index 8adac820..25f5cffa 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleArtwork.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleArtwork.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.tv.material3.Text @@ -110,7 +111,7 @@ fun TitleBackdrop(item: TitleItem, modifier: Modifier = Modifier) { val posterShadow = remember { Shadow(radius = D.posterShadowRadius, offset = DpOffset.Zero.copy(y = D.posterShadowY), color = Color.Black.copy(alpha = D.posterShadowOpacity)) } TitleArtwork(item.poster, (L.heroSheetWidth.value * 2).toInt(), (L.heroSheetHeight.value * 2).toInt(), Modifier.offset(WolfskinTokens.Shell.stageWidth - L.heroSheetWidth - D.heroSheetRight, D.heroSheetTop) - .size(L.heroSheetWidth, L.heroSheetHeight).dropShadow(posterShape, posterShadow).clip(posterShape), poster = true) + .size(L.heroSheetWidth, L.heroSheetHeight).testTag("title-poster-backdrop").dropShadow(posterShape, posterShadow).clip(posterShape), poster = true) } Box(Modifier.fillMaxSize().background(horizontal)) Box(Modifier.fillMaxSize().background(vertical)) @@ -136,13 +137,13 @@ fun TitleTileArtwork(item: TitleItem) { val filter = remember { ColorFilter.colorMatrix(ColorMatrix().apply { for (index in 0 until 15) values[index] *= D.tileAmbientBrightness }) } - TitleArtwork(item.poster, (D.episodeCardWidth.value * 2).toInt(), (D.episodeCardHeight.value * 2).toInt(), Modifier.fillMaxSize().artOverscan(D.tileAmbientInset).blur(D.tileAmbientBlur), colorFilter = filter) + TitleArtwork(item.poster, WolfskinTokens.Image.episodeRequestWidth, WolfskinTokens.Image.episodeRequestHeight, Modifier.fillMaxSize().artOverscan(D.tileAmbientInset).blur(D.tileAmbientBlur), colorFilter = filter) val height = D.episodeCardHeight - D.tileSheetInset * 2 val shape = remember { RoundedCornerShape(D.tileSheetRadius) } val shadow = remember { Shadow(radius = D.tileShadowRadius, offset = DpOffset.Zero.copy(y = D.tileShadowY), color = Color.Black.copy(alpha = D.tileShadowOpacity)) } TitleArtwork(item.poster, (height.value * 2 * 2 / 3).toInt(), (height.value * 2).toInt(), Modifier.offset(D.tileSheetLeft, D.tileSheetInset).size(height * (2f / 3), height).dropShadow(shape, shadow).clip(shape), poster = true) - } else TitleArtwork(item.backdrop, (D.episodeCardWidth.value * 2).toInt(), (D.episodeCardHeight.value * 2).toInt(), Modifier.fillMaxSize()) + } else TitleArtwork(item.backdrop, WolfskinTokens.Image.episodeRequestWidth, WolfskinTokens.Image.episodeRequestHeight, Modifier.fillMaxSize()) } } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleMenu.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleMenu.kt index 2195ff72..64e848e1 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleMenu.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleMenu.kt @@ -43,7 +43,7 @@ internal fun TitleMenu(state: TitleState, shell: ShellState) { opacity.animateTo(if (visible) 1f else 0f, tween(motionDuration(if (visible) WolfskinTokens.Motion.base else WolfskinTokens.Motion.captionOut, reduced), easing = WolfskinTokens.Motion.easeOut)) } - if (visible || opacity.value > 0f) { + if ((visible || opacity.value > 0f) && (state.sheet == null || state.sheet == TitleSheet.Menu)) { Box(Modifier.fillMaxSize().background(C.sheetScrim) .clickable { if (visible) state.back(shell) } .focusRequester(focus).onPreviewKeyEvent { event -> diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePage.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePage.kt index 44800e1b..4a79a147 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePage.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePage.kt @@ -93,7 +93,10 @@ fun TitlePage(state: TitleState, shell: ShellState, modifier: Modifier = Modifie val focus = remember { FocusRequester() } var measuredHeaderHeight by remember(state.data.item.id) { mutableStateOf(L.row_dhead) } val compactHeader = state.data.status == TitleReadStatus.Ready - val headerHeight = if (compactHeader) measuredHeaderHeight else L.row_dhead + val item = state.data.item + val posterFloor = if (item.kind == "movie" && item.poster != null && (item.backdrop == null || item.isPosterBackdrop)) + D.heroSheetTop + L.heroSheetHeight + D.posterCastGap - L.rowHeadingBand else WolfskinTokens.Shell.zero + val headerHeight = if (compactHeader) measuredHeaderHeight.coerceAtLeast(posterFloor) else L.row_dhead LaunchedEffect(state.sheet, shell.navFocused, shell.pickerVisible) { if (state.sheet == null && !shell.navFocused && !shell.pickerVisible) focus.requestFocus() } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePrefetch.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePrefetch.kt index fdf8b69d..d4a956fc 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePrefetch.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePrefetch.kt @@ -22,7 +22,7 @@ internal fun TitleRowPrefetch(data: TitlePageData, row: String?) { queue(data.cast[index].portrait, WolfskinTokens.Image.castRequestWidth, WolfskinTokens.Image.castRequestHeight) "episodes" -> for (index in 0 until minOf(data.episodes.size, WolfskinTokens.Card.tileSlots)) { val item = data.episodes[index] - queue(if (item.isPosterBackdrop) item.poster else item.backdrop, (WolfskinTokens.Title.episodeCardWidth.value * 2).toInt(), (WolfskinTokens.Title.episodeCardHeight.value * 2).toInt()) + queue(if (item.isPosterBackdrop) item.poster else item.backdrop, WolfskinTokens.Image.episodeRequestWidth, WolfskinTokens.Image.episodeRequestHeight) } "related" -> for (index in 0 until minOf(data.related.size, WolfskinTokens.Card.posterSlots)) queue(data.related[index].poster, WolfskinTokens.Image.posterRequestWidth, WolfskinTokens.Image.posterRequestHeight, true) diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleState.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleState.kt index af484aeb..fad34b31 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleState.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleState.kt @@ -26,7 +26,7 @@ class TitleState( var sheetIndex by mutableStateOf(0) private var mediaInfoFromMenu = false val menuOptions: List by derivedStateOf { buildList { - if (target != null) add(TitleOption("info", "Media info", "more", icon = false)) + if (target != null) add(TitleOption("info", "Media info", "", icon = false)) if (data.connection == TitleConnection.SignedIn && data.requestsAllowed) { add(TitleOption("add", "Add for someone", "users", icon = false)) } @@ -72,6 +72,7 @@ class TitleState( if (!pendingSubtitle) subtitleIndex = value.selectedSubtitle if (row !in rows) { row = "header"; column = 0 } column = column.coerceAtMost(rowSize(row).minus(1).coerceAtLeast(0)) + if (sheet == TitleSheet.Menu && menuOptions.isEmpty()) sheet = null } /** Pointer focus and D-pad use the same row memory. */ diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt index 459fd3fc..e10e109f 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt @@ -262,7 +262,7 @@ object WolfskinTokens { const val heroRequestHeight = 1080 const val heroPosterRequestWidth = 420 const val heroPosterRequestHeight = 630 - const val episodeRequestWidth = 400 + const val episodeRequestWidth = 448 const val episodeRequestHeight = 280 const val castRequestWidth = 200 const val castRequestHeight = 200 @@ -452,9 +452,10 @@ object WolfskinTokens { } object Title { val episodeCardWidth = 224.0.dp - val episodeCardHeight = 126.0.dp + val episodeCardHeight = 140.0.dp val actionMenuWidth = 260.0.dp val seriesHeaderGap = 20.0.dp + val posterCastGap = 10.0.dp val lineGap = 11.0.dp val lineLift = -2.0.dp val overviewGap = 17.0.dp diff --git a/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/WolfskinImagesTest.kt b/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/WolfskinImagesTest.kt index dfefe549..a027f92f 100644 --- a/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/WolfskinImagesTest.kt +++ b/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/WolfskinImagesTest.kt @@ -18,7 +18,7 @@ class WolfskinImagesTest { Surface("grid/Home/Discover/person poster", 256, 384, "w342"), Surface("Home tile", 400, 225, "w780"), Surface("Home wide", 544, 306, "w780"), - Surface("episode still", 400, 280, "w780"), + Surface("episode still", 448, 280, "w780"), Surface("cast portrait", 200, 200, "w342"), Surface("person portrait", 240, 240, "w342"), Surface("hero poster", 420, 630, "w342", true), diff --git a/wolfskin-design/title-tokens.json b/wolfskin-design/title-tokens.json index cdcda86e..99f15d01 100644 --- a/wolfskin-design/title-tokens.json +++ b/wolfskin-design/title-tokens.json @@ -1,9 +1,10 @@ { "title": { - "episodeCardWidth": {"dp": 224, "px": 448, "source": "tv-round2: episode width +12%; 16:9 art"}, - "episodeCardHeight": {"dp": 126, "px": 252, "source": "tv-round2: 16:9 episode art"}, + "episodeCardWidth": {"dp": 224, "px": 448, "source": "tv-round2: episode width +12%"}, + "episodeCardHeight": {"dp": 140, "px": 280, "source": "feedback-2026-11-06: preserve taller episode cards"}, "actionMenuWidth": {"dp": 260, "px": 520, "source": "tv-round2: compact title action menu"}, "seriesHeaderGap": {"dp": 20, "px": 40, "source": "feedback-2026-11-06: measured series header to seasons"}, + "posterCastGap": {"dp": 10, "px": 20, "source": "tv-round2: minimum poster-to-cast clearance"}, "lineGap": {"dp": 11, "px": 22, "source": "index.html:214"}, "lineLift": {"dp": -2, "px": -4, "source": "index.html:214"}, "overviewGap": {"dp": 17, "px": 34, "source": "index.html:216"}, diff --git a/wolfskin-design/tokens.css b/wolfskin-design/tokens.css index 8ca184ac..8967d79f 100644 --- a/wolfskin-design/tokens.css +++ b/wolfskin-design/tokens.css @@ -291,9 +291,10 @@ --lift-sheetBlur: 80.0px; --lift-sheetX: -30.0px; --title-episodeCardWidth: 448.0px; - --title-episodeCardHeight: 252.0px; + --title-episodeCardHeight: 280.0px; --title-actionMenuWidth: 520.0px; --title-seriesHeaderGap: 40.0px; + --title-posterCastGap: 20.0px; --title-lineGap: 22.0px; --title-lineLift: -4.0px; --title-overviewGap: 34.0px; diff --git a/wolfskin-design/tokens.json b/wolfskin-design/tokens.json index d7db186e..ea56e6d1 100644 --- a/wolfskin-design/tokens.json +++ b/wolfskin-design/tokens.json @@ -1543,9 +1543,9 @@ "source": "feedback-2026-11-06: largest upright hero poster slot" }, "episodeRequest": { - "px": [400, 280], + "px": [448, 280], "decode": "ARGB_8888", - "source": "feedback-2026-11-06: taller episode cards" + "source": "tv-round2: wider episode cards at their preserved height" }, "castRequest": { "px": [ diff --git a/wolfskin-design/tokens.sha256 b/wolfskin-design/tokens.sha256 index 3ef0cd19..bd2e8257 100644 --- a/wolfskin-design/tokens.sha256 +++ b/wolfskin-design/tokens.sha256 @@ -2,7 +2,7 @@ b3f096b692c395534177cc82ac68f5b801870bc7e28f0dd5cd7c17e2103920a3 discover-token c29dc64f3c3ca900c747b3db8b270e25908948bf5f76388d2c627a612fc7c99d generate_tokens.py eef4e9f8c91306362540eda617c9efad4e19ed688f205f6f486625a5918d8105 home-tokens.json 192beb887fc34005db99c87ffbcbaf4a057ee2728475fc96224cf89445019b51 shell-tokens.json -12420580fed6e6977c8762fb0649f0ed22ca6a8df32d65ea69b3965cd851bb65 src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt -98054296d1de4df2f9f4808d505e512d5906f5f23f7a05e6d846391d93effa5e title-tokens.json -40d763d9023abb56c197201a6a13d3fefacb681713010f849d450c96216e37cb tokens.css -ba0da02b03047fbc2f29d538d980e87aa237f8ae36545aa4234600243fe14929 tokens.json +0d69fccfbfada103268bfc38186205cf5f94daeb345a00a6aec585609e7ddb1e src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt +98fa6414cc6663624d09329615cdf0e6599baec570a8d878f5214c95cb33cb48 title-tokens.json +a68f336e8b4373e97a7acaeb02383b4a40dc9f7cc6f6e5413341f14fb2d308eb tokens.css +b1cf8f8caea9bfacb7994e0ba39e71ffab33452f6f5227a524ba71874b045b4d tokens.json From 152dac97c07e04870138455e6c060eb469327313 Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 16:01:45 +0100 Subject: [PATCH 06/18] Define the shared TV update controller contract --- .../tv/update/FakeUpdateController.kt | 30 ++++++++++++ .../wolfskin/tv/update/UpdateController.kt | 47 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/FakeUpdateController.kt create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/FakeUpdateController.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/FakeUpdateController.kt new file mode 100644 index 00000000..3976489b --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/FakeUpdateController.kt @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +/** Deterministic capture/test controller; no network, storage or Android hand-off. */ +class FakeUpdateController( + initialState: UpdateUiState = UpdateUiState.Idle, + initialAutoCheck: Boolean = true, + initialVersion: InstalledVersion = InstalledVersion("1.1.1", 100001), +) : UpdateController { + private val mutableState = MutableStateFlow(initialState) + private val mutableAutoCheck = MutableStateFlow(initialAutoCheck) + private val mutableVersion = MutableStateFlow(initialVersion) + override val state = mutableState.asStateFlow() + override val autoCheck = mutableAutoCheck.asStateFlow() + override val installedVersion = mutableVersion.asStateFlow() + val actions = mutableListOf() + + fun show(state: UpdateUiState) { mutableState.value = state } + fun showInstalled(version: InstalledVersion) { mutableVersion.value = version } + override fun check(manual: Boolean) { actions += "check:$manual" } + override fun download() { actions += "download" } + override fun cancel() { actions += "cancel" } + override fun install() { actions += "install" } + override fun retry() { actions += "retry" } + override fun onResume() { actions += "resume" } + override fun setAutoCheck(enabled: Boolean) { mutableAutoCheck.value = enabled } +} diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt new file mode 100644 index 00000000..c7faa29e --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import kotlinx.coroutines.flow.StateFlow + +/** Shared process-scoped updater for Wolfskin and classic settings. */ +interface UpdateController { + val state: StateFlow + val autoCheck: StateFlow + val installedVersion: StateFlow + + fun check(manual: Boolean) + fun download() + fun cancel() + fun install() + fun retry() + fun setAutoCheck(enabled: Boolean) + + /** Refresh installed identity and unknown-source permission after Android returns. */ + fun onResume() +} + +/** PackageManager identity, refreshed after returning from the system installer. */ +data class InstalledVersion(val versionName: String, val versionCode: Long) + +/** Only verified, app-private bytes may produce Ready. Checking never initiates download. */ +sealed interface UpdateUiState { + data object Idle : UpdateUiState + data object Checking : UpdateUiState + data object UpToDate : UpdateUiState + data object NoReleasePublished : UpdateUiState + data class Available(val versionName: String, val bytes: Long, val dateText: String, val notes: String) : UpdateUiState + data class Downloading(val bytesDone: Long, val bytesTotal: Long?) : UpdateUiState + data class Ready(val versionName: String) : UpdateUiState + data object PermissionNeeded : UpdateUiState + data object HandingOff : UpdateUiState + data object InstallCancelled : UpdateUiState + data class Failed(val kind: UpdateFailure, val message: String) : UpdateUiState + data object Offline : UpdateUiState + data object NoInstaller : UpdateUiState +} + +/** Failures are distinct from a successful version comparison or an empty channel. */ +enum class UpdateFailure { + Network, HttpRefused, InvalidMetadata, UnsupportedAbi, InsufficientStorage, + ChecksumMismatch, WrongPackage, WrongSigner, LowerVersionCode, +} From 7a0cbdf909beb6eecb5d5e68d380b784102d3a16 Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 16:14:58 +0100 Subject: [PATCH 07/18] Retain candidate metadata across updater states --- .../wolfskin/tv/update/FakeUpdateController.kt | 8 +++++++- .../justinvisser/wolfskin/tv/update/UpdateController.kt | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/FakeUpdateController.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/FakeUpdateController.kt index 3976489b..ebac04ed 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/FakeUpdateController.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/FakeUpdateController.kt @@ -9,16 +9,22 @@ class FakeUpdateController( initialState: UpdateUiState = UpdateUiState.Idle, initialAutoCheck: Boolean = true, initialVersion: InstalledVersion = InstalledVersion("1.1.1", 100001), + initialRelease: UpdateUiState.Available? = initialState as? UpdateUiState.Available, ) : UpdateController { private val mutableState = MutableStateFlow(initialState) private val mutableAutoCheck = MutableStateFlow(initialAutoCheck) private val mutableVersion = MutableStateFlow(initialVersion) + private val mutableRelease = MutableStateFlow(initialRelease) override val state = mutableState.asStateFlow() override val autoCheck = mutableAutoCheck.asStateFlow() override val installedVersion = mutableVersion.asStateFlow() + override val release = mutableRelease.asStateFlow() val actions = mutableListOf() - fun show(state: UpdateUiState) { mutableState.value = state } + fun show(state: UpdateUiState) { + if (state is UpdateUiState.Available) mutableRelease.value = state + mutableState.value = state + } fun showInstalled(version: InstalledVersion) { mutableVersion.value = version } override fun check(manual: Boolean) { actions += "check:$manual" } override fun download() { actions += "download" } diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt index c7faa29e..ee7982d9 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt @@ -8,6 +8,8 @@ interface UpdateController { val state: StateFlow val autoCheck: StateFlow val installedVersion: StateFlow + /** Candidate facts survive download/installer transitions and verified-file restoration. */ + val release: StateFlow fun check(manual: Boolean) fun download() From 19df50c0f1ed299faf80976668d347d655b0d121 Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 16:27:55 +0100 Subject: [PATCH 08/18] Build the approved television Updates screen --- .../wolfskin/tv/AnimeAvailabilityTest.kt | 2 +- .../wolfskin/tv/AnimeRootRemovalTest.kt | 2 +- .../tv/ConductarrAudienceRecoveryTest.kt | 4 +- .../wolfskin/tv/FirstSignInNavigationTest.kt | 2 +- .../wolfskin/tv/PersonPickerSessionTest.kt | 2 +- .../wolfskin/tv/PersonSwitchThreadingTest.kt | 4 +- .../wolfskin/tv/SavedPeoplePickerTest.kt | 2 +- .../wolfskin/tv/ShellStartupTimingTest.kt | 4 +- .../wolfskin/tv/UpdateBehaviorTest.kt | 102 ++++++++++ .../wolfskin/tv/UpdatesCaptureTest.kt | 171 +++++++++++++++++ .../justinvisser/wolfskin/tv/WolfskinApp.kt | 8 +- .../wolfskin/tv/update/UpdateController.kt | 1 + .../wolfskin/tv/update/UpdateFocus.kt | 80 ++++++++ .../wolfskin/tv/update/UpdatePresentation.kt | 83 ++++++++ .../wolfskin/tv/update/UpdateProgress.kt | 58 ++++++ .../wolfskin/tv/update/UpdatesScreen.kt | 179 ++++++++++++++++++ wolfskin-design/generate_tokens.py | 3 +- .../wolfskin/design/CssLineBox.kt | 2 +- .../justinvisser/wolfskin/design/Identity.kt | 6 +- .../justinvisser/wolfskin/design/NavBar.kt | 14 +- .../wolfskin/design/SettingsList.kt | 72 +++---- .../wolfskin/design/ShellState.kt | 11 +- .../wolfskin/design/ShellSurface.kt | 3 +- .../wolfskin/design/UpdateTypography.kt | 23 +++ .../wolfskin/design/WolfskinTokens.kt | 37 ++++ .../res/drawable/wolfskin_settings_list.xml | 3 + .../src/main/res/drawable/wolfskin_update.xml | 3 + .../src/main/res/font/update_dejavu_sans.ttf | Bin 0 -> 759720 bytes .../main/res/font/update_dejavu_sans_bold.ttf | Bin 0 -> 708920 bytes .../src/main/res/raw/update_font_license.txt | 47 +++++ .../wolfskin/design/ShellKeysTest.kt | 6 +- wolfskin-design/tokens.css | 31 +++ wolfskin-design/tokens.json | 3 + wolfskin-design/tokens.sha256 | 9 +- wolfskin-design/update-tokens.json | 161 ++++++++++++++++ 35 files changed, 1069 insertions(+), 69 deletions(-) create mode 100644 app/src/test/java/org/justinvisser/wolfskin/tv/UpdateBehaviorTest.kt create mode 100644 app/src/test/java/org/justinvisser/wolfskin/tv/UpdatesCaptureTest.kt create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateFocus.kt create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatePresentation.kt create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateProgress.kt create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt create mode 100644 wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/UpdateTypography.kt create mode 100644 wolfskin-design/src/main/res/drawable/wolfskin_settings_list.xml create mode 100644 wolfskin-design/src/main/res/drawable/wolfskin_update.xml create mode 100644 wolfskin-design/src/main/res/font/update_dejavu_sans.ttf create mode 100644 wolfskin-design/src/main/res/font/update_dejavu_sans_bold.ttf create mode 100644 wolfskin-design/src/main/res/raw/update_font_license.txt create mode 100644 wolfskin-design/update-tokens.json diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/AnimeAvailabilityTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/AnimeAvailabilityTest.kt index 35e45892..ad3d4647 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/AnimeAvailabilityTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/AnimeAvailabilityTest.kt @@ -88,7 +88,7 @@ class AnimeAvailabilityTest { } } val model = WolfskinShellViewModel(context, session, mockk(), mockk(), mockk(), mockk(relaxed = true), - libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true)) + libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true), org.justinvisser.wolfskin.tv.update.FakeUpdateController()) try { requireNotNull(model.onForeground(server, user)).join() assertEquals("$key with $count Anime titles", count > 0, "anime" in session.state!!.tabs) diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/AnimeRootRemovalTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/AnimeRootRemovalTest.kt index 1af82b5c..125a67bd 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/AnimeRootRemovalTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/AnimeRootRemovalTest.kt @@ -69,7 +69,7 @@ class AnimeRootRemovalTest { val navigation = NavigationManager() val session = WolfskinSession() val model = WolfskinShellViewModel(context, session, repository, navigation, mockk(), mockk(relaxed = true), - libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true)) + libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true), org.justinvisser.wolfskin.tv.update.FakeUpdateController()) try { model.load(server, user) requireNotNull(model.onForeground(server, user)).join() diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/ConductarrAudienceRecoveryTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/ConductarrAudienceRecoveryTest.kt index b748367e..052aa05c 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/ConductarrAudienceRecoveryTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/ConductarrAudienceRecoveryTest.kt @@ -49,7 +49,7 @@ class ConductarrAudienceRecoveryTest { val client = session.identity.value!!.client val libraries = LibraryReadFacade(mockk()) val model = WolfskinShellViewModel(context, WolfskinSession(), mockk(), mockk(), mockk(), mockk(relaxed = true), - libraries, WolfskinSeeAllLists(), session, mockk(relaxed = true)) + libraries, WolfskinSeeAllLists(), session, mockk(relaxed = true), org.justinvisser.wolfskin.tv.update.FakeUpdateController()) try { requireNotNull(model.onForeground(server, user)).join() assertNull(libraries.audiences) @@ -82,7 +82,7 @@ class ConductarrAudienceRecoveryTest { session.authenticate() val libraries = LibraryReadFacade(mockk()) val model = WolfskinShellViewModel(context, WolfskinSession(), mockk(), mockk(), mockk(), mockk(relaxed = true), - libraries, WolfskinSeeAllLists(), session, mockk(relaxed = true)) + libraries, WolfskinSeeAllLists(), session, mockk(relaxed = true), org.justinvisser.wolfskin.tv.update.FakeUpdateController()) try { val identity = session.identity.value!! val intent = org.justinvisser.wolfskin.design.DiscoverRequest( diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/FirstSignInNavigationTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/FirstSignInNavigationTest.kt index 07cd1e37..c412265e 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/FirstSignInNavigationTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/FirstSignInNavigationTest.kt @@ -91,7 +91,7 @@ class FirstSignInNavigationTest { val navigation = NavigationManager() val session = WolfskinSession() val model = WolfskinShellViewModel(rule.activity, session, repository, navigation, mockk(relaxed = true), mockk(relaxed = true), - LibraryReadFacade(api), WolfskinSeeAllLists(), conductarr, mockk(relaxed = true)) + LibraryReadFacade(api), WolfskinSeeAllLists(), conductarr, mockk(relaxed = true), org.justinvisser.wolfskin.tv.update.FakeUpdateController()) val home = HomeSnapshot(listOf(HomeRow("resume", HomeRowKind.Hero, cards = listOf( HomeTitle("episode", "Me and My Town", "episode", seriesTitle = "Desperate Housewives", season = 5, episode = 9)), heroKind = "resume"))) try { diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/PersonPickerSessionTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/PersonPickerSessionTest.kt index 95fcbb52..35c5cb57 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/PersonPickerSessionTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/PersonPickerSessionTest.kt @@ -85,7 +85,7 @@ class PersonPickerSessionTest { val navigation = remember { NavigationManager() } val model = remember { WolfskinShellViewModel(rule.activity, session, repository, navigation, setup, mockk(relaxed = true), - libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true)).also { models.add(it) } + libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true), org.justinvisser.wolfskin.tv.update.FakeUpdateController()).also { models.add(it) } } DisposableEffect(model) { onDispose { model.viewModelScope.cancel() } } WolfskinApp(server, current.user, navigation, UserPreferences(AppPreferences.getDefaultInstance(), null), diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/PersonSwitchThreadingTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/PersonSwitchThreadingTest.kt index 6a5936f8..9a1ff11e 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/PersonSwitchThreadingTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/PersonSwitchThreadingTest.kt @@ -87,7 +87,7 @@ class PersonSwitchThreadingTest { coEvery { libraries.readDestinations(any()) } returns emptyMap() val session = WolfskinSession() val model = WolfskinShellViewModel(context, session, repository, mockk(relaxed = true), setup, mockk(relaxed = true), - libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true)) + libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true), org.justinvisser.wolfskin.tv.update.FakeUpdateController()) val clients = mutableListOf() try { model.load(server, justin) @@ -163,7 +163,7 @@ class PersonSwitchThreadingTest { coEvery { libraries.readDestinations(any()) } returns emptyMap() val session = WolfskinSession() val model = WolfskinShellViewModel(context, session, repository, mockk(relaxed = true), setup, mockk(relaxed = true), - libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true)) + libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true), org.justinvisser.wolfskin.tv.update.FakeUpdateController()) try { model.load(server, justin) requireNotNull(model.onForeground(server, justin)).join() diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/SavedPeoplePickerTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/SavedPeoplePickerTest.kt index 1fb29d31..01a2e425 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/SavedPeoplePickerTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/SavedPeoplePickerTest.kt @@ -63,7 +63,7 @@ class SavedPeoplePickerTest { val session = WolfskinSession() val navigation = NavigationManager() val model = WolfskinShellViewModel(rule.activity, session, repository, navigation, mockk(relaxed = true), - mockk(relaxed = true), libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true)) + mockk(relaxed = true), libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true), org.justinvisser.wolfskin.tv.update.FakeUpdateController()) try { rule.setContent { WolfskinApp(server, users.first(), navigation, UserPreferences(AppPreferences.getDefaultInstance(), null), diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/ShellStartupTimingTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/ShellStartupTimingTest.kt index dbcffdb4..8a01861d 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/ShellStartupTimingTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/ShellStartupTimingTest.kt @@ -66,7 +66,7 @@ class ShellStartupTimingTest { coEvery { libraries.readDestinations(user.id) } returns emptyMap() val session = WolfskinSession() val model = WolfskinShellViewModel(context, session, repository, navigation, mockk(), mockk(relaxed = true), - libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true)) + libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true), org.justinvisser.wolfskin.tv.update.FakeUpdateController()) val load = launch { model.load(server, user) } try { withTimeout(5_000) { savedPeopleStarted.await() } @@ -121,7 +121,7 @@ class ShellStartupTimingTest { coEvery { libraries.readDestinations(any()) } returns emptyMap() val session = WolfskinSession() val model = WolfskinShellViewModel(context, session, repository, navigation, mockk(relaxed = true), mockk(relaxed = true), - libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true)) + libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true), org.justinvisser.wolfskin.tv.update.FakeUpdateController()) val pending = CompletableDeferred() val release = java.util.concurrent.CountDownLatch(1) val firstAudience = java.util.concurrent.atomic.AtomicBoolean(true) diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/UpdateBehaviorTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/UpdateBehaviorTest.kt new file mode 100644 index 00000000..72c07539 --- /dev/null +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/UpdateBehaviorTest.kt @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv + +import org.junit.Assert.* +import org.junit.Test +import org.justinvisser.wolfskin.design.ShellKey +import org.justinvisser.wolfskin.tv.update.* + +/** Behavior boundaries are controller outcomes, not incidental UI wording. */ +class UpdateBehaviorTest { + @Test fun everyOutcomeHasOnlyExplicitUserActions() { + val expected = listOf( + UpdateUiState.Idle to listOf(UpdateCommand.Check), + UpdateUiState.Checking to listOf(UpdateCommand.Back), + UpdateUiState.UpToDate to listOf(UpdateCommand.Check), + UpdateUiState.NoReleasePublished to listOf(UpdateCommand.Check), + updateReleaseFixture() to listOf(UpdateCommand.Download, UpdateCommand.Notes), + UpdateUiState.Downloading(12, 30) to listOf(UpdateCommand.Cancel), + UpdateUiState.Ready("1.1.1") to listOf(UpdateCommand.Install, UpdateCommand.Notes), + UpdateUiState.PermissionNeeded to listOf(UpdateCommand.Install, UpdateCommand.Cancel), + UpdateUiState.HandingOff to listOf(UpdateCommand.Cancel), + UpdateUiState.InstallCancelled to listOf(UpdateCommand.Install, UpdateCommand.Notes), + UpdateUiState.Offline to listOf(UpdateCommand.Retry), + UpdateUiState.NoInstaller to listOf(UpdateCommand.Retry, UpdateCommand.Classic), + ) + UpdateFailure.entries.map { UpdateUiState.Failed(it, "operation failed") to listOf(UpdateCommand.Retry, UpdateCommand.Back) } + expected.forEach { (state, commands) -> + assertEquals(state.toString(), commands, presentUpdate(state, updateReleaseFixture()).actions.map { it.command }) + } + assertNotEquals(presentUpdate(UpdateUiState.UpToDate, null), presentUpdate(UpdateUiState.NoReleasePublished, null)) + } + + @Test fun percentageRequiresPositiveTotalAndIsBounded() { + listOf(null, 0L, -1L).forEach { total -> + val ui = presentUpdate(UpdateUiState.Downloading(20_100_000, total), updateReleaseFixture()) + assertNull(ui.fraction) + assertTrue(ui.title.isEmpty()) + assertNotNull(ui.byteProgress) + } + assertEquals(.42f, presentUpdate(UpdateUiState.Downloading(20_076_000, 47_800_000), null).fraction!!, .0001f) + assertEquals(1f, presentUpdate(UpdateUiState.Downloading(90, 30), null).fraction!!, 0f) + } + + @Test fun actionsAndAutoCheckRememberFocusWithoutTogglingOnMovement() { + val controller = FakeUpdateController(updateReleaseFixture()) + val focus = UpdateFocus(controller, {}, {}, {}, {}) + focus.update(controller.state.value, presentUpdate(controller.state.value, controller.release.value).actions) + focus.key(ShellKey.Right) + focus.key(ShellKey.Down) + assertTrue(focus.autoFocused) + assertTrue(controller.autoCheck.value) + focus.key(ShellKey.Ok) + assertFalse(controller.autoCheck.value) + focus.key(ShellKey.Up) + assertFalse(focus.autoFocused) + assertEquals(1, focus.actionIndex) + assertFalse(controller.autoCheck.value) + } + + @Test fun notesTrapFocusAndBackRestoresNotesAction() { + val controller = FakeUpdateController(updateReleaseFixture()) + var backs = 0 + var navs = 0 + val steps = mutableListOf() + val focus = UpdateFocus(controller, { backs++ }, {}, { navs++ }, steps::add) + focus.update(controller.state.value, presentUpdate(controller.state.value, controller.release.value).actions) + focus.key(ShellKey.Right); focus.key(ShellKey.Ok) + listOf(ShellKey.Up, ShellKey.Down, ShellKey.Left, ShellKey.Right, ShellKey.Ok).forEach(focus::key) + assertTrue(focus.notesOpen) + assertEquals(listOf(-1, 1), steps) + assertEquals(0, navs) + assertTrue(controller.autoCheck.value) + focus.key(ShellKey.Back) + assertFalse(focus.notesOpen) + assertEquals(1, focus.actionIndex) + assertEquals(0, backs) + focus.key(ShellKey.Up) + assertEquals(1, navs) + focus.key(ShellKey.Back) + assertEquals(1, backs) + } + + @Test fun progressUpdatesCannotStealFocusAndInstallerCancellationRestoresInstall() { + val controller = FakeUpdateController(UpdateUiState.Downloading(1, 100)) + val focus = UpdateFocus(controller, {}, {}, {}, {}) + fun update(state: UpdateUiState) { focus.update(state, presentUpdate(state, null).actions) } + update(controller.state.value) + focus.key(ShellKey.Down) + update(UpdateUiState.Downloading(90, 100)) + assertTrue(focus.autoFocused) + update(UpdateUiState.Ready("1.1.1")) + assertFalse(focus.autoFocused) + focus.key(ShellKey.Right) + update(UpdateUiState.PermissionNeeded) + update(UpdateUiState.InstallCancelled) + assertEquals(0, focus.actionIndex) + assertFalse(focus.autoFocused) + } +} + +/** Same release facts as the approved television frames. */ +fun updateReleaseFixture() = UpdateUiState.Available("1.1.1", 47_800_000, "6 Nov 2026", + "Updates inside Wolfskin settings.\nKeep sign-ins and preferences.\nClassic settings remains for a trial.") diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/UpdatesCaptureTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/UpdatesCaptureTest.kt new file mode 100644 index 00000000..e6643fd7 --- /dev/null +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/UpdatesCaptureTest.kt @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv + +import android.app.Application +import android.view.View +import android.view.WindowManager +import androidx.activity.ComponentActivity +import androidx.compose.foundation.layout.requiredSize +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.mutableStateOf +import androidx.compose.ui.Modifier +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.onRoot +import androidx.compose.ui.test.performKeyInput +import androidx.compose.ui.test.pressKey +import androidx.compose.ui.input.key.Key +import androidx.compose.ui.semantics.SemanticsProperties +import com.github.takahirom.roborazzi.captureRoboImage +import java.io.File +import org.junit.Assert.* +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.justinvisser.wolfskin.design.* +import org.justinvisser.wolfskin.tv.update.* +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +/** Native TV frames use the real shell, updater controller seam and Android key adapter. */ +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [34], application = Application::class, qualifiers = "w960dp-h540dp-xhdpi") +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class UpdatesCaptureTest { + @get:Rule val rule = createAndroidComposeRule() + private val shell = ShellState(listOf(ShellPerson("justin", "Justin", "J", true)), "justin").apply { + pickerVisible = false + enterDestination("updates") + settingsRow = 1 + } + private lateinit var controller: FakeUpdateController + private val reduced = mutableStateOf(false) + private val directory get() = System.getProperty("wolfskin.updater.captureDirectory")?.let(::File) + + @Before fun fullscreen() { + rule.activity.window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN) + @Suppress("DEPRECATION") + rule.activity.window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + rule.mainClock.autoAdvance = false + } + + private fun launch(state: UpdateUiState, auto: Boolean = true, settings: Boolean = false) { + controller = FakeUpdateController(state, auto, InstalledVersion("1.1.0-140-g5162c299", 100000), state as? UpdateUiState.Available ?: updateReleaseFixture()) + if (settings) shell.enterDestination("settings") + rule.setContent { + CompositionLocalProvider(LocalReducedMotion provides reduced.value) { + WolfskinTheme { + ShellSurface(shell, Modifier.requiredSize(WolfskinTokens.Shell.stageWidth, WolfskinTokens.Shell.stageHeight), + settingsInstalledVersion = controller.installedVersion.value.versionName) { modifier -> + UpdatesScreen(shell, controller, { shell.navFocused = false; shell.enterDestination("settings") }, {}, modifier) + } + } + } + } + rule.mainClock.advanceTimeBy(1000) + rule.waitForIdle() + } + + private fun capture(name: String) { + val target = directory ?: return + target.mkdirs() + rule.waitForIdle() + val file = File(target, "$name.png") + file.parentFile?.mkdirs() + rule.onRoot().captureRoboImage(file.absolutePath) + } + + private fun press(vararg keys: Key) { + keys.forEach { key -> rule.onNodeWithTag("wolfskin-shell").performKeyInput { pressKey(key) } } + rule.mainClock.advanceTimeBy(320) + rule.waitForIdle() + } + + @Test fun settings() { launch(UpdateUiState.Checking, settings = true); capture("settings") } + @Test fun classic() { + launch(UpdateUiState.Checking, settings = true) + repeat(8) { press(Key.DirectionDown) } + assertEquals(9, shell.settingsRow) + assertEquals(4, shell.view.listState.firstVisibleItemIndex) + capture("classic") + } + @Test fun checking() { launch(UpdateUiState.Checking); capture("checking") } + @Test fun current() { launch(UpdateUiState.UpToDate); capture("current") } + @Test fun available() { launch(updateReleaseFixture()); capture("available") } + @Test fun notes() { launch(updateReleaseFixture()); press(Key.DirectionRight); capture("notes") } + @Test fun notesOpen() { launch(updateReleaseFixture()); press(Key.DirectionRight, Key.DirectionCenter); capture("notes-open") } + @Test fun downloading() { launch(UpdateUiState.Downloading(20_100_000, 47_800_000)); capture("downloading") } + @Test fun ready() { launch(UpdateUiState.Ready("1.1.1")); capture("ready") } + @Test fun permission() { launch(UpdateUiState.PermissionNeeded); capture("permission") } + @Test fun handoff() { launch(UpdateUiState.HandingOff); capture("handoff") } + @Test fun cancelled() { launch(UpdateUiState.InstallCancelled); capture("cancelled") } + @Test fun failed() { launch(UpdateUiState.Failed(UpdateFailure.HttpRefused, "The download server refused the request (403).")); capture("failed") } + @Test fun offline() { launch(UpdateUiState.Offline); capture("offline") } + @Test fun noInstaller() { launch(UpdateUiState.NoInstaller); capture("no-installer") } + @Test fun noReleasePublished() { launch(UpdateUiState.NoReleasePublished); capture("no-release") } + @Test fun unknownDownloadLength() { launch(UpdateUiState.Downloading(20_100_000, null)); capture("unknown-total") } + @Test fun autoOn() { launch(updateReleaseFixture()); press(Key.DirectionDown); capture("auto-on") } + @Test fun autoOff() { launch(updateReleaseFixture()); press(Key.DirectionDown, Key.DirectionCenter); capture("auto-off") } + @Test fun updated() { + launch(UpdateUiState.UpToDate) + rule.runOnIdle { controller.showInstalled(InstalledVersion("1.1.1", 100001)) } + rule.mainClock.advanceTimeBy(320) + capture("updated") + } + + @Test fun notesTrapRealKeysAndBackPreservesSettingsRowAndScroller() { + launch(updateReleaseFixture()) + press(Key.DirectionRight, Key.DirectionCenter, Key.DirectionUp, Key.DirectionRight, Key.DirectionDown) + assertTrue(shell.contentOverlayVisible) + assertFalse(shell.navFocused) + assertTrue(controller.autoCheck.value) + press(Key.Back) + assertFalse(shell.contentOverlayVisible) + assertEquals(1, (shell.contentFocus as UpdateFocus).actionIndex) + press(Key.Back) + assertEquals("settings", shell.route) + assertEquals(1, shell.settingsRow) + assertEquals(0, shell.view.listState.firstVisibleItemIndex) + } + + @Test fun longNotesScrollWithoutEscapingToNavOrAutoCheck() { + launch(updateReleaseFixture().copy(notes = (1..30).joinToString("\n") { "Release detail $it" })) + press(Key.DirectionRight, Key.DirectionCenter, Key.DirectionDown, Key.DirectionDown) + val range = rule.onNodeWithTag("update-notes").fetchSemanticsNode().config[SemanticsProperties.VerticalScrollAxisRange] + assertTrue(range.value() > 0f) + assertFalse(shell.navFocused) + assertFalse((shell.contentFocus as UpdateFocus).autoFocused) + press(Key.Back) + assertEquals(1, (shell.contentFocus as UpdateFocus).actionIndex) + } + + @Test fun nativeProgressAndStateTransitionAtSixteenMillisecondFrames() { + launch(UpdateUiState.Checking) + val target = directory + if (target != null) { + repeat(113) { frame -> + rule.mainClock.advanceTimeBy(16) + capture("motion/checking-%03d".format(frame)) + } + } + rule.runOnIdle { controller.show(UpdateUiState.Downloading(20_100_000, 47_800_000)) } + rule.mainClock.advanceTimeByFrame() + repeat(24) { frame -> rule.mainClock.advanceTimeBy(16); capture("motion/state-%03d".format(frame)) } + assertEquals(12f, rule.onNodeWithTag("update-progress").fetchSemanticsNode().boundsInRoot.height, .01f) + if (target != null) { + repeat(101) { frame -> rule.mainClock.advanceTimeBy(16); capture("motion/download-%03d".format(frame)) } + } + press(Key.DirectionDown) + rule.runOnIdle { controller.show(UpdateUiState.Downloading(31_000_000, 47_800_000)) } + rule.mainClock.advanceTimeBy(16) + assertTrue((shell.contentFocus as UpdateFocus).autoFocused) + rule.runOnIdle { reduced.value = true } + rule.mainClock.advanceTimeBy(96) + capture("motion/reduced-000") + rule.mainClock.advanceTimeBy(1600) + capture("motion/reduced-100") + assertTrue((shell.contentFocus as UpdateFocus).autoFocused) + } +} diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/WolfskinApp.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/WolfskinApp.kt index aed8ec7b..a1d5c5e7 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/WolfskinApp.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/WolfskinApp.kt @@ -80,6 +80,7 @@ class WolfskinShellViewModel @Inject constructor( val seeAll: WolfskinSeeAllLists, val conductarr: ConductarrSession, artwork: WolfskinArtwork, + val updates: org.justinvisser.wolfskin.tv.update.UpdateController, ) : ViewModel() { init { artwork.configure(context) } val backdropFlow: StateFlow = backdrop.backdropFlow @@ -195,7 +196,7 @@ class WolfskinShellViewModel @Inject constructor( is ShellAction.Destination -> { val target = if (action.route == "home") Destination.Home() else Destination.Wolfskin(action.route) when { - action.route == "settings" -> navigation.navigateTo(target) + action.route == "settings" || action.route == "updates" -> navigation.navigateTo(target) action.preservePushed && navigation.backStack.size > 1 -> navigation.backStack[0] = target else -> navigation.replace(target) } @@ -262,6 +263,7 @@ fun WolfskinApp( { shell, homeServer, homeUser, contentModifier -> HomeDestination(shell, homeServer, homeUser, contentModifier) }, ) { val identity by viewModel.conductarr.identity.collectAsStateWithLifecycle() + val installedVersion by viewModel.updates.installedVersion.collectAsStateWithLifecycle() LaunchedEffect(server.id, user.id, user.accessToken, ConductarrPreference.baseUrl, ConductarrPreference.fixtures) { viewModel.load(server, user) } androidx.lifecycle.compose.LifecycleEventEffect(androidx.lifecycle.Lifecycle.Event.ON_RESUME) { viewModel.onForeground(server, user) } LaunchedEffect(identity?.signedIn, identity?.person) { @@ -329,11 +331,15 @@ fun WolfskinApp( } else TitleDestination(route, state, preferences) } else { ShellSurface(state, handlesContentKeys = upstream == null, + settingsInstalledVersion = installedVersion.versionName, overlay = { if (route == "discover" || route.startsWith("discover-")) DiscoverOverlay(discover) }) { contentModifier -> when { (upstream != null || destination is Destination.Home || route in LIBRARY_DESTINATIONS) && state.person.key != viewModel.signedInPerson -> ShellPlaceholder("Sign in as ${state.person.name} to open their Jellyfin library", contentModifier) upstream != null -> DestinationContent(upstream, preferences, viewModel::clearBackdrop, contentModifier) destination is Destination.Home -> homeContent(state, server, user, contentModifier) + route == "updates" -> org.justinvisser.wolfskin.tv.update.UpdatesScreen(state, viewModel.updates, + onBack = { state.navFocused = false; navigationManager.goBack() }, + onClassic = { navigationManager.navigateTo(handOffDestination("classic")) }, modifier = contentModifier) route in LIBRARY_DESTINATIONS || route.startsWith("seeall/") -> WolfskinLibraryContent(androidx.compose.ui.platform.LocalContext.current, route, state, user, "${server.id}:${user.id}", viewModel.libraries, navigationManager, viewModel.seeAll, contentModifier) destination is Destination.Wolfskin -> DestinationContent(destination, preferences, viewModel::clearBackdrop, contentModifier) diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt index ee7982d9..f7913df2 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt @@ -13,6 +13,7 @@ interface UpdateController { fun check(manual: Boolean) fun download() + /** Cancel partial bytes, or dismiss permission/handoff while retaining a verified APK. */ fun cancel() fun install() fun retry() diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateFocus.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateFocus.kt new file mode 100644 index 00000000..67d22cd2 --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateFocus.kt @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import org.justinvisser.wolfskin.design.ShellContentFocus +import org.justinvisser.wolfskin.design.ShellKey + +/** Action focus survives progress emissions; release notes own every key until Back. */ +class UpdateFocus( + private val controller: UpdateController, + private val back: () -> Unit, + private val classic: () -> Unit, + private val nav: () -> Unit, + private val scrollNotes: (Int) -> Unit, +) : ShellContentFocus { + override val cardKey: String? = null + var actionIndex by mutableIntStateOf(0) + private set + var autoFocused by mutableStateOf(false) + private set + var notesOpen by mutableStateOf(false) + private set + private var actions = emptyList() + private var previousState: Class<*>? = null + + /** Only a changed operation may retire an action; progress cannot steal focus. */ + fun update(state: UpdateUiState, value: List) { + if (previousState != state.javaClass) { + actionIndex = 0 + notesOpen = false + if (state == UpdateUiState.InstallCancelled || state is UpdateUiState.Ready) autoFocused = false + } + previousState = state.javaClass + actions = value + actionIndex = actionIndex.coerceAtMost(actions.lastIndex.coerceAtLeast(0)) + } + + fun focusAction(index: Int) { actionIndex = index; autoFocused = false } + fun focusAuto() { autoFocused = true } + + fun activate(index: Int) { + focusAction(index) + when (actions[index].command) { + UpdateCommand.Back -> back() + UpdateCommand.Check -> controller.check(manual = true) + UpdateCommand.Download -> controller.download() + UpdateCommand.Notes -> notesOpen = true + UpdateCommand.Cancel -> controller.cancel() + UpdateCommand.Install -> controller.install() + UpdateCommand.Retry -> controller.retry() + UpdateCommand.Classic -> classic() + } + } + + fun toggleAuto() { autoFocused = true; controller.setAutoCheck(!controller.autoCheck.value) } + + override fun key(key: ShellKey): Boolean { + if (notesOpen) { + when (key) { + ShellKey.Back -> notesOpen = false + ShellKey.Up -> scrollNotes(-1) + ShellKey.Down -> scrollNotes(1) + else -> Unit + } + return true + } + when (key) { + ShellKey.Back -> back() + ShellKey.Up -> if (autoFocused) autoFocused = false else nav() + ShellKey.Down -> autoFocused = true + ShellKey.Left -> if (!autoFocused) actionIndex = (actionIndex - 1).coerceAtLeast(0) + ShellKey.Right -> if (!autoFocused) actionIndex = (actionIndex + 1).coerceAtMost(actions.lastIndex.coerceAtLeast(0)) + ShellKey.Ok -> if (autoFocused) toggleAuto() else if (actions.isNotEmpty()) activate(actionIndex) + } + return true + } +} diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatePresentation.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatePresentation.kt new file mode 100644 index 00000000..3bc8c628 --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatePresentation.kt @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import java.text.NumberFormat + +/** Screen commands remain explicit; no state transition implicitly installs an APK. */ +enum class UpdateCommand { Back, Check, Download, Notes, Cancel, Install, Retry, Classic } + +/** An action is a user command, not a focusable progress indicator. */ +data class UpdateAction(val label: String, val command: UpdateCommand, val primary: Boolean = false) + +/** Plain copy for the process controller's state; bytes and notes remain real controller data. */ +data class UpdatePresentation( + val title: String = "", + val summary: String = "", + val paragraphs: List = emptyList(), + val actions: List, + val progress: Boolean = false, + val fraction: Float? = null, + val byteProgress: String? = null, +) + +/** Decimal megabytes match release sizes; unknown totals never create a percentage. */ +fun formatUpdateBytes(bytes: Long): String = NumberFormat.getNumberInstance().apply { + minimumFractionDigits = 1 + maximumFractionDigits = 1 +}.format(bytes / 1_000_000.0) + " MB" + +/** Metadata uses the controller's locale-formatted release date. */ +fun updateMetadata(release: UpdateUiState.Available?): String = release?.let { + "${it.versionName} · ${formatUpdateBytes(it.bytes)} · ${it.dateText}" +}.orEmpty() + +/** Every controller outcome is distinct from a successful compatible version comparison. */ +fun presentUpdate(state: UpdateUiState, release: UpdateUiState.Available?, updatedVersion: String? = null): UpdatePresentation { + val back = UpdateAction("Back", UpdateCommand.Back) + val notes = UpdateAction("Release notes", UpdateCommand.Notes) + val retry = UpdateAction("Retry", UpdateCommand.Retry, true) + val metadata = updateMetadata(release) + return when (state) { + UpdateUiState.Idle -> UpdatePresentation(actions = listOf(UpdateAction("Check for updates", UpdateCommand.Check, true))) + UpdateUiState.Checking -> UpdatePresentation(actions = listOf(back), progress = true) + UpdateUiState.UpToDate -> UpdatePresentation( + title = updatedVersion?.let { "Updated to $it" } ?: "Up to date", + summary = if (updatedVersion != null) "Sign-ins and settings kept." else "No newer release for this TV.", + actions = listOf(UpdateAction("Check again", UpdateCommand.Check, true)), + ) + UpdateUiState.NoReleasePublished -> UpdatePresentation("No release published", "No update has been published for this TV yet.", + actions = listOf(UpdateAction("Check again", UpdateCommand.Check, true))) + is UpdateUiState.Available -> UpdatePresentation("Update available", updateMetadata(state), + state.notes.lineSequence().filter { it.isNotBlank() }.take(3).toList(), + listOf(UpdateAction("Download", UpdateCommand.Download, true), notes)) + is UpdateUiState.Downloading -> { + val total = state.bytesTotal?.takeIf { it > 0 } + val fraction = total?.let { (state.bytesDone.toDouble() / it).coerceIn(0.0, 1.0).toFloat() } + val bytes = total?.let { "${formatUpdateBytes(state.bytesDone).removeSuffix(" MB")} / ${formatUpdateBytes(it)}" } + ?: formatUpdateBytes(state.bytesDone) + UpdatePresentation(fraction?.let { "${(it * 100).toInt()}%" }.orEmpty(), metadata, + actions = listOf(UpdateAction("Cancel download", UpdateCommand.Cancel)), progress = true, fraction = fraction, byteProgress = bytes) + } + is UpdateUiState.Ready -> UpdatePresentation("Ready to install", metadata.ifEmpty { state.versionName }, + listOf("Verified · your sign-ins and settings stay."), listOf(UpdateAction("Install update", UpdateCommand.Install, true), notes)) + UpdateUiState.PermissionNeeded -> UpdatePresentation("Allow updates on this TV", "Enable Wolfskin in Install unknown apps, then return.", + actions = listOf(UpdateAction("Open TV settings", UpdateCommand.Install, true), UpdateAction("Not now", UpdateCommand.Cancel))) + UpdateUiState.HandingOff -> UpdatePresentation("Continue in Android", "Confirm the update on the system screen.", + listOf("Wolfskin closes during installation.", "Choose Open, or reopen Wolfskin from the launcher."), listOf(UpdateAction("Back", UpdateCommand.Cancel))) + UpdateUiState.InstallCancelled -> UpdatePresentation("Install cancelled", metadata, + listOf("Verified · your sign-ins and settings stay."), listOf(UpdateAction("Try install again", UpdateCommand.Install, true), notes)) + is UpdateUiState.Failed -> UpdatePresentation(failureTitle(state.kind), state.message, actions = listOf(retry, back)) + UpdateUiState.Offline -> UpdatePresentation("No network", "Reconnect this TV, then try again.", + actions = listOf(UpdateAction("Try again", UpdateCommand.Retry, true))) + UpdateUiState.NoInstaller -> UpdatePresentation("This TV cannot open an installer", "Android’s install confirmation is unavailable.", + listOf("The download is kept. Classic settings may offer the same system limitation."), + listOf(retry, UpdateAction("Classic settings (trial)", UpdateCommand.Classic))) + } +} + +private fun failureTitle(kind: UpdateFailure): String = when (kind) { + UpdateFailure.Network -> "Check failed" + UpdateFailure.HttpRefused, UpdateFailure.InsufficientStorage -> "Download failed" + UpdateFailure.InvalidMetadata, UpdateFailure.UnsupportedAbi -> "Update unavailable" + UpdateFailure.ChecksumMismatch, UpdateFailure.WrongPackage, UpdateFailure.WrongSigner, UpdateFailure.LowerVersionCode -> "Verification failed" +} diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateProgress.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateProgress.kt new file mode 100644 index 00000000..fc23963c --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateProgress.kt @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import androidx.compose.animation.core.RepeatMode +import androidx.compose.animation.core.animateFloat +import androidx.compose.animation.core.infiniteRepeatable +import androidx.compose.animation.core.rememberInfiniteTransition +import androidx.compose.animation.core.tween +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.CornerRadius +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.drawscope.clipRect +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.semantics.ProgressBarRangeInfo +import androidx.compose.ui.semantics.progressBarRangeInfo +import androidx.compose.ui.semantics.semantics +import org.justinvisser.wolfskin.design.reducedMotion +import org.justinvisser.wolfskin.design.WolfskinTokens.Color as C +import org.justinvisser.wolfskin.design.WolfskinTokens.Motion as M +import org.justinvisser.wolfskin.design.WolfskinTokens.Update as U + +/** Draw-only bounded track: changing bytes never moves logical or Android focus. */ +@Composable +fun UpdateProgress(fraction: Float?, modifier: Modifier = Modifier) { + val reduced = reducedMotion() + val phase = if (reduced) 0f else { + val transition = rememberInfiniteTransition(label = "update-progress") + val animated by transition.animateFloat(0f, 1f, + infiniteRepeatable(tween(if (fraction == null) M.updateScan else M.updateSheen, + easing = if (fraction == null) M.breatheEase else M.linear), RepeatMode.Restart), label = "highlight") + animated + } + Canvas(modifier.fillMaxWidth().height(U.progressHeight).testTag("update-progress") + .semantics { progressBarRangeInfo = fraction?.let { ProgressBarRangeInfo(it, 0f..1f) } ?: ProgressBarRangeInfo.Indeterminate }) { + val radius = CornerRadius(U.progressRadius.toPx()) + drawRoundRect(C.surface3, cornerRadius = radius) + val width = size.width * (fraction ?: U.scanFraction) + val left = if (fraction != null || reduced) 0f else width * (-1f + (U.scanEnd + 1f) * phase) + clipRect { + drawRoundRect(C.accent, Offset(left, 0f), Size(width, size.height), radius) + if (!reduced && fraction != null && width > 0f) { + clipRect(0f, 0f, width, size.height) { + val start = width * (-1f + 2f * phase) + drawRect(Brush.horizontalGradient(listOf(Color.Transparent, Color.White.copy(alpha = U.sheenAlpha), Color.Transparent), + startX = start, endX = start + width), size = Size(width, size.height)) + } + } + } + } +} diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt new file mode 100644 index 00000000..ea69c6f7 --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import androidx.compose.animation.core.tween +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.gestures.animateScrollBy +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.role +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.stateDescription +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.compose.LifecycleEventEffect +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.tv.material3.Text +import kotlinx.coroutines.launch +import org.justinvisser.wolfskin.design.Avatar +import org.justinvisser.wolfskin.design.CssColumn +import org.justinvisser.wolfskin.design.PickerButton +import org.justinvisser.wolfskin.design.ShellState +import org.justinvisser.wolfskin.design.WolfskinTokens +import org.justinvisser.wolfskin.design.exactLineBox +import org.justinvisser.wolfskin.design.focusRing +import org.justinvisser.wolfskin.design.focusScale +import org.justinvisser.wolfskin.design.motionDuration +import org.justinvisser.wolfskin.design.reducedMotion +import org.justinvisser.wolfskin.design.rowReveal +import org.justinvisser.wolfskin.design.WolfskinTokens.Color as C +import org.justinvisser.wolfskin.design.WolfskinTokens.Layout as L +import org.justinvisser.wolfskin.design.WolfskinTokens.Motion as M +import org.justinvisser.wolfskin.design.WolfskinTokens.Shell as S +import org.justinvisser.wolfskin.design.UpdateTypography as T +import org.justinvisser.wolfskin.design.WolfskinTokens.Update as U + +/** Controller lifetime belongs to the process, while navigation owns this screen's focus. */ +@Composable +fun UpdatesScreen(shell: ShellState, controller: UpdateController, onBack: () -> Unit, onClassic: () -> Unit, modifier: Modifier = Modifier) { + val state by controller.state.collectAsStateWithLifecycle() + val installed by controller.installedVersion.collectAsStateWithLifecycle() + val release by controller.release.collectAsStateWithLifecycle() + val autoCheck by controller.autoCheck.collectAsStateWithLifecycle() + val initialInstalled = remember { installed.versionName } + val updatedVersion = installed.versionName.takeIf { it != initialInstalled } + val presentation = presentUpdate(if (updatedVersion != null) UpdateUiState.UpToDate else state, release, updatedVersion) + val scroll = rememberScrollState() + val scope = rememberCoroutineScope() + val density = LocalDensity.current + val reduced = reducedMotion() + val focus = remember(controller, shell) { + UpdateFocus(controller, onBack, onClassic, { shell.navFocused = true; shell.navIndex = shell.currentTab }) { direction -> + scope.launch { scroll.animateScrollBy(with(density) { U.notesScrollStep.toPx() } * direction, + tween(motionDuration(M.scroll, reduced), easing = M.easeOut)) } + } + } + LaunchedEffect(state, presentation.actions) { focus.update(state, presentation.actions) } + LaunchedEffect(controller) { if (controller.state.value == UpdateUiState.Idle) controller.check(manual = true) } + LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { controller.onResume() } + DisposableEffect(shell, focus) { + shell.contentFocus = focus + onDispose { if (shell.contentFocus === focus) shell.contentFocus = null; shell.contentOverlayVisible = false } + } + LaunchedEffect(focus.notesOpen) { shell.contentOverlayVisible = focus.notesOpen } + Box(modifier.fillMaxSize().testTag("updates-screen")) { + Row(Modifier.offset(L.safeSide, U.headerTop).height(U.headerHeight), + verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(S.settingsHeaderGap)) { + Avatar(shell.person, S.settingsHeaderAvatar, T.avatarLetterLibHeader, letterColor = C.muted) + Text("Updates", Modifier.alignByBaseline().exactLineBox(T.screenTitle), style = T.screenTitle, color = C.fg) + Text("Installed ${installed.versionName}", Modifier.alignByBaseline(), style = T.nav.copy(fontWeight = androidx.compose.ui.text.font.FontWeight.Normal), color = C.muted) + } + Text("Back · Settings", Modifier.align(Alignment.TopEnd).padding(end = L.safeSide).offset(y = U.backTop), style = T.label.copy(fontWeight = androidx.compose.ui.text.font.FontWeight.Normal), color = C.muted) + if (focus.notesOpen) { + NotesPanel(release, scroll) + } else { + UpdatePanel(presentation, focus, !shell.navFocused, state.javaClass) + AutoCheckRow(autoCheck, focus.autoFocused && !shell.navFocused, Modifier.offset(L.safeSide, U.autoTop), focus::toggleAuto) + } + } +} + +@Composable +private fun UpdatePanel(presentation: UpdatePresentation, focus: UpdateFocus, focused: Boolean, identity: Any) { + val shape = RoundedCornerShape(U.radius) + CssColumn(Modifier.offset(L.safeSide, U.contentTop).width(U.width).rowReveal(identity) + .background(C.surface, shape).border(U.border, C.border, shape).padding(U.padding + U.border)) { + if (presentation.title.isNotEmpty()) { + Text(presentation.title, Modifier.exactLineBox(T.heading), style = T.heading, color = C.fg) + Spacer(Modifier.height(U.titleBottom)) + } + if (presentation.summary.isNotEmpty()) { + Text(presentation.summary, Modifier.exactLineBox(T.body), style = T.body, color = C.muted) + if (presentation.paragraphs.isNotEmpty()) Spacer(Modifier.height(U.paragraphBottom)) + } + presentation.paragraphs.forEachIndexed { index, paragraph -> + Text(paragraph, Modifier.exactLineBox(T.body), style = T.body, color = C.muted) + if (index != presentation.paragraphs.lastIndex) Spacer(Modifier.height(U.paragraphBottom)) + } + if (presentation.progress) { + Spacer(Modifier.height(U.progressTop)) + UpdateProgress(presentation.fraction) + presentation.byteProgress?.let { + Spacer(Modifier.height(U.progressBottom)) + Text(it, Modifier.exactLineBox(T.body), style = T.body, color = C.muted) + } + } + Row(Modifier.padding(top = U.actionsTop), horizontalArrangement = Arrangement.spacedBy(U.actionGap)) { + presentation.actions.forEachIndexed { index, action -> + Box(Modifier.testTag("update-action-${action.command}")) { + PickerButton(action.label, focused && !focus.autoFocused && focus.actionIndex == index, action.primary, + textStyle = T.button, onFocus = { focus.focusAction(index) }) { focus.activate(index) } + } + } + } + } +} + +@Composable +private fun AutoCheckRow(enabled: Boolean, focused: Boolean, modifier: Modifier, onToggle: () -> Unit) { + val shape = RoundedCornerShape(WolfskinTokens.Radius.listRow) + Row(modifier.size(L.settingsRowWidth, L.settingsRowHeight).testTag("update-auto-check") + .semantics { role = Role.Switch; stateDescription = if (enabled) "On" else "Off" } + .focusScale(focused, WolfskinTokens.Focus.scaleRow) + .background(if (focused) C.fg else C.listRowRest, shape).clickable(onClick = onToggle) + .padding(horizontal = S.settingsRowPadding), verticalAlignment = Alignment.CenterVertically) { + Column(Modifier.weight(1f)) { + Text("Auto-check for updates", Modifier.exactLineBox(T.listTitle), style = T.listTitle, color = if (focused) C.onFocus else C.fg) + Text("${if (enabled) "On" else "Off"} · checks only, never installs", Modifier.exactLineBox(T.caption), style = T.caption, color = if (focused) C.onFocus else C.muted) + } + Box(Modifier.size(U.toggleWidth, U.toggleHeight).background(if (focused || !enabled) C.surface3 else C.accentSoft, CircleShape)) { + Box(Modifier.align(if (enabled) Alignment.CenterEnd else Alignment.CenterStart).padding(horizontal = U.toggleInset) + .size(U.toggleThumb).background(if (enabled) C.accentText else C.muted, CircleShape)) + } + } +} + +@Composable +private fun NotesPanel(release: UpdateUiState.Available?, scroll: androidx.compose.foundation.ScrollState) { + val shape = RoundedCornerShape(U.radius) + Column(Modifier.offset(L.safeSide, U.contentTop).size(U.width, U.notesHeight).testTag("update-notes") + .focusRing(true, U.radius, WolfskinTokens.Focus.ringControlRing) + .background(C.surface, shape).border(U.border, C.border, shape) + .verticalScroll(scroll).padding(U.padding + U.border)) { + Text(updateMetadata(release), Modifier.exactLineBox(T.stateTitle), style = T.stateTitle.copy(fontWeight = androidx.compose.ui.text.font.FontWeight.Bold), color = C.fg) + Spacer(Modifier.height(U.notesTitleBottom)) + release?.notes?.lineSequence()?.filter { it.isNotBlank() }?.forEach { paragraph -> + Row(Modifier.padding(vertical = U.notesGap / 2)) { + Text("•", Modifier.width(U.padding / 2), style = T.nav, color = C.muted) + Text(paragraph.removePrefix("- "), Modifier.exactLineBox(T.nav), style = T.nav.copy(fontWeight = androidx.compose.ui.text.font.FontWeight.Normal), color = C.muted) + } + } + Text("Sign-in stays on this TV. Android asks before installing.", Modifier.padding(top = U.notesGap), style = T.body, color = C.muted) + } +} diff --git a/wolfskin-design/generate_tokens.py b/wolfskin-design/generate_tokens.py index e18bc364..d036e496 100755 --- a/wolfskin-design/generate_tokens.py +++ b/wolfskin-design/generate_tokens.py @@ -121,9 +121,10 @@ def main() -> None: tokens.update(json.loads((ROOT / "title-tokens.json").read_text())) tokens.update(json.loads((ROOT / "home-tokens.json").read_text())) tokens.update(json.loads((ROOT / "discover-tokens.json").read_text())) + tokens.update(json.loads((ROOT / "update-tokens.json").read_text())) kotlin, css = render_tokens(tokens) outputs = {str(KOTLIN): kotlin, "tokens.css": css} - inputs = ["tokens.json", "shell-tokens.json", "title-tokens.json", "home-tokens.json", "discover-tokens.json", "generate_tokens.py"] + inputs = ["tokens.json", "shell-tokens.json", "title-tokens.json", "home-tokens.json", "discover-tokens.json", "update-tokens.json", "generate_tokens.py"] checksums = {name: hashlib.sha256((ROOT / name).read_bytes()).hexdigest() for name in inputs} checksums.update({name: hashlib.sha256(content.encode()).hexdigest() for name, content in outputs.items()}) outputs["tokens.sha256"] = "".join(f"{checksum} {name}\n" for name, checksum in sorted(checksums.items())) diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/CssLineBox.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/CssLineBox.kt index 4f1d281a..1600e51c 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/CssLineBox.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/CssLineBox.kt @@ -40,7 +40,7 @@ private class CssColumnHeight : ParentDataModifier { /** Fractional line heights accumulate before rounding, rather than adding a rounded pixel per row. */ @Composable -internal fun CssColumn(modifier: Modifier = Modifier, gap: Dp = WolfskinTokens.Shell.zero, content: @Composable () -> Unit) { +fun CssColumn(modifier: Modifier = Modifier, gap: Dp = WolfskinTokens.Shell.zero, content: @Composable () -> Unit) { val exact = remember { CssColumnHeight() } Layout(content, modifier.then(exact)) { children, constraints -> val measured = Array(children.size) { children[it].measure(constraints.copy(minWidth = 0, minHeight = 0)) } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/Identity.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/Identity.kt index 266cbded..d7c5570f 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/Identity.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/Identity.kt @@ -23,10 +23,10 @@ fun personColor(key: String): Color = when (key.lowercase()) { /** The same mark anchors the picker and the persistent navigation. */ @Composable -fun Wordmark(modifier: Modifier = Modifier) { +fun Wordmark(modifier: Modifier = Modifier, prefix: String = "Wolf", textStyle: TextStyle = WolfskinTokens.Type.wordmark) { Row(modifier) { - Text("Wolf", color = WolfskinTokens.Color.fg, style = WolfskinTokens.Type.wordmark) - Text("skin", color = WolfskinTokens.Color.accent, style = WolfskinTokens.Type.wordmark) + Text(prefix, color = WolfskinTokens.Color.fg, style = textStyle) + Text("skin", color = WolfskinTokens.Color.accent, style = textStyle) } } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/NavBar.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/NavBar.kt index 40b8563c..929fce42 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/NavBar.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/NavBar.kt @@ -61,6 +61,7 @@ fun NavBar(state: ShellState, scrolled: Boolean, modifier: Modifier = Modifier) val reduced = reducedMotion() val labelFade = tween(motionDuration(S.navLabelFade, reduced), easing = CubicBezierEasing(0f, 0f, .58f, 1f)) val index = if (state.navFocused) state.navIndex else state.currentTab + val hasSelectedTab = state.route != "settings" && state.route != "updates" val box = boxes[index] val avatarFocused = state.navFocused && index == state.tabs.size val pad = if (avatarFocused) L.navBlobAvatarPad else S.zero @@ -79,14 +80,15 @@ fun NavBar(state: ShellState, scrolled: Boolean, modifier: Modifier = Modifier) Box(modifier.fillMaxWidth().height(L.navBand)) { Canvas(Modifier.matchParentSize()) { if (scrolled) drawRect(C.bg) else drawRect(band) - drawRoundRect(color, Offset(x * density, y * density), Size(width * density, height * density), CornerRadius(height * density / 2)) + if (state.navFocused || hasSelectedTab) drawRoundRect(color, Offset(x * density, y * density), Size(width * density, height * density), CornerRadius(height * density / 2)) } - Wordmark(Modifier.offset(L.safeSide, S.wordmarkTop)) + Wordmark(Modifier.offset(L.safeSide, S.wordmarkTop), if (hasSelectedTab) "Wolf" else "wolf", + if (hasSelectedTab) WolfskinTokens.Type.wordmark else UpdateTypography.wordmark) state.tabs.forEachIndexed { itemIndex, tab -> val item = boxes[itemIndex] val focused = state.navFocused && state.navIndex == itemIndex val labelColor by animateColorAsState( - if (focused) C.onFocus else if (itemIndex == state.currentTab) C.fg else C.muted, + if (focused) C.onFocus else if (hasSelectedTab && itemIndex == state.currentTab) C.fg else C.muted, animationSpec = labelFade, label = "nav-label-$tab", ) @@ -95,8 +97,8 @@ fun NavBar(state: ShellState, scrolled: Boolean, modifier: Modifier = Modifier) .clickable { state.focusNav(itemIndex); state.key(ShellKey.Ok) }, contentAlignment = Alignment.Center) { - Text(tab.replaceFirstChar { it.uppercase() }, style = WolfskinTokens.Type.nav, color = labelColor) - if (itemIndex == state.currentTab && !focused) { + Text(tab.replaceFirstChar { it.uppercase() }, style = if (hasSelectedTab) WolfskinTokens.Type.nav else UpdateTypography.nav, color = labelColor) + if (hasSelectedTab && itemIndex == state.currentTab && !focused) { Box(Modifier.align(Alignment.BottomCenter).offset(y = -L.navUnderline).size(item.width - L.navItemPaddingX * 2, L.navUnderline).background(C.accent)) } } @@ -111,7 +113,7 @@ fun NavBar(state: ShellState, scrolled: Boolean, modifier: Modifier = Modifier) } } val avatar = boxes.last() - Avatar(state.person, L.navAvatar, WolfskinTokens.Type.avatarLetterNav, + Avatar(state.person, L.navAvatar, if (hasSelectedTab) WolfskinTokens.Type.avatarLetterNav else UpdateTypography.avatarLetterNav, Modifier.offset(avatar.left, avatar.top) .focusRing(avatarFocused, L.navAvatar / 2, WolfskinTokens.Focus.ringAvatarRing) .focusProperties { canFocus = false } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/SettingsList.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/SettingsList.kt index 08c79cd8..15c47744 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/SettingsList.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/SettingsList.kt @@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding @@ -36,50 +37,52 @@ import androidx.tv.material3.Text import org.justinvisser.wolfskin.design.WolfskinTokens.Color as C import org.justinvisser.wolfskin.design.WolfskinTokens.Layout as L import org.justinvisser.wolfskin.design.WolfskinTokens.Shell as S +import org.justinvisser.wolfskin.design.UpdateTypography as T /** Settings routes identify real upstream destinations rather than stand-in panels. */ data class SettingsGroup(val key: String, val title: String, val description: String, val wolfskin: Boolean = false) val SETTINGS_GROUPS = listOf( - SettingsGroup("requests", "Requests", "Coming in: what the household asked for, and how far each is"), - SettingsGroup("interface", "Interface", "Sign in automatically · Remember selected tabs · Theme music · Subtitle style · Application theme · Screensaver"), - SettingsGroup("playback", "Playback", "Skip forward · Skip back · Skip back when resuming"), - SettingsGroup("nextup", "Next up", "Show next up timing · Auto play next up · Delay · Passout protection"), - SettingsGroup("profile", "User profile settings", "Profile protection · Customize home page (Wolfskin presets: Default, Compact, Series thumbs, Episode thumbnails) · Navigation drawer items · Language", true), - SettingsGroup("about", "About", "Installed version · Update (Wolfskin releases on Forgejo) · Wolfskin about", true), - SettingsGroup("seerr", "Seerr integration", "Add, change or remove the Seerr server this TV asks for Discover and ratings", true), - SettingsGroup("advanced", "Advanced settings", "Ratings display · Backdrop style · Playback backend (ExoPlayer, MPV) · Max resolution and bitrate · Skip segments · Logs and image cache"), + SettingsGroup("requests", "Requests", "Coming in: what the household asked for"), + SettingsGroup("updates", "Updates", "Check and install", true), + SettingsGroup("interface", "Interface", "Sign-in · Theme music · Subtitles"), + SettingsGroup("playback", "Playback", "Skip forward · Skip back · Resume"), + SettingsGroup("nextup", "Next up", "Auto-play · Delay · Passout protection"), + SettingsGroup("profile", "User profile settings", "Protection · Home · Language"), + SettingsGroup("about", "About", "Installed version · Wolfskin about"), + SettingsGroup("seerr", "Seerr integration", "Manage the Seerr server"), + SettingsGroup("advanced", "Advanced settings", "Playback backend · Logs · Image cache"), + SettingsGroup("classic", "Classic settings (trial)", "Original settings, including About → Update"), ) /** The count describes returned request history, not an inferred queue of active downloads. */ @Composable -fun SettingsList(state: ShellState, modifier: Modifier = Modifier, requestCount: Int? = null) { +fun SettingsList(state: ShellState, modifier: Modifier = Modifier, requestCount: Int? = null, installedVersion: String = "") { val list = state.view.listState + val reduced = reducedMotion() val density = LocalDensity.current LaunchedEffect(state.settingsRow, state.navFocused) { if (state.navFocused) return@LaunchedEffect - val y = L.row_lhead + L.row_srow * state.settingsRow - val target = if (y >= L.windowAhead) y - L.pinnedLine else S.zero - val current = if (list.firstVisibleItemIndex == 0) S.zero else L.row_lhead + L.row_srow * (list.firstVisibleItemIndex - 1) - val distance = with(density) { (target - current).toPx() } - list.firstVisibleItemScrollOffset - list.animateScrollBy(distance, tween(if (NetworkArtTransition.reduced) 0 else WolfskinTokens.Motion.scroll, easing = WolfskinTokens.Motion.easeOut)) + val target = (state.settingsRow - WolfskinTokens.Update.settingsVisibleRows.toInt() + 1).coerceAtLeast(0) + val distance = with(density) { (L.row_srow * (target - list.firstVisibleItemIndex)).toPx() } - list.firstVisibleItemScrollOffset + list.animateScrollBy(distance, tween(if (reduced) 0 else WolfskinTokens.Motion.scroll, easing = WolfskinTokens.Motion.easeOut)) } - LazyColumn(modifier.fillMaxSize(), state = list, - contentPadding = PaddingValues(bottom = S.stageHeight - L.pinnedLine - L.row_srow)) { - item(key = "settings-header") { - Row(Modifier.height(L.row_lhead).padding(start = L.safeSide, top = S.settingsHeaderTop), - verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(S.settingsHeaderGap)) { - Avatar(state.person, S.settingsHeaderAvatar, WolfskinTokens.Type.avatarLetterLibHeader, letterColor = C.muted) - Text("Settings", Modifier.alignByBaseline(), style = WolfskinTokens.Type.screenTitle, color = C.fg) - Text("Requests and Wholphin settings on this TV · ${state.person.name}", Modifier.alignByBaseline(), style = WolfskinTokens.Type.nav.copy(fontWeight = FontWeight.Normal), color = C.muted) - } + Box(modifier.fillMaxSize()) { + Row(Modifier.offset(L.safeSide, WolfskinTokens.Update.headerTop).height(WolfskinTokens.Update.headerHeight), + verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(S.settingsHeaderGap)) { + Avatar(state.person, S.settingsHeaderAvatar, T.avatarLetterLibHeader, letterColor = C.muted) + Text("Settings", Modifier.alignByBaseline().exactLineBox(T.screenTitle), style = T.screenTitle, color = C.fg) + Text("This TV · ${state.person.name}", Modifier.alignByBaseline(), style = T.nav.copy(fontWeight = FontWeight.Normal), color = C.muted) } - itemsIndexed(SETTINGS_GROUPS, key = { _, group -> group.key }) { index, group -> - Box(Modifier.height(L.row_srow)) { - SettingsRow(group, !state.navFocused && !state.requestsVisible && index == state.settingsRow, - if (group.key == "requests") requestCount else null, - Modifier.offset(L.safeSide, S.settingsRowTop)) { - state.navFocused = false; state.settingsRow = index; state.key(ShellKey.Ok) + LazyColumn(Modifier.fillMaxWidth().offset(y = WolfskinTokens.Update.rowsTop).height(WolfskinTokens.Update.rowsViewport + S.settingsRowGap), + state = list, contentPadding = PaddingValues(bottom = S.settingsRowGap)) { + itemsIndexed(SETTINGS_GROUPS, key = { _, group -> group.key }) { index, group -> + Box(Modifier.height(L.row_srow)) { + val display = if (group.key == "updates") group.copy(description = "$installedVersion · Check and install") else group + SettingsRow(display, !state.navFocused && !state.requestsVisible && index == state.settingsRow, + if (group.key == "requests") requestCount else null, Modifier.offset(L.safeSide)) { + state.navFocused = false; state.settingsRow = index; state.key(ShellKey.Ok) + } } } } @@ -94,14 +97,13 @@ fun SettingsRow(group: SettingsGroup, focused: Boolean, requestCount: Int?, modi .background(if (focused) C.fg else C.listRowRest, RoundedCornerShape(WolfskinTokens.Radius.listRow)) .clickable(onClick = onClick).padding(horizontal = S.settingsRowPadding), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(S.settingsRowGap)) { - Glyph(group.key, if (focused) C.onFocus else C.accentText, Modifier.size(S.settingsIcon)) + Glyph(if (group.key == "updates") "updates" else "settings-list", if (focused) C.onFocus else C.accentText, Modifier.size(S.settingsIcon)) Column(Modifier.weight(1f)) { val count = requestCount?.let { " · $it ${if (it == 1) "request" else "requests"}" } ?: "" - Text(group.title + count, Modifier.exactLineBox(WolfskinTokens.Type.listTitle), color = foreground, style = WolfskinTokens.Type.listTitle, maxLines = 1) - Text(group.description, Modifier.exactLineBox(WolfskinTokens.Type.caption), color = if (focused) C.onFocus else C.muted, style = WolfskinTokens.Type.caption, maxLines = 1, overflow = TextOverflow.Ellipsis) + Text(group.title + count, Modifier.exactLineBox(T.listTitle), color = foreground, style = T.listTitle, maxLines = 1) + Text(group.description, Modifier.exactLineBox(T.caption), color = if (focused) C.onFocus else C.muted, style = T.caption, maxLines = 1, overflow = TextOverflow.Ellipsis) } - if (group.wolfskin) SettingsPill("Wolfskin", focused) - SettingsPill(if (group.key == "requests") "Wolfskin screen" else "upstream screen", focused) + SettingsPill(if (group.key == "requests" || group.key == "updates") "Wolfskin screen" else "upstream screen", focused) Glyph("right", if (focused) C.onFocus else C.accentText, Modifier.size(S.settingsChevron)) } } @@ -122,6 +124,6 @@ private fun SettingsPill(label: String, focused: Boolean) { drawRoundRect(border, topLeft = inset, size = bounds, cornerRadius = radius, style = outline) } }.padding(horizontal = S.settingsPillPadding + S.settingsPillStroke), contentAlignment = Alignment.Center) { - Text(label, color = foreground, style = WolfskinTokens.Type.caption.copy(fontWeight = WolfskinTokens.Type.label.fontWeight)) + Text(label, color = foreground, style = T.caption.copy(fontWeight = T.label.fontWeight)) } } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/ShellState.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/ShellState.kt index c770a3ab..2992e93f 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/ShellState.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/ShellState.kt @@ -260,9 +260,13 @@ class ShellState( } } else if (route == "settings") { val group = SETTINGS_GROUPS[settingsRow].key - if (group == "requests") openRequests() else { - handOff = group - onAction(ShellAction.HandOff(group)) + when (group) { + "requests" -> openRequests() + "updates" -> onAction(ShellAction.Destination("updates")) + else -> { + handOff = group + onAction(ShellAction.HandOff(group)) + } } } else contentFocus?.key(ShellKey.Ok) @@ -305,6 +309,7 @@ class ShellState( gearFocused = true pickerIndex = people.lastIndex } else if (route !in tabs) { + if (route == "updates") navFocused = false onAction(ShellAction.Pop) } else if (!navFocused) { navFocused = true diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/ShellSurface.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/ShellSurface.kt index 603942b2..cf1da9c4 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/ShellSurface.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/ShellSurface.kt @@ -56,6 +56,7 @@ fun ShellSurface( modifier: Modifier = Modifier, handlesContentKeys: Boolean = true, settingsRequestCount: Int? = null, + settingsInstalledVersion: String = "", overlay: @Composable () -> Unit = {}, content: @Composable (Modifier) -> Unit = { ShellPlaceholder(state.route) }, ) { @@ -91,7 +92,7 @@ fun ShellSurface( if (state.pickerVisible) { WhosWatching(state) } else { - if (state.route == "settings") SettingsList(state, requestCount = settingsRequestCount ?: state.requests.snapshot.requestCount) else content(Modifier.fillMaxSize().focusRequester(contentFocus).focusRestorer().focusGroup()) + if (state.route == "settings") SettingsList(state, requestCount = settingsRequestCount ?: state.requests.snapshot.requestCount, installedVersion = settingsInstalledVersion) else content(Modifier.fillMaxSize().focusRequester(contentFocus).focusRestorer().focusGroup()) NavBar(state, state.view.listState.firstVisibleItemIndex > 0 || state.view.listState.firstVisibleItemScrollOffset > L.navSolidAfter.value * 2) if (state.requestsVisible) ComingInSheet(state) overlay() diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/UpdateTypography.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/UpdateTypography.kt new file mode 100644 index 00000000..92ad49f0 --- /dev/null +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/UpdateTypography.kt @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.design + +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight + +/** The approved Updates frames resolve system-ui to DejaVu Sans; other screens keep their fonts. */ +object UpdateTypography { + val family = FontFamily(Font(R.font.update_dejavu_sans), Font(R.font.update_dejavu_sans_bold, FontWeight.Bold)) + val screenTitle = WolfskinTokens.Type.screenTitle.copy(fontFamily = family) + val stateTitle = WolfskinTokens.Type.stateTitle.copy(fontFamily = family) + val heading = WolfskinTokens.Update.heading.copy(fontFamily = family) + val nav = WolfskinTokens.Type.nav.copy(fontFamily = family) + val wordmark = WolfskinTokens.Type.wordmark.copy(fontFamily = family) + val listTitle = WolfskinTokens.Type.listTitle.copy(fontFamily = family) + val body = WolfskinTokens.Type.body.copy(fontFamily = family) + val button = WolfskinTokens.Type.button.copy(fontFamily = family) + val label = WolfskinTokens.Type.label.copy(fontFamily = family) + val caption = WolfskinTokens.Type.caption.copy(fontFamily = family) + val avatarLetterNav = WolfskinTokens.Type.avatarLetterNav.copy(fontFamily = family) + val avatarLetterLibHeader = WolfskinTokens.Type.avatarLetterLibHeader.copy(fontFamily = family) +} diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt index 35ac83e3..0cfda025 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt @@ -209,6 +209,9 @@ object WolfskinTokens { const val fillInverse = "background color.fg, text color.onFocus" } object Motion { + const val updateScan = 1800 + const val updateSheen = 1600 + val linear = CubicBezierEasing(0.0f, 0.0f, 1.0f, 1.0f) const val skeletonCycle = 1400 const val skeletonLowAlpha = 0.55f const val focusMove = 180 @@ -698,4 +701,38 @@ object WolfskinTokens { const val ambientSaturation = 1.2f const val ambientBrightness = 0.55f } + object Update { + val heading = TextStyle(fontSize = 18.0.sp, fontWeight = FontWeight(800), lineHeight = 20.160000000000004.sp, letterSpacing = -0.02.em) + const val settingsVisibleRows = 6.0f + val headerTop = 75.0.dp + val headerHeight = 42.0.dp + val rowsTop = 139.0.dp + val rowsViewport = 362.0.dp + val contentTop = 149.0.dp + val width = 650.0.dp + val padding = 20.0.dp + val border = 1.0.dp + val radius = 11.0.dp + val titleBottom = 8.0.dp + val paragraphBottom = 7.0.dp + val actionsTop = 18.0.dp + val actionGap = 12.0.dp + val progressTop = 15.0.dp + val progressBottom = 11.0.dp + val progressHeight = 6.0.dp + val progressRadius = 4.0.dp + val autoTop = 431.0.dp + val toggleWidth = 40.0.dp + val toggleHeight = 21.0.dp + val toggleThumb = 15.0.dp + val toggleInset = 3.0.dp + val notesHeight = 256.0.dp + val notesTitleBottom = 10.0.dp + val notesGap = 9.0.dp + val notesScrollStep = 40.0.dp + val backTop = 92.0.dp + const val scanFraction = 0.28f + const val scanEnd = 4.6f + const val sheenAlpha = 0.35f + } } diff --git a/wolfskin-design/src/main/res/drawable/wolfskin_settings_list.xml b/wolfskin-design/src/main/res/drawable/wolfskin_settings_list.xml new file mode 100644 index 00000000..362cc295 --- /dev/null +++ b/wolfskin-design/src/main/res/drawable/wolfskin_settings_list.xml @@ -0,0 +1,3 @@ + + + diff --git a/wolfskin-design/src/main/res/drawable/wolfskin_update.xml b/wolfskin-design/src/main/res/drawable/wolfskin_update.xml new file mode 100644 index 00000000..cfe21b10 --- /dev/null +++ b/wolfskin-design/src/main/res/drawable/wolfskin_update.xml @@ -0,0 +1,3 @@ + + + diff --git a/wolfskin-design/src/main/res/font/update_dejavu_sans.ttf b/wolfskin-design/src/main/res/font/update_dejavu_sans.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1728e9ec32bad1522771b4e5d3d05149e7b06a88 GIT binary patch literal 759720 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

Fvay3Tf9H*%**9_dn1cYZySZ9FF@ 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Ö&o*pTo>f;EqJsQ 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

%x6P}nlPX1;07O{^oVBo5qBZhkk(tz9-vYKy; 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

jtd_Q!Gux8B;xpRLn@rL-e>KuKyzRxjtn9+V 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%0A2zLEtgMD9h|GcF_FuHMhK{>04= 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%0A!TH;*kD^vhbuLu&0$|p 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

Qyg~M3$zt$TAAyx6!th$h;D5!v|ec@Im!l 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%0D2Fw$5%9ACKO6eY|8y=83!kRW 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

He822sU6LAa_$GQM`&SB(sok}6{Pc1r*~#m)2x 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%0A#g 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

l;`zz*vu78V)iczy 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 literal 0 HcmV?d00001 diff --git a/wolfskin-design/src/main/res/raw/update_font_license.txt b/wolfskin-design/src/main/res/raw/update_font_license.txt new file mode 100644 index 00000000..272739c0 --- /dev/null +++ b/wolfskin-design/src/main/res/raw/update_font_license.txt @@ -0,0 +1,47 @@ +DejaVu Sans and DejaVu Sans Bold +https://dejavu-fonts.github.io/ + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. +Bitstream Vera is a trademark of Bitstream, Inc. +DejaVu changes are in public domain. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license ("Fonts") and associated +documentation files (the "Font Software"), to reproduce and distribute the +Font Software, including without limitation the rights to use, copy, merge, +publish, distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to the +following conditions: + +The above copyright and trademark notices and this permission notice shall +be included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may be modified and +additional glyphs or characters may be added to the Fonts, only if the fonts +are renamed to names not containing either the words "Bitstream" or the word +"Vera". + +This License becomes null and void to the extent applicable to Fonts or Font +Software that has been modified and is distributed under the "Bitstream +Vera" names. + +The Font Software may be sold as part of a larger software package but no +copy of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME +FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING +ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE +FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome +Foundation, and Bitstream Inc., shall not be used in advertising or +otherwise to promote the sale, use or other dealings in this Font Software +without prior written authorization from the Gnome Foundation or Bitstream +Inc., respectively. For further information, contact: fonts at gnome dot +org. diff --git a/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/ShellKeysTest.kt b/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/ShellKeysTest.kt index 77052d6f..ea452a66 100644 --- a/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/ShellKeysTest.kt +++ b/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/ShellKeysTest.kt @@ -54,10 +54,10 @@ class ShellKeysTest { assertEquals(state.tabs.size, state.navIndex) } - @Test fun playbackHandOffInElevenPresses() { - replay(settings + listOf(Key.DirectionDown, Key.DirectionDown, Key.DirectionCenter), 11) + @Test fun playbackHandOffInTwelvePresses() { + replay(settings + listOf(Key.DirectionDown, Key.DirectionDown, Key.DirectionDown, Key.DirectionCenter), 12) assertEquals("playback", state.handOff) - assertEquals(2, state.settingsRow) + assertEquals(3, state.settingsRow) } @Test fun onlyLastPersonReachesGearAndUpReturnsThere() { diff --git a/wolfskin-design/tokens.css b/wolfskin-design/tokens.css index bd65a73d..ef0f40c6 100644 --- a/wolfskin-design/tokens.css +++ b/wolfskin-design/tokens.css @@ -123,6 +123,9 @@ --layout-castCircle: 200.0px; --layout-personPortrait: 240.0px; --layout-row_chipsGrid: 136.0px; + --motion-updateScan: 1800ms; + --motion-updateSheen: 1600ms; + --motion-linear: cubic-bezier(0, 0, 1, 1); --motion-skeletonCycle: 1400ms; --motion-focusMove: 180ms; --motion-captionDelay: 60ms; @@ -513,4 +516,32 @@ --discover-stageGap: 10.0px; --discover-ambientInset: 80.0px; --discover-ambientBlur: 60.0px; + --update-heading: 36.0px; + --update-headerTop: 150.0px; + --update-headerHeight: 84.0px; + --update-rowsTop: 278.0px; + --update-rowsViewport: 724.0px; + --update-contentTop: 298.0px; + --update-width: 1300.0px; + --update-padding: 40.0px; + --update-border: 2.0px; + --update-radius: 22.0px; + --update-titleBottom: 16.0px; + --update-paragraphBottom: 14.0px; + --update-actionsTop: 36.0px; + --update-actionGap: 24.0px; + --update-progressTop: 30.0px; + --update-progressBottom: 22.0px; + --update-progressHeight: 12.0px; + --update-progressRadius: 8.0px; + --update-autoTop: 862.0px; + --update-toggleWidth: 80.0px; + --update-toggleHeight: 42.0px; + --update-toggleThumb: 30.0px; + --update-toggleInset: 6.0px; + --update-notesHeight: 512.0px; + --update-notesTitleBottom: 20.0px; + --update-notesGap: 18.0px; + --update-notesScrollStep: 80.0px; + --update-backTop: 184.0px; } diff --git a/wolfskin-design/tokens.json b/wolfskin-design/tokens.json index 28161fbc..c6e1ca85 100644 --- a/wolfskin-design/tokens.json +++ b/wolfskin-design/tokens.json @@ -1390,6 +1390,9 @@ } }, "motion": { + "updateScan": { "$type": "duration", "$value": "1800ms", "source": "approved Updates progress busy scan" }, + "updateSheen": { "$type": "duration", "$value": "1600ms", "source": "approved Updates download highlight" }, + "linear": { "$type": "cubicBezier", "$value": [0, 0, 1, 1] }, "skeletonCycle": { "$type": "duration", "$value": "1400ms" }, "skeletonLowAlpha": { "$type": "number", "$value": 0.55 }, "focusMove": { "$type": "duration", "$value": "180ms" }, diff --git a/wolfskin-design/tokens.sha256 b/wolfskin-design/tokens.sha256 index 8d5b523f..ef997d43 100644 --- a/wolfskin-design/tokens.sha256 +++ b/wolfskin-design/tokens.sha256 @@ -1,8 +1,9 @@ b3f096b692c395534177cc82ac68f5b801870bc7e28f0dd5cd7c17e2103920a3 discover-tokens.json -c29dc64f3c3ca900c747b3db8b270e25908948bf5f76388d2c627a612fc7c99d generate_tokens.py +993d933950e17fb72d0902ffc440e1e4ed4dc088c96a8d12974431c77dc31634 generate_tokens.py 25985087986a46f00e2819917d0421ff2b437ec21c54f6ce6412b84c0eb05302 home-tokens.json be3af0ddcb0d67abef0805d19d7a33cdb55428bcace656b50f0a38935f212028 shell-tokens.json -0446c2e85bbda72adde76329958931216fe81c43cebd47bbdb885f5dd59d87f8 src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt +18c08c6f4d77ee0690e63ec2e1ce14854eced539746c41c948942460b37a38b2 src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt e0a2f5df2f249bce3f6e13f4a0320c7b18b85777eaf04a27a428d6683a6aad28 title-tokens.json -faa4e0c5398d35ecab9b1088815b79c8de26a44d403c4cafae59c7c341992da7 tokens.css -f4424475291a745400a5daa071cb846838fb5e9ce889022288bcc6a7be758fe0 tokens.json +eed527dac5e09b209619cd67990556a5f9223d05e7e2516f300cb4760a198ca7 tokens.css +2e5e0476341adec1ec05331af38bc67cd02ba013a0988aea40a70eff21513264 tokens.json +824cb58d1507bc05212323ecfa66664f8b2bde23438940eed8717266161cac55 update-tokens.json diff --git a/wolfskin-design/update-tokens.json b/wolfskin-design/update-tokens.json new file mode 100644 index 00000000..35dc1a1f --- /dev/null +++ b/wolfskin-design/update-tokens.json @@ -0,0 +1,161 @@ +{ + "update": { + "heading": { + "$type": "typography", + "$value": {"fontWeight": 800}, + "px": 36, + "sp": 18, + "weight": 800, + "lineHeight": 1.12, + "letterSpacingEm": -0.02 + }, + "settingsVisibleRows": {"$type": "number", "$value": 6}, + "headerTop": { + "$type": "dimension", + "px": 150, + "dp": 75.0 + }, + "headerHeight": { + "$type": "dimension", + "px": 84, + "dp": 42.0 + }, + "rowsTop": { + "$type": "dimension", + "px": 278, + "dp": 139.0 + }, + "rowsViewport": { + "$type": "dimension", + "px": 724, + "dp": 362.0 + }, + "contentTop": { + "$type": "dimension", + "px": 298, + "dp": 149.0 + }, + "width": { + "$type": "dimension", + "px": 1300, + "dp": 650.0 + }, + "padding": { + "$type": "dimension", + "px": 40, + "dp": 20.0 + }, + "border": { + "$type": "dimension", + "px": 2, + "dp": 1.0 + }, + "radius": { + "$type": "dimension", + "px": 22, + "dp": 11.0 + }, + "titleBottom": { + "$type": "dimension", + "px": 16, + "dp": 8.0 + }, + "paragraphBottom": { + "$type": "dimension", + "px": 14, + "dp": 7.0 + }, + "actionsTop": { + "$type": "dimension", + "px": 36, + "dp": 18.0 + }, + "actionGap": { + "$type": "dimension", + "px": 24, + "dp": 12.0 + }, + "progressTop": { + "$type": "dimension", + "px": 30, + "dp": 15.0 + }, + "progressBottom": { + "$type": "dimension", + "px": 22, + "dp": 11.0 + }, + "progressHeight": { + "$type": "dimension", + "px": 12, + "dp": 6.0 + }, + "progressRadius": { + "$type": "dimension", + "px": 8, + "dp": 4.0 + }, + "autoTop": { + "$type": "dimension", + "px": 862, + "dp": 431.0 + }, + "toggleWidth": { + "$type": "dimension", + "px": 80, + "dp": 40.0 + }, + "toggleHeight": { + "$type": "dimension", + "px": 42, + "dp": 21.0 + }, + "toggleThumb": { + "$type": "dimension", + "px": 30, + "dp": 15.0 + }, + "toggleInset": { + "$type": "dimension", + "px": 6, + "dp": 3.0 + }, + "notesHeight": { + "$type": "dimension", + "px": 512, + "dp": 256.0 + }, + "notesTitleBottom": { + "$type": "dimension", + "px": 20, + "dp": 10.0 + }, + "notesGap": { + "$type": "dimension", + "px": 18, + "dp": 9.0 + }, + "notesScrollStep": { + "$type": "dimension", + "px": 80, + "dp": 40.0 + }, + "backTop": { + "$type": "dimension", + "px": 184, + "dp": 92.0 + }, + "scanFraction": { + "$type": "number", + "$value": 0.28 + }, + "scanEnd": { + "$type": "number", + "$value": 4.6 + }, + "sheenAlpha": { + "$type": "number", + "$value": 0.35 + } + } +} From e6ddf1d7e55d6c4538f646cf2841028bea0be343 Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 16:41:07 +0100 Subject: [PATCH 09/18] Show episode ratings and animate title readiness without empty space --- .../wolfskin/tv/TitleRound2Test.kt | 24 ++++- data/tv-spec/spec.md | 2 +- docker/README.md | 13 ++- .../wolfskin/design/TitleHeader.kt | 13 ++- .../justinvisser/wolfskin/design/TitlePage.kt | 11 ++ .../wolfskin/design/TitleState.kt | 2 - .../wolfskin/design/MotionSurfaceTest.kt | 17 ++- .../design/TitleReadinessMotionTest.kt | 100 ++++++++++++++++++ 8 files changed, 159 insertions(+), 23 deletions(-) create mode 100644 wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/TitleReadinessMotionTest.kt diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/TitleRound2Test.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleRound2Test.kt index ff2edf66..91c9387e 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/TitleRound2Test.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleRound2Test.kt @@ -101,22 +101,36 @@ class TitleRound2Test { assertTrue(state.data.playTarget!!.resumeSeconds > 0) rule.onNodeWithTag("title-progress").assertIsDisplayed() rule.onAllNodesWithContentDescription("rtCritics", useUnmergedTree = true).assertCountEquals(1) - rule.onNodeWithText("Ep", useUnmergedTree = true).assertDoesNotExist() + rule.onNodeWithText("Ep", useUnmergedTree = true).assertIsDisplayed() + rule.onAllNodesWithText("7.4", useUnmergedTree = true).assertCountEquals(1) + rule.onNode(hasText("7.4") and hasAnyAncestor(hasTestTag("title-facts")), useUnmergedTree = true).assertIsDisplayed() rule.onNodeWithTag("title-option-seasons").assertDoesNotExist() press(Key.DirectionDown) assertEquals("seasons", state.row) rule.onNode(hasText("Season 1") and hasClickAction()).assertIsDisplayed() } - @Test fun seriesKeepsItsSeasonsShortcutAndSecondaryRequestUsesTheMenu() { + @Test fun seriesUsesDownToReachSeasonsWithoutARedundantShortcut() { render("Andor") - rule.onNodeWithTag("title-option-seasons").assertIsDisplayed() + rule.onNodeWithTag("title-option-seasons").assertDoesNotExist() menu() rule.onNodeWithText("Add for someone").assertIsDisplayed() press(Key.Back) - press(Key.DirectionRight) - press(Key.DirectionCenter) + press(Key.DirectionDown) assertEquals("seasons", state.row) + rule.onNode(hasText("Season 1") and hasClickAction()).assertIsDisplayed() + } + + @Test fun episodeFactsUseTheEpisodeSetRatherThanTheSeriesSet() { + render("episode-episode-1-2025-s1e1", "shared") { data -> + data.copy(item = data.item.copy(ratings = listOf(LibraryRating("rtCritics", 20.0, "Rotten"))), + watchTarget = data.watchTarget.copy(ratings = listOf(LibraryRating("rtCritics", 84.0, "Fresh"), LibraryRating("tmdb", 8.7, episode = true))), + episodes = data.episodes.distinctBy { it.id }) + } + rule.onAllNodesWithText("84%", useUnmergedTree = true).assertCountEquals(1) + rule.onAllNodesWithText("8.7", useUnmergedTree = true).assertCountEquals(1) + rule.onNodeWithText("20%", useUnmergedTree = true).assertDoesNotExist() + rule.onNode(hasText("8.7") and hasAnyAncestor(hasTestTag("title-facts")), useUnmergedTree = true).assertIsDisplayed() } @Test fun episodeSkeletonAndReadySlotsMatchWhileMetadataFitsOneLine() { diff --git a/data/tv-spec/spec.md b/data/tv-spec/spec.md index 913f31f5..7660ed8e 100644 --- a/data/tv-spec/spec.md +++ b/data/tv-spec/spec.md @@ -74,7 +74,7 @@ Row reveals are grouped rather than the browser prototype's per-card staging: th The title page's scroll dim is a draw-only colour overlay, not an alpha-animated full-screen layer. Discover scrolls its backdrop through placement offsets rather than a full-screen translation layer. Initial loading animated layers are Home **2**, Library **up to 3** lazy rows, Discover **2**, title header **1**, person **2**; pending title episode/cast shelves add **1 each**, and each pending Discover lane owns **1**. Deep Home loading is bounded to **4** visible shelf layers. These are animated layers, not independent pulse clocks or every static display-list node: one shared pulse clock drives the loading screen without adding a layer. A hero hand-off adds at most **2** bounded owners (outgoing art and copy). Focus changes can animate **2** card transforms, **1** caption and at most **2** rating plates; artwork fades are painter draws without additional compositing layers. Late title metadata adds at most **4** bounded alpha layers: title ratings, play-target ratings, genres and overview. No animated owner is full-screen. -The series readiness band reserves **56 px (28 dp)** from its first content paint, including when empty or when readiness later disappears. Ratings remain inside the fixed-height facts band. The series header's measured height therefore cannot change when late ratings/readiness arrive; overview, actions, season and episode anchors retain their coordinates. Skeletons have no click/hover focus targets; pending episode/cast rows remain absent from the key-navigation state until real cards exist. Initial loading keeps nav focus and Back still pops the title/person route. +The approved title follow-up (2026-11-07) supersedes the fixed readiness reservation: an absent readiness line occupies **0 px**, while a present line occupies **56 px (28 dp)**. Late arrival/removal animates that height over the **200 ms late-line duration with token ease-out**; reduced motion snaps. Overview, actions and following rows move monotonically with that band; an already-pinned focused row stays pinned through same-remeasure scroll compensation. Ratings remain inside the fixed-height facts band and appear once: an explicit episode page uses its opened episode's own set, including the episode score, rather than the series-only set. Series and episode pages have no redundant Seasons shortcut; Down reaches the season chips. Skeletons have no click/hover focus targets; pending episode/cast rows remain absent from the key-navigation state until real cards exist. Initial loading keeps nav focus and Back still pops the title/person route. Discover key traversal skips pending lanes in both directions. If every remaining lane is pending, Down stays on the real filter chips and Back returns to nav; a skeleton must never create an empty-column focus range. diff --git a/docker/README.md b/docker/README.md index 5198772e..c8dae34c 100644 --- a/docker/README.md +++ b/docker/README.md @@ -648,7 +648,10 @@ retain the approved frames except for the requested feedback changes: Focused summaries ellipsise to one line, the show-name overlay is absent, and `S1 E3 · duration` plus the watched check share one line. Ready title headers measure their copy/actions and leave 40 px before the - following section; series retain the empty 56 px readiness reservation. + following section. Missing readiness lines collapse completely on every title + kind; late lines expand/collapse over the 200 ms late-line token with ease-out, + or snap with reduced motion. Already-pinned rows compensate in the same + remeasure rather than bouncing through a second focus-follow animation. Poster-only movies floor that stack so Cast circles clear the poster by at least 20 px, including held movie fallbacks and short overviews. - Every Discover heading uses a 104 px band, including a 60 px title-to-card @@ -720,9 +723,11 @@ the motion ease-out token, with reduced-motion fades capped at 80 ms. Only the bounded menu panel owns an alpha layer; the scrim is static. Opening another sheet immediately removes the menu panel and scrim, preventing double darkening. An empty menu closes if its last permitted action disappears. Controls -use the shared 4 px straddle focus ring. Episode details omit the redundant -Seasons shortcut; series pages retain it. Ratings appear only in the header -facts line, not again beside progress, on movie, series and episode pages. +use the shared 4 px straddle focus ring. Neither series nor episode details have +a redundant Seasons shortcut; Down reaches the season chips directly. Ratings +appear only in the header facts line, not again beside progress. Explicit episode +pages use the opened episode's own set, including its `Ep` score; movie and series +pages keep their own sets. Episode shelf skeletons use the same width, height and pitch as ready cards. Person filmography and related-title shelves remain posters; Home continuation diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleHeader.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleHeader.kt index 85c224bf..f7cfe54f 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleHeader.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleHeader.kt @@ -1,5 +1,9 @@ package org.justinvisser.wolfskin.design +import androidx.compose.animation.core.animateDpAsState +import androidx.compose.animation.core.tween +import androidx.compose.runtime.getValue +import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.layout.boundsInRoot import androidx.compose.ui.platform.testTag @@ -35,6 +39,11 @@ import org.justinvisser.wolfskin.design.WolfskinTokens.Title as D fun TitleHeader(state: TitleState, active: Boolean, modifier: Modifier = Modifier) { if (state.data.status == TitleReadStatus.Loading) { TitleHeaderSkeleton(modifier); return } val item = state.data.item + val factsItem = state.data.watchTarget.takeIf { it.kind == "episode" } ?: item + val readinessHeight by animateDpAsState( + if (state.data.requestedStage == null) WolfskinTokens.Shell.zero else WolfskinTokens.Motion.readinessSlot, + tween(if (reducedMotion()) 0 else WolfskinTokens.Motion.lateLineFade, easing = WolfskinTokens.Motion.easeOut), + label = "title-readiness-height") val episode = when { state.row == "episodes" -> state.data.episodes.getOrNull(state.column) state.data.watchTarget.kind == "episode" -> state.data.watchTarget @@ -56,10 +65,10 @@ fun TitleHeader(state: TitleState, active: Boolean, modifier: Modifier = Modifie item.year?.let { Text(it.toString(), color = C.muted, style = TitleTextStyles.body, modifier = Modifier.exactLineBox(TitleTextStyles.body)) } if (item.kind == "movie" && item.runtimeSeconds > 0) Text(item.runtime, color = C.muted, style = TitleTextStyles.body, modifier = Modifier.exactLineBox(TitleTextStyles.body)) if (item.kind == "tv" && item.seasons > 0) Text("${item.seasons} season${if (item.seasons == 1) "" else "s"}", color = C.muted, style = TitleTextStyles.body, modifier = Modifier.exactLineBox(TitleTextStyles.body)) - if (state.data.connection != TitleConnection.SignedOut) TitleRatings(item.ratings) + if (state.data.connection != TitleConnection.SignedOut) TitleRatings(factsItem.ratings) if (item.genres.isNotEmpty()) Text(item.genres.take(3).joinToString(", "), color = C.muted, style = TitleTextStyles.body, modifier = Modifier.exactLineBox(TitleTextStyles.body).lateLineFade(item.genres)) } - Box(Modifier.fillMaxWidth().height(if (item.kind == "tv" || state.data.requestedStage != null) WolfskinTokens.Motion.readinessSlot else WolfskinTokens.Shell.zero).testTag("title-readiness-slot")) { + Box(Modifier.fillMaxWidth().height(readinessHeight).clipToBounds().testTag("title-readiness-slot")) { state.data.requestedStage?.let { stage -> val color = when (stage) { "Ready" -> C.ok; "Failed" -> C.fail; "Downloading", "Almost ready" -> C.accent; else -> C.muted } Row(Modifier.exactLineBox(TitleTextStyles.dLine, bottom = D.lineGap).lateLineFade(stage), horizontalArrangement = Arrangement.spacedBy(L.navItemGap), verticalAlignment = Alignment.CenterVertically) { diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePage.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePage.kt index 4a79a147..c423ad3e 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePage.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitlePage.kt @@ -120,7 +120,18 @@ fun TitlePage(state: TitleState, shell: ShellState, modifier: Modifier = Modifie val position by remember(list, rowOffsets) { derivedStateOf { rowOffsets[list.firstVisibleItemIndex.coerceAtMost(rowOffsets.lastIndex)] + list.firstVisibleItemScrollOffset } } + val headerPixels = with(density) { headerHeight.roundToPx() } + val previousHeaderPixels = remember(list, item.id, density) { intArrayOf(headerPixels) } + val compensateHeader = previousHeaderPixels[0] != headerPixels && !shell.navFocused && !list.isScrollInProgress && + list.firstVisibleItemIndex == 0 && list.firstVisibleItemScrollOffset > 0 && + list.layoutInfo.visibleItemsInfo.any { it.key == state.row && kotlin.math.abs(it.offset - with(density) { L.pinnedLine.roundToPx() }) <= 1 } + // Compensate in the same remeasure; an asynchronous scroll would chase the animated header. + androidx.compose.runtime.SideEffect { + if (compensateHeader) list.requestScrollToItem(0, (list.firstVisibleItemScrollOffset + headerPixels - previousHeaderPixels[0]).coerceAtLeast(0)) + previousHeaderPixels[0] = headerPixels + } LaunchedEffect(state.row, shell.navFocused, state.data.status, displayedRows, rowOffsets) { + if (compensateHeader) return@LaunchedEffect if (state.data.status == TitleReadStatus.Loading) shell.focusNav(shell.currentTab) val index = if (shell.navFocused) 0 else displayedRows.indexOf(state.row).coerceAtLeast(0) val y = rowOffsets[index] diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleState.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleState.kt index fad34b31..1d363e19 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleState.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/TitleState.kt @@ -193,7 +193,6 @@ class TitleState( "menu" -> { sheetIndex = 0; sheet = TitleSheet.Menu } "watched" -> if (data.watchTarget.kind == "tv") { sheetIndex = 0; sheet = TitleSheet.ConfirmWatched } else toggleWatched() "trailer" -> data.trailerUrl?.let { onAction(TitleAction.Trailer(it)) } - "seasons" -> focus("seasons", data.seasonNumbers.indexOf(season).coerceAtLeast(0)) "retry" -> onAction(TitleAction.Retry) "back" -> onAction(TitleAction.Pop) "request", "add" -> onAction(TitleAction.Request(data.item, id != "request")) @@ -302,7 +301,6 @@ fun titleOptions(state: TitleState): List = buildList { add(TitleOption("watched", "Mark ${if (series) "series " else ""}as ${if (state.watched) "unwatched" else "watched"}", if (state.watched) "eye" else "eyeoff", if (data.watchTarget.kind == "episode") data.watchTarget.episodeLabel else "", on = state.watched)) if (data.trailerUrl != null) add(TitleOption("trailer", "Play trailer", "trailer")) if (target != null || (data.connection == TitleConnection.SignedIn && data.requestsAllowed)) add(TitleOption("menu", "Menu", "more")) - if (item.kind == "tv" && item.seasons > 0 && data.watchTarget.kind != "episode") add(TitleOption("seasons", "Seasons", "tv", icon = false)) } else if (data.connection != TitleConnection.SignedIn || !data.requestsAllowed) { add(TitleOption("retry", "Try again", "wifi", primary = true, icon = false)) } else { diff --git a/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/MotionSurfaceTest.kt b/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/MotionSurfaceTest.kt index 12d6ddad..47dac75a 100644 --- a/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/MotionSurfaceTest.kt +++ b/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/MotionSurfaceTest.kt @@ -44,20 +44,19 @@ class MotionSurfaceTest { @get:Rule val rule = createAndroidComposeRule(effectContext = animatorScale) private val viewer = ShellPerson("justin", "Justin", "J", false) - @Test fun lateSeriesReadinessAndRatingsLeaveActionsOverviewAndEpisodesAtTheSameCoordinates() { + @Test fun reducedMotionReadinessSnapsAndRemovingItRestoresTheCollapsedStack() { val shell = shell() val series = TitleItem("series", "A series", "tv", seasons = 2, held = true, overview = "Series overview") val episode = TitleItem("episode", "Pilot", "episode", season = 1, episode = 1, overview = "Episode overview") val state = TitleState(TitlePageData(series, playTarget = episode, episodes = listOf(episode), connection = TitleConnection.SignedIn), viewer) {} - rule.setContent { WolfskinTheme { TitleSurface(state, shell, Modifier.requiredSize(960.dp, 540.dp)) } } - rule.waitForIdle() + rule.setContent { CompositionLocalProvider(LocalReducedMotion provides true) { WolfskinTheme { TitleSurface(state, shell, Modifier.requiredSize(960.dp, 540.dp)) } } } val before = bounds() - for (stage in listOf("Ready", "Downloading", null)) { - rule.runOnIdle { state.update(state.data.copy(requestedStage = stage, requestActor = "Mindel", item = series.copy(ratings = listOf(LibraryRating("rt", 88.0))))) } - rule.mainClock.advanceTimeBy(3400) - rule.waitForIdle() - assertEquals("Late metadata cannot change reserved header geometry", before, bounds()) - } + assertEquals(0f, rule.onNodeWithTag("title-readiness-slot").fetchSemanticsNode().boundsInRoot.height, 0.1f) + rule.runOnIdle { state.update(state.data.copy(requestedStage = "Ready", requestActor = "Mindel")) } + assertEquals(56f, rule.onNodeWithTag("title-readiness-slot").fetchSemanticsNode().boundsInRoot.height, 0.1f) + bounds().zip(before).forEach { (after, initial) -> assertEquals(56f, after.top - initial.top, 1f) } + rule.runOnIdle { state.update(state.data.copy(requestedStage = null)) } + assertEquals(before, bounds()) } @Test fun titleSkeletonIgnoresDownAndBackPopsWithoutOpeningThePicker() { diff --git a/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/TitleReadinessMotionTest.kt b/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/TitleReadinessMotionTest.kt new file mode 100644 index 00000000..01bc734a --- /dev/null +++ b/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/TitleReadinessMotionTest.kt @@ -0,0 +1,100 @@ +package org.justinvisser.wolfskin.design + +import android.app.Application +import androidx.activity.ComponentActivity +import androidx.compose.foundation.layout.requiredSize +import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.MotionDurationScale +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.onRoot +import androidx.compose.ui.unit.dp +import com.github.takahirom.roborazzi.captureRoboImage +import org.junit.Assert.* +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode +import java.io.File + +/** Readiness changes move real title content continuously, without reserving an empty band. */ +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [34], application = Application::class, qualifiers = "w960dp-h540dp-xhdpi") +@GraphicsMode(GraphicsMode.Mode.NATIVE) +class TitleReadinessMotionTest { + private val animatorScale = object : MotionDurationScale { override var scaleFactor by mutableFloatStateOf(1f) } + @get:Rule val rule = createAndroidComposeRule(effectContext = animatorScale) + private lateinit var state: TitleState + + private fun render() { + val viewer = ShellPerson("justin", "Justin", "J", false) + val shell = ShellState(listOf(viewer), viewer.key).apply { pickerVisible = false; pickerLaunch = false; enterDestination("title/series") } + val series = TitleItem("series", "A series", "tv", seasons = 1, held = true, overview = "A series overview") + val episode = TitleItem("episode", "Pilot", "episode", held = true, season = 1, episode = 1, overview = "Episode overview") + state = TitleState(TitlePageData(series, playTarget = episode, episodes = listOf(episode), connection = TitleConnection.SignedIn), viewer) {} + rule.setContent { WolfskinTheme { TitleSurface(state, shell, Modifier.requiredSize(960.dp, 540.dp)) } } + rule.mainClock.advanceTimeBy(500) + rule.waitForIdle() + } + + private fun positions(): List = listOf("title-readiness-slot", "title-overview", "title-actions", "title-shelf:episodes").mapIndexed { index, tag -> + val bounds = rule.onNodeWithTag(tag).fetchSemanticsNode().boundsInRoot + if (index == 0) bounds.height else bounds.top + } + + private fun frames(stage: String?, name: String, count: Int = 22): List> { + val directory = File(requireNotNull(System.getProperty("wolfskin.captureDirectory")), "title-readiness-motion/$name").apply { mkdirs() } + rule.runOnIdle { state.update(state.data.copy(requestedStage = stage, requestActor = "Justin")); androidx.compose.runtime.snapshots.Snapshot.sendApplyNotifications() } + val values = List(count) { index -> + rule.waitForIdle() + positions().also { + rule.onRoot().captureRoboImage(File(directory, "${index.toString().padStart(2, '0')}.png").absolutePath) + rule.mainClock.advanceTimeBy(16) + rule.waitForIdle() + } + } + File(directory, "samples.csv").writeText("timeMs,slotHeightPx,overviewTopPx,actionsTopPx,episodesTopPx\n" + values.mapIndexed { index, row -> "${index * 16},${row.joinToString(",")}" }.joinToString("\n")) + return values + } + + @Test fun lateReadinessExpansionAndRemovalStayMonotonicAndMoveTheWholeStack() { + render() + val collapsed = positions() + assertEquals(0f, collapsed[0], 0.1f) + rule.mainClock.autoAdvance = false + val opening = frames("Ready", "expand") + val expanded = opening.last() + assertEquals(56f, expanded[0], 0.1f) + expanded.drop(1).zip(collapsed.drop(1)).forEach { (after, before) -> assertEquals(56f, after - before, 1f) } + val closing = frames(null, "collapse") + assertEquals(collapsed, closing.last()) + for ((samples, direction) in listOf(opening to 1f, closing to -1f)) { + samples.zipWithNext().forEach { (before, after) -> before.zip(after).forEach { (first, second) -> + assertTrue("Readiness content must not reverse or overshoot: $samples", (second - first) * direction >= -0.1f) + assertTrue("Height change must not jump in one frame", kotlin.math.abs(second - first) < 56f) + } } + samples.forEach { assertTrue(it[0] in 0f..56f) } + } + assertFalse(state.options.any { it.id == "seasons" }) + rule.mainClock.autoAdvance = true + } + + @Test fun aPinnedEpisodeShelfDoesNotBounceWhenReadinessChangesAboveIt() { + render() + rule.runOnIdle { state.focus("episodes", 0) } + rule.mainClock.advanceTimeBy(500) + rule.waitForIdle() + val pinned = positions().last() + rule.mainClock.autoAdvance = false + for (samples in listOf(frames("Ready", "pinned", count = 34), frames(null, "pinned-collapse", count = 34))) { + samples.forEach { assertEquals("A header change cannot bounce a pinned focused shelf", pinned, it.last(), 1f) } + } + assertEquals("episodes", state.row) + rule.mainClock.autoAdvance = true + } +} From ee3f3ae11ec266ed002abf786212c4d823670224 Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 16:55:14 +0100 Subject: [PATCH 10/18] Preserve check state after refreshing installed identity --- .../org/justinvisser/wolfskin/tv/UpdatesCaptureTest.kt | 10 ++++++++++ .../justinvisser/wolfskin/tv/update/UpdatesScreen.kt | 7 +++++-- .../java/org/justinvisser/wolfskin/design/Identity.kt | 9 +++++++-- .../java/org/justinvisser/wolfskin/design/NavBar.kt | 3 ++- .../org/justinvisser/wolfskin/design/SettingsList.kt | 2 +- .../org/justinvisser/wolfskin/design/WolfskinTokens.kt | 1 + wolfskin-design/tokens.css | 1 + wolfskin-design/tokens.sha256 | 6 +++--- wolfskin-design/update-tokens.json | 1 + 9 files changed, 31 insertions(+), 9 deletions(-) diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/UpdatesCaptureTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/UpdatesCaptureTest.kt index e6643fd7..347c3855 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/UpdatesCaptureTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/UpdatesCaptureTest.kt @@ -15,6 +15,7 @@ import androidx.compose.ui.test.onRoot import androidx.compose.ui.test.performKeyInput import androidx.compose.ui.test.pressKey import androidx.compose.ui.input.key.Key +import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.semantics.SemanticsProperties import com.github.takahirom.roborazzi.captureRoboImage import java.io.File @@ -141,6 +142,15 @@ class UpdatesCaptureTest { assertEquals(1, (shell.contentFocus as UpdateFocus).actionIndex) } + @Test fun refreshingInstalledIdentityCannotMaskAnOngoingCheck() { + launch(UpdateUiState.UpToDate) + rule.runOnIdle { controller.showInstalled(InstalledVersion("1.1.1", 100001)) } + rule.mainClock.advanceTimeBy(320) + rule.runOnIdle { controller.show(UpdateUiState.Checking) } + rule.mainClock.advanceTimeBy(320) + rule.onNodeWithTag("update-progress").assertIsDisplayed() + } + @Test fun nativeProgressAndStateTransitionAtSixteenMillisecondFrames() { launch(UpdateUiState.Checking) val target = directory diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt index ea69c6f7..a33341aa 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt @@ -51,6 +51,7 @@ import org.justinvisser.wolfskin.design.focusRing import org.justinvisser.wolfskin.design.focusScale import org.justinvisser.wolfskin.design.motionDuration import org.justinvisser.wolfskin.design.reducedMotion +import org.justinvisser.wolfskin.design.resolveUpdateAvatarColor import org.justinvisser.wolfskin.design.rowReveal import org.justinvisser.wolfskin.design.WolfskinTokens.Color as C import org.justinvisser.wolfskin.design.WolfskinTokens.Layout as L @@ -68,7 +69,9 @@ fun UpdatesScreen(shell: ShellState, controller: UpdateController, onBack: () -> val autoCheck by controller.autoCheck.collectAsStateWithLifecycle() val initialInstalled = remember { installed.versionName } val updatedVersion = installed.versionName.takeIf { it != initialInstalled } - val presentation = presentUpdate(if (updatedVersion != null) UpdateUiState.UpToDate else state, release, updatedVersion) + val presentation = remember(state, release, updatedVersion) { + presentUpdate(state, release, updatedVersion.takeIf { state == UpdateUiState.UpToDate }) + } val scroll = rememberScrollState() val scope = rememberCoroutineScope() val density = LocalDensity.current @@ -90,7 +93,7 @@ fun UpdatesScreen(shell: ShellState, controller: UpdateController, onBack: () -> Box(modifier.fillMaxSize().testTag("updates-screen")) { Row(Modifier.offset(L.safeSide, U.headerTop).height(U.headerHeight), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(S.settingsHeaderGap)) { - Avatar(shell.person, S.settingsHeaderAvatar, T.avatarLetterLibHeader, letterColor = C.muted) + Avatar(shell.person, S.settingsHeaderAvatar, T.avatarLetterLibHeader, letterColor = C.muted, backgroundColor = resolveUpdateAvatarColor(shell.person)) Text("Updates", Modifier.alignByBaseline().exactLineBox(T.screenTitle), style = T.screenTitle, color = C.fg) Text("Installed ${installed.versionName}", Modifier.alignByBaseline(), style = T.nav.copy(fontWeight = androidx.compose.ui.text.font.FontWeight.Normal), color = C.muted) } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/Identity.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/Identity.kt index d7c5570f..6aec4bf2 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/Identity.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/Identity.kt @@ -21,6 +21,10 @@ fun personColor(key: String): Color = when (key.lowercase()) { else -> WolfskinTokens.Color.accent } +/** Updates has its own locked avatar swatch; other destinations retain household colours. */ +fun resolveUpdateAvatarColor(person: ShellPerson): Color = + if (person.key.equals("justin", ignoreCase = true)) WolfskinTokens.Update.avatarJustin else personColor(person.key) + /** The same mark anchors the picker and the persistent navigation. */ @Composable fun Wordmark(modifier: Modifier = Modifier, prefix: String = "Wolf", textStyle: TextStyle = WolfskinTokens.Type.wordmark) { @@ -32,8 +36,9 @@ fun Wordmark(modifier: Modifier = Modifier, prefix: String = "Wolf", textStyle: /** Initials are drawn over opaque person colour at the exact slot size. */ @Composable -fun Avatar(person: ShellPerson, diameter: Dp, textStyle: TextStyle, modifier: Modifier = Modifier, letterColor: Color = WolfskinTokens.Color.onFocus) { - Box(modifier.size(diameter).background(personColor(person.key), CircleShape), contentAlignment = Alignment.Center) { +fun Avatar(person: ShellPerson, diameter: Dp, textStyle: TextStyle, modifier: Modifier = Modifier, letterColor: Color = WolfskinTokens.Color.onFocus, + backgroundColor: Color = personColor(person.key)) { + Box(modifier.size(diameter).background(backgroundColor, CircleShape), contentAlignment = Alignment.Center) { Text(person.initial, color = letterColor, style = textStyle) } } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/NavBar.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/NavBar.kt index 929fce42..e30392ae 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/NavBar.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/NavBar.kt @@ -117,6 +117,7 @@ fun NavBar(state: ShellState, scrolled: Boolean, modifier: Modifier = Modifier) Modifier.offset(avatar.left, avatar.top) .focusRing(avatarFocused, L.navAvatar / 2, WolfskinTokens.Focus.ringAvatarRing) .focusProperties { canFocus = false } - .clickable { state.focusNav(state.tabs.size); state.key(ShellKey.Ok) }) + .clickable { state.focusNav(state.tabs.size); state.key(ShellKey.Ok) }, + backgroundColor = if (hasSelectedTab) personColor(state.person.key) else resolveUpdateAvatarColor(state.person)) } } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/SettingsList.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/SettingsList.kt index 15c47744..e04c344f 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/SettingsList.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/SettingsList.kt @@ -70,7 +70,7 @@ fun SettingsList(state: ShellState, modifier: Modifier = Modifier, requestCount: Box(modifier.fillMaxSize()) { Row(Modifier.offset(L.safeSide, WolfskinTokens.Update.headerTop).height(WolfskinTokens.Update.headerHeight), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(S.settingsHeaderGap)) { - Avatar(state.person, S.settingsHeaderAvatar, T.avatarLetterLibHeader, letterColor = C.muted) + Avatar(state.person, S.settingsHeaderAvatar, T.avatarLetterLibHeader, letterColor = C.muted, backgroundColor = resolveUpdateAvatarColor(state.person)) Text("Settings", Modifier.alignByBaseline().exactLineBox(T.screenTitle), style = T.screenTitle, color = C.fg) Text("This TV · ${state.person.name}", Modifier.alignByBaseline(), style = T.nav.copy(fontWeight = FontWeight.Normal), color = C.muted) } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt index 0cfda025..bb8cfdc6 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt @@ -702,6 +702,7 @@ object WolfskinTokens { const val ambientBrightness = 0.55f } object Update { + val avatarJustin = ComposeColor(0xFF7AB8FF) val heading = TextStyle(fontSize = 18.0.sp, fontWeight = FontWeight(800), lineHeight = 20.160000000000004.sp, letterSpacing = -0.02.em) const val settingsVisibleRows = 6.0f val headerTop = 75.0.dp diff --git a/wolfskin-design/tokens.css b/wolfskin-design/tokens.css index ef0f40c6..fdc284bd 100644 --- a/wolfskin-design/tokens.css +++ b/wolfskin-design/tokens.css @@ -516,6 +516,7 @@ --discover-stageGap: 10.0px; --discover-ambientInset: 80.0px; --discover-ambientBlur: 60.0px; + --update-avatarJustin: #7ab8ff; --update-heading: 36.0px; --update-headerTop: 150.0px; --update-headerHeight: 84.0px; diff --git a/wolfskin-design/tokens.sha256 b/wolfskin-design/tokens.sha256 index ef997d43..ae81afd2 100644 --- a/wolfskin-design/tokens.sha256 +++ b/wolfskin-design/tokens.sha256 @@ -2,8 +2,8 @@ b3f096b692c395534177cc82ac68f5b801870bc7e28f0dd5cd7c17e2103920a3 discover-token 993d933950e17fb72d0902ffc440e1e4ed4dc088c96a8d12974431c77dc31634 generate_tokens.py 25985087986a46f00e2819917d0421ff2b437ec21c54f6ce6412b84c0eb05302 home-tokens.json be3af0ddcb0d67abef0805d19d7a33cdb55428bcace656b50f0a38935f212028 shell-tokens.json -18c08c6f4d77ee0690e63ec2e1ce14854eced539746c41c948942460b37a38b2 src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt +289935944db0aa2f43224d7532331ad9ac5c666dbe40f1c44c9b7ee725f972ad src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt e0a2f5df2f249bce3f6e13f4a0320c7b18b85777eaf04a27a428d6683a6aad28 title-tokens.json -eed527dac5e09b209619cd67990556a5f9223d05e7e2516f300cb4760a198ca7 tokens.css +5fa37cdbb5ab1bf0dbb0f83b8facabcd601ffb22492ad54f8aa9fc86cb729ee4 tokens.css 2e5e0476341adec1ec05331af38bc67cd02ba013a0988aea40a70eff21513264 tokens.json -824cb58d1507bc05212323ecfa66664f8b2bde23438940eed8717266161cac55 update-tokens.json +20c17f4e980baccce555b0cff8f76a2cfbc0db4e88d5a11f43abf73f0d936eb2 update-tokens.json diff --git a/wolfskin-design/update-tokens.json b/wolfskin-design/update-tokens.json index 35dc1a1f..b5e59c6f 100644 --- a/wolfskin-design/update-tokens.json +++ b/wolfskin-design/update-tokens.json @@ -1,5 +1,6 @@ { "update": { + "avatarJustin": {"$type": "color", "$value": "#7ab8ff"}, "heading": { "$type": "typography", "$value": {"fontWeight": 800}, From 2b8c729f628a3ccef3fdf8eeac405bebc68f6535 Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 17:17:20 +0100 Subject: [PATCH 11/18] Compile updater fixtures through the existing app test source set --- .../damontecres/wholphin/ui/TestModule.kt | 5 ++++ .../tv/{ => update}/UpdateBehaviorTest.kt | 3 +-- .../tv/{ => update}/UpdatesCaptureTest.kt | 27 +++++++++---------- .../wolfskin/tv/update/UpdatesScreen.kt | 18 ++++++++----- .../wolfskin/design/WolfskinTokens.kt | 5 +++- wolfskin-design/tokens.css | 5 +++- wolfskin-design/tokens.sha256 | 6 ++--- wolfskin-design/update-tokens.json | 9 +++---- 8 files changed, 45 insertions(+), 33 deletions(-) rename app/src/test/java/org/justinvisser/wolfskin/tv/{ => update}/UpdateBehaviorTest.kt (98%) rename app/src/test/java/org/justinvisser/wolfskin/tv/{ => update}/UpdatesCaptureTest.kt (90%) diff --git a/app/src/test/java/com/github/damontecres/wholphin/ui/TestModule.kt b/app/src/test/java/com/github/damontecres/wholphin/ui/TestModule.kt index 3b4d3efa..6fb56cd0 100644 --- a/app/src/test/java/com/github/damontecres/wholphin/ui/TestModule.kt +++ b/app/src/test/java/com/github/damontecres/wholphin/ui/TestModule.kt @@ -73,6 +73,11 @@ import javax.inject.Singleton object TestModule { val testDispatcher = StandardTestDispatcher() + @Provides + @Singleton + fun updateController(): org.justinvisser.wolfskin.tv.update.UpdateController = + org.justinvisser.wolfskin.tv.update.FakeUpdateController() + @Provides @Singleton fun deviceInfo( diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/UpdateBehaviorTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdateBehaviorTest.kt similarity index 98% rename from app/src/test/java/org/justinvisser/wolfskin/tv/UpdateBehaviorTest.kt rename to app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdateBehaviorTest.kt index 72c07539..561b625a 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/UpdateBehaviorTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdateBehaviorTest.kt @@ -1,10 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-only -package org.justinvisser.wolfskin.tv +package org.justinvisser.wolfskin.tv.update import org.junit.Assert.* import org.junit.Test import org.justinvisser.wolfskin.design.ShellKey -import org.justinvisser.wolfskin.tv.update.* /** Behavior boundaries are controller outcomes, not incidental UI wording. */ class UpdateBehaviorTest { diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/UpdatesCaptureTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdatesCaptureTest.kt similarity index 90% rename from app/src/test/java/org/justinvisser/wolfskin/tv/UpdatesCaptureTest.kt rename to app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdatesCaptureTest.kt index 347c3855..951e0eba 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/UpdatesCaptureTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdatesCaptureTest.kt @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -package org.justinvisser.wolfskin.tv +package org.justinvisser.wolfskin.tv.update import android.app.Application import android.view.View @@ -25,7 +25,6 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.justinvisser.wolfskin.design.* -import org.justinvisser.wolfskin.tv.update.* import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config import org.robolectric.annotation.GraphicsMode @@ -78,7 +77,7 @@ class UpdatesCaptureTest { rule.onRoot().captureRoboImage(file.absolutePath) } - private fun press(vararg keys: Key) { + private fun press(keys: List) { keys.forEach { key -> rule.onNodeWithTag("wolfskin-shell").performKeyInput { pressKey(key) } } rule.mainClock.advanceTimeBy(320) rule.waitForIdle() @@ -87,7 +86,7 @@ class UpdatesCaptureTest { @Test fun settings() { launch(UpdateUiState.Checking, settings = true); capture("settings") } @Test fun classic() { launch(UpdateUiState.Checking, settings = true) - repeat(8) { press(Key.DirectionDown) } + repeat(8) { press(listOf(Key.DirectionDown)) } assertEquals(9, shell.settingsRow) assertEquals(4, shell.view.listState.firstVisibleItemIndex) capture("classic") @@ -95,8 +94,8 @@ class UpdatesCaptureTest { @Test fun checking() { launch(UpdateUiState.Checking); capture("checking") } @Test fun current() { launch(UpdateUiState.UpToDate); capture("current") } @Test fun available() { launch(updateReleaseFixture()); capture("available") } - @Test fun notes() { launch(updateReleaseFixture()); press(Key.DirectionRight); capture("notes") } - @Test fun notesOpen() { launch(updateReleaseFixture()); press(Key.DirectionRight, Key.DirectionCenter); capture("notes-open") } + @Test fun notes() { launch(updateReleaseFixture()); press(listOf(Key.DirectionRight)); capture("notes") } + @Test fun notesOpen() { launch(updateReleaseFixture()); press(listOf(Key.DirectionRight, Key.DirectionCenter)); capture("notes-open") } @Test fun downloading() { launch(UpdateUiState.Downloading(20_100_000, 47_800_000)); capture("downloading") } @Test fun ready() { launch(UpdateUiState.Ready("1.1.1")); capture("ready") } @Test fun permission() { launch(UpdateUiState.PermissionNeeded); capture("permission") } @@ -107,8 +106,8 @@ class UpdatesCaptureTest { @Test fun noInstaller() { launch(UpdateUiState.NoInstaller); capture("no-installer") } @Test fun noReleasePublished() { launch(UpdateUiState.NoReleasePublished); capture("no-release") } @Test fun unknownDownloadLength() { launch(UpdateUiState.Downloading(20_100_000, null)); capture("unknown-total") } - @Test fun autoOn() { launch(updateReleaseFixture()); press(Key.DirectionDown); capture("auto-on") } - @Test fun autoOff() { launch(updateReleaseFixture()); press(Key.DirectionDown, Key.DirectionCenter); capture("auto-off") } + @Test fun autoOn() { launch(updateReleaseFixture()); press(listOf(Key.DirectionDown)); capture("auto-on") } + @Test fun autoOff() { launch(updateReleaseFixture()); press(listOf(Key.DirectionDown, Key.DirectionCenter)); capture("auto-off") } @Test fun updated() { launch(UpdateUiState.UpToDate) rule.runOnIdle { controller.showInstalled(InstalledVersion("1.1.1", 100001)) } @@ -118,14 +117,14 @@ class UpdatesCaptureTest { @Test fun notesTrapRealKeysAndBackPreservesSettingsRowAndScroller() { launch(updateReleaseFixture()) - press(Key.DirectionRight, Key.DirectionCenter, Key.DirectionUp, Key.DirectionRight, Key.DirectionDown) + press(listOf(Key.DirectionRight, Key.DirectionCenter, Key.DirectionUp, Key.DirectionRight, Key.DirectionDown)) assertTrue(shell.contentOverlayVisible) assertFalse(shell.navFocused) assertTrue(controller.autoCheck.value) - press(Key.Back) + press(listOf(Key.Back)) assertFalse(shell.contentOverlayVisible) assertEquals(1, (shell.contentFocus as UpdateFocus).actionIndex) - press(Key.Back) + press(listOf(Key.Back)) assertEquals("settings", shell.route) assertEquals(1, shell.settingsRow) assertEquals(0, shell.view.listState.firstVisibleItemIndex) @@ -133,12 +132,12 @@ class UpdatesCaptureTest { @Test fun longNotesScrollWithoutEscapingToNavOrAutoCheck() { launch(updateReleaseFixture().copy(notes = (1..30).joinToString("\n") { "Release detail $it" })) - press(Key.DirectionRight, Key.DirectionCenter, Key.DirectionDown, Key.DirectionDown) + press(listOf(Key.DirectionRight, Key.DirectionCenter, Key.DirectionDown, Key.DirectionDown)) val range = rule.onNodeWithTag("update-notes").fetchSemanticsNode().config[SemanticsProperties.VerticalScrollAxisRange] assertTrue(range.value() > 0f) assertFalse(shell.navFocused) assertFalse((shell.contentFocus as UpdateFocus).autoFocused) - press(Key.Back) + press(listOf(Key.Back)) assertEquals(1, (shell.contentFocus as UpdateFocus).actionIndex) } @@ -167,7 +166,7 @@ class UpdatesCaptureTest { if (target != null) { repeat(101) { frame -> rule.mainClock.advanceTimeBy(16); capture("motion/download-%03d".format(frame)) } } - press(Key.DirectionDown) + press(listOf(Key.DirectionDown)) rule.runOnIdle { controller.show(UpdateUiState.Downloading(31_000_000, 47_800_000)) } rule.mainClock.advanceTimeBy(16) assertTrue((shell.contentFocus as UpdateFocus).autoFocused) diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt index a33341aa..725f591a 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt @@ -165,18 +165,22 @@ private fun AutoCheckRow(enabled: Boolean, focused: Boolean, modifier: Modifier, @Composable private fun NotesPanel(release: UpdateUiState.Available?, scroll: androidx.compose.foundation.ScrollState) { val shape = RoundedCornerShape(U.radius) - Column(Modifier.offset(L.safeSide, U.contentTop).size(U.width, U.notesHeight).testTag("update-notes") + val paragraphs = remember(release?.notes) { release?.notes?.lineSequence()?.filter { it.isNotBlank() }?.toList().orEmpty() } + val notesStyle = T.nav.copy(fontWeight = androidx.compose.ui.text.font.FontWeight.Normal) + CssColumn(Modifier.offset(L.safeSide, U.contentTop).size(U.width, U.notesHeight).testTag("update-notes") .focusRing(true, U.radius, WolfskinTokens.Focus.ringControlRing) .background(C.surface, shape).border(U.border, C.border, shape) .verticalScroll(scroll).padding(U.padding + U.border)) { Text(updateMetadata(release), Modifier.exactLineBox(T.stateTitle), style = T.stateTitle.copy(fontWeight = androidx.compose.ui.text.font.FontWeight.Bold), color = C.fg) - Spacer(Modifier.height(U.notesTitleBottom)) - release?.notes?.lineSequence()?.filter { it.isNotBlank() }?.forEach { paragraph -> - Row(Modifier.padding(vertical = U.notesGap / 2)) { - Text("•", Modifier.width(U.padding / 2), style = T.nav, color = C.muted) - Text(paragraph.removePrefix("- "), Modifier.exactLineBox(T.nav), style = T.nav.copy(fontWeight = androidx.compose.ui.text.font.FontWeight.Normal), color = C.muted) + Spacer(Modifier.height(U.notesListTop)) + paragraphs.forEachIndexed { index, paragraph -> + Row(Modifier.padding(start = U.notesMarkerOffset).exactLineBox(notesStyle)) { + Text("•", Modifier.width(U.notesMarkerWidth).exactLineBox(notesStyle), style = notesStyle, color = C.muted) + Text(paragraph.removePrefix("- "), Modifier.exactLineBox(notesStyle), style = notesStyle, color = C.muted) } + if (index != paragraphs.lastIndex) Spacer(Modifier.height(U.notesGap)) } - Text("Sign-in stays on this TV. Android asks before installing.", Modifier.padding(top = U.notesGap), style = T.body, color = C.muted) + Spacer(Modifier.height(U.notesListBottom)) + Text("Sign-in stays on this TV. Android asks before installing.", Modifier.exactLineBox(T.body), style = T.body, color = C.muted) } } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt index bb8cfdc6..5c231d6a 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt @@ -703,6 +703,10 @@ object WolfskinTokens { } object Update { val avatarJustin = ComposeColor(0xFF7AB8FF) + val notesListTop = 14.0.dp + val notesListBottom = 14.0.dp + val notesMarkerOffset = 5.5.dp + val notesMarkerWidth = 14.5.dp val heading = TextStyle(fontSize = 18.0.sp, fontWeight = FontWeight(800), lineHeight = 20.160000000000004.sp, letterSpacing = -0.02.em) const val settingsVisibleRows = 6.0f val headerTop = 75.0.dp @@ -728,7 +732,6 @@ object WolfskinTokens { val toggleThumb = 15.0.dp val toggleInset = 3.0.dp val notesHeight = 256.0.dp - val notesTitleBottom = 10.0.dp val notesGap = 9.0.dp val notesScrollStep = 40.0.dp val backTop = 92.0.dp diff --git a/wolfskin-design/tokens.css b/wolfskin-design/tokens.css index fdc284bd..de9f79e7 100644 --- a/wolfskin-design/tokens.css +++ b/wolfskin-design/tokens.css @@ -517,6 +517,10 @@ --discover-ambientInset: 80.0px; --discover-ambientBlur: 60.0px; --update-avatarJustin: #7ab8ff; + --update-notesListTop: 28.0px; + --update-notesListBottom: 28.0px; + --update-notesMarkerOffset: 11.0px; + --update-notesMarkerWidth: 29.0px; --update-heading: 36.0px; --update-headerTop: 150.0px; --update-headerHeight: 84.0px; @@ -541,7 +545,6 @@ --update-toggleThumb: 30.0px; --update-toggleInset: 6.0px; --update-notesHeight: 512.0px; - --update-notesTitleBottom: 20.0px; --update-notesGap: 18.0px; --update-notesScrollStep: 80.0px; --update-backTop: 184.0px; diff --git a/wolfskin-design/tokens.sha256 b/wolfskin-design/tokens.sha256 index ae81afd2..5b6dd97f 100644 --- a/wolfskin-design/tokens.sha256 +++ b/wolfskin-design/tokens.sha256 @@ -2,8 +2,8 @@ b3f096b692c395534177cc82ac68f5b801870bc7e28f0dd5cd7c17e2103920a3 discover-token 993d933950e17fb72d0902ffc440e1e4ed4dc088c96a8d12974431c77dc31634 generate_tokens.py 25985087986a46f00e2819917d0421ff2b437ec21c54f6ce6412b84c0eb05302 home-tokens.json be3af0ddcb0d67abef0805d19d7a33cdb55428bcace656b50f0a38935f212028 shell-tokens.json -289935944db0aa2f43224d7532331ad9ac5c666dbe40f1c44c9b7ee725f972ad src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt +1b8222d01dc30cbe2591097218a4a93c6ac4b24704cf81b18174b7839eb57e31 src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt e0a2f5df2f249bce3f6e13f4a0320c7b18b85777eaf04a27a428d6683a6aad28 title-tokens.json -5fa37cdbb5ab1bf0dbb0f83b8facabcd601ffb22492ad54f8aa9fc86cb729ee4 tokens.css +9a4c316e83af3207dd21fa7a3b4a70711460f38b740ee1de3ec9b042b3d4f9a8 tokens.css 2e5e0476341adec1ec05331af38bc67cd02ba013a0988aea40a70eff21513264 tokens.json -20c17f4e980baccce555b0cff8f76a2cfbc0db4e88d5a11f43abf73f0d936eb2 update-tokens.json +1bedb8e8079b4a954651d8761d18b8be4adb3933370e5f296be27287401ae460 update-tokens.json diff --git a/wolfskin-design/update-tokens.json b/wolfskin-design/update-tokens.json index b5e59c6f..a6065c06 100644 --- a/wolfskin-design/update-tokens.json +++ b/wolfskin-design/update-tokens.json @@ -1,6 +1,10 @@ { "update": { "avatarJustin": {"$type": "color", "$value": "#7ab8ff"}, + "notesListTop": {"$type": "dimension", "px": 28, "dp": 14}, + "notesListBottom": {"$type": "dimension", "px": 28, "dp": 14}, + "notesMarkerOffset": {"$type": "dimension", "px": 11, "dp": 5.5}, + "notesMarkerWidth": {"$type": "dimension", "px": 29, "dp": 14.5}, "heading": { "$type": "typography", "$value": {"fontWeight": 800}, @@ -126,11 +130,6 @@ "px": 512, "dp": 256.0 }, - "notesTitleBottom": { - "$type": "dimension", - "px": 20, - "dp": 10.0 - }, "notesGap": { "$type": "dimension", "px": 18, From 37ad87d05822ec21f2eeaae6f7e8047493d83b3e Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 17:55:09 +0100 Subject: [PATCH 12/18] Match native updater frames and preserve D-pad focus behavior --- README.md | 8 +++ ...datesCaptureTest.kt => UpdatesKeysTest.kt} | 57 +++++++++---------- .../wolfskin/tv/update/UpdateFocus.kt | 1 - .../wolfskin/tv/update/UpdatesScreen.kt | 24 ++++++-- .../update-font-license.txt} | 0 .../org/justinvisser/wolfskin/design/Glyph.kt | 3 + .../justinvisser/wolfskin/design/NavBar.kt | 19 ++++--- .../wolfskin/design/SettingsList.kt | 11 ++-- .../wolfskin/design/UpdateTypography.kt | 30 ++++++---- .../wolfskin/design/WolfskinTokens.kt | 6 ++ .../drawable/wolfskin_settings_chevron.xml | 3 + .../wolfskin/design/ShellCaptureTest.kt | 2 +- .../wolfskin/design/ShellKeysTest.kt | 16 ++++++ wolfskin-design/tokens.css | 6 ++ wolfskin-design/tokens.sha256 | 6 +- wolfskin-design/update-tokens.json | 6 ++ 16 files changed, 131 insertions(+), 67 deletions(-) rename app/src/test/java/org/justinvisser/wolfskin/tv/update/{UpdatesCaptureTest.kt => UpdatesKeysTest.kt} (72%) rename wolfskin-design/src/main/{res/raw/update_font_license.txt => assets/update-font-license.txt} (100%) create mode 100644 wolfskin-design/src/main/res/drawable/wolfskin_settings_chevron.xml diff --git a/README.md b/README.md index b8f04e12..ba3b9a44 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,14 @@ Wolfskin is an Android TV client for one household. It is released through Forge The app uses Wolfskin launcher artwork and a lilac-on-`#07070a` theme by default on a fresh install. Existing theme choices and all upstream colour themes remain available under Settings → App theme. Settings → About credits and links to Wholphin by damontecres. +## Wolfskin TV updates + +Settings opens on Requests. Press Down, then OK to open Updates; the row and screen show the installed app version. Left/Right selects an action, Down reaches Auto-check, and Up returns to the remembered action. Release notes keep focus inside the notes panel: Up/Down scrolls, and Back returns to the Release notes button. + +Auto-check uses the same preference as classic settings and only checks for updates. Manual checks remain available when it is off. Download and Install update are separate, explicit actions; Android owns installation permission and confirmation. Back can leave a download running, and returning to Updates shows the controller's current state. + +Classic settings (trial) is the final Settings row. It opens the full original settings, including About → Update and More/Advanced → Updates. All existing settings groups remain available. + --- # Wholphin - an OSS Android TV client for Jellyfin diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdatesCaptureTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdatesKeysTest.kt similarity index 72% rename from app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdatesCaptureTest.kt rename to app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdatesKeysTest.kt index 951e0eba..e593675d 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdatesCaptureTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdatesKeysTest.kt @@ -29,11 +29,11 @@ import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config import org.robolectric.annotation.GraphicsMode -/** Native TV frames use the real shell, updater controller seam and Android key adapter. */ +/** Native D-pad behavior preserves the retained shell, action focus and real scroller. */ @RunWith(RobolectricTestRunner::class) @Config(sdk = [34], application = Application::class, qualifiers = "w960dp-h540dp-xhdpi") @GraphicsMode(GraphicsMode.Mode.NATIVE) -class UpdatesCaptureTest { +class UpdatesKeysTest { @get:Rule val rule = createAndroidComposeRule() private val shell = ShellState(listOf(ShellPerson("justin", "Justin", "J", true)), "justin").apply { pickerVisible = false @@ -78,41 +78,24 @@ class UpdatesCaptureTest { } private fun press(keys: List) { - keys.forEach { key -> rule.onNodeWithTag("wolfskin-shell").performKeyInput { pressKey(key) } } + keys.forEach { key -> + rule.onNodeWithTag("wolfskin-shell").performKeyInput { pressKey(key) } + rule.runOnIdle { androidx.compose.runtime.snapshots.Snapshot.sendApplyNotifications() } + rule.mainClock.advanceTimeByFrame() + } rule.mainClock.advanceTimeBy(320) rule.waitForIdle() } - @Test fun settings() { launch(UpdateUiState.Checking, settings = true); capture("settings") } - @Test fun classic() { + @Test fun classicRequiresEveryRetainedRowAndTheRealScroller() { + shell.settingsRow = 0 launch(UpdateUiState.Checking, settings = true) - repeat(8) { press(listOf(Key.DirectionDown)) } + repeat(9) { press(listOf(Key.DirectionDown)) } assertEquals(9, shell.settingsRow) assertEquals(4, shell.view.listState.firstVisibleItemIndex) capture("classic") - } - @Test fun checking() { launch(UpdateUiState.Checking); capture("checking") } - @Test fun current() { launch(UpdateUiState.UpToDate); capture("current") } - @Test fun available() { launch(updateReleaseFixture()); capture("available") } - @Test fun notes() { launch(updateReleaseFixture()); press(listOf(Key.DirectionRight)); capture("notes") } - @Test fun notesOpen() { launch(updateReleaseFixture()); press(listOf(Key.DirectionRight, Key.DirectionCenter)); capture("notes-open") } - @Test fun downloading() { launch(UpdateUiState.Downloading(20_100_000, 47_800_000)); capture("downloading") } - @Test fun ready() { launch(UpdateUiState.Ready("1.1.1")); capture("ready") } - @Test fun permission() { launch(UpdateUiState.PermissionNeeded); capture("permission") } - @Test fun handoff() { launch(UpdateUiState.HandingOff); capture("handoff") } - @Test fun cancelled() { launch(UpdateUiState.InstallCancelled); capture("cancelled") } - @Test fun failed() { launch(UpdateUiState.Failed(UpdateFailure.HttpRefused, "The download server refused the request (403).")); capture("failed") } - @Test fun offline() { launch(UpdateUiState.Offline); capture("offline") } - @Test fun noInstaller() { launch(UpdateUiState.NoInstaller); capture("no-installer") } - @Test fun noReleasePublished() { launch(UpdateUiState.NoReleasePublished); capture("no-release") } - @Test fun unknownDownloadLength() { launch(UpdateUiState.Downloading(20_100_000, null)); capture("unknown-total") } - @Test fun autoOn() { launch(updateReleaseFixture()); press(listOf(Key.DirectionDown)); capture("auto-on") } - @Test fun autoOff() { launch(updateReleaseFixture()); press(listOf(Key.DirectionDown, Key.DirectionCenter)); capture("auto-off") } - @Test fun updated() { - launch(UpdateUiState.UpToDate) - rule.runOnIdle { controller.showInstalled(InstalledVersion("1.1.1", 100001)) } - rule.mainClock.advanceTimeBy(320) - capture("updated") + press(listOf(Key.DirectionCenter)) + assertEquals("classic", shell.handOff) } @Test fun notesTrapRealKeysAndBackPreservesSettingsRowAndScroller() { @@ -141,6 +124,19 @@ class UpdatesCaptureTest { assertEquals(1, (shell.contentFocus as UpdateFocus).actionIndex) } + @Test fun navAndAutoCheckReturnToTheRememberedActionWithoutToggling() { + launch(updateReleaseFixture()) + press(listOf(Key.DirectionRight, Key.DirectionDown, Key.DirectionUp)) + assertEquals(1, (shell.contentFocus as UpdateFocus).actionIndex) + assertTrue(controller.autoCheck.value) + press(listOf(Key.DirectionUp)) + assertTrue(shell.navFocused) + press(listOf(Key.DirectionDown)) + assertFalse(shell.navFocused) + assertEquals(1, (shell.contentFocus as UpdateFocus).actionIndex) + assertTrue(controller.autoCheck.value) + } + @Test fun refreshingInstalledIdentityCannotMaskAnOngoingCheck() { launch(UpdateUiState.UpToDate) rule.runOnIdle { controller.showInstalled(InstalledVersion("1.1.1", 100001)) } @@ -150,7 +146,7 @@ class UpdatesCaptureTest { rule.onNodeWithTag("update-progress").assertIsDisplayed() } - @Test fun nativeProgressAndStateTransitionAtSixteenMillisecondFrames() { + @Test fun progressKeepsAutoCheckFocusAcrossByteAndReducedMotionChanges() { launch(UpdateUiState.Checking) val target = directory if (target != null) { @@ -162,7 +158,6 @@ class UpdatesCaptureTest { rule.runOnIdle { controller.show(UpdateUiState.Downloading(20_100_000, 47_800_000)) } rule.mainClock.advanceTimeByFrame() repeat(24) { frame -> rule.mainClock.advanceTimeBy(16); capture("motion/state-%03d".format(frame)) } - assertEquals(12f, rule.onNodeWithTag("update-progress").fetchSemanticsNode().boundsInRoot.height, .01f) if (target != null) { repeat(101) { frame -> rule.mainClock.advanceTimeBy(16); capture("motion/download-%03d".format(frame)) } } diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateFocus.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateFocus.kt index 67d22cd2..cd959f76 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateFocus.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateFocus.kt @@ -39,7 +39,6 @@ class UpdateFocus( } fun focusAction(index: Int) { actionIndex = index; autoFocused = false } - fun focusAuto() { autoFocused = true } fun activate(index: Int) { focusAction(index) diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt index 725f591a..1d270736 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdatesScreen.kt @@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding @@ -28,8 +27,14 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.drawWithCache +import androidx.compose.ui.geometry.CornerRadius +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.testTag import androidx.compose.ui.semantics.Role @@ -47,7 +52,6 @@ import org.justinvisser.wolfskin.design.PickerButton import org.justinvisser.wolfskin.design.ShellState import org.justinvisser.wolfskin.design.WolfskinTokens import org.justinvisser.wolfskin.design.exactLineBox -import org.justinvisser.wolfskin.design.focusRing import org.justinvisser.wolfskin.design.focusScale import org.justinvisser.wolfskin.design.motionDuration import org.justinvisser.wolfskin.design.reducedMotion @@ -76,10 +80,11 @@ fun UpdatesScreen(shell: ShellState, controller: UpdateController, onBack: () -> val scope = rememberCoroutineScope() val density = LocalDensity.current val reduced = reducedMotion() + val scrollDuration by rememberUpdatedState(motionDuration(M.scroll, reduced)) val focus = remember(controller, shell) { UpdateFocus(controller, onBack, onClassic, { shell.navFocused = true; shell.navIndex = shell.currentTab }) { direction -> scope.launch { scroll.animateScrollBy(with(density) { U.notesScrollStep.toPx() } * direction, - tween(motionDuration(M.scroll, reduced), easing = M.easeOut)) } + tween(scrollDuration, easing = M.easeOut)) } } } LaunchedEffect(state, presentation.actions) { focus.update(state, presentation.actions) } @@ -168,7 +173,18 @@ private fun NotesPanel(release: UpdateUiState.Available?, scroll: androidx.compo val paragraphs = remember(release?.notes) { release?.notes?.lineSequence()?.filter { it.isNotBlank() }?.toList().orEmpty() } val notesStyle = T.nav.copy(fontWeight = androidx.compose.ui.text.font.FontWeight.Normal) CssColumn(Modifier.offset(L.safeSide, U.contentTop).size(U.width, U.notesHeight).testTag("update-notes") - .focusRing(true, U.radius, WolfskinTokens.Focus.ringControlRing) + .drawWithCache { + val ring = WolfskinTokens.Focus.ringControlRing.toPx() / 2f + val radius = U.radius.toPx() + val inset = U.border.toPx() + ring / 2f + onDrawWithContent { + drawContent() + drawRoundRect(C.accent, Offset(-ring / 2f, -ring / 2f), Size(size.width + ring, size.height + ring), + CornerRadius(radius + ring / 2f), style = Stroke(ring)) + drawRoundRect(C.accent, Offset(inset, inset), Size(size.width - inset * 2, size.height - inset * 2), + CornerRadius(radius - inset), style = Stroke(ring)) + } + } .background(C.surface, shape).border(U.border, C.border, shape) .verticalScroll(scroll).padding(U.padding + U.border)) { Text(updateMetadata(release), Modifier.exactLineBox(T.stateTitle), style = T.stateTitle.copy(fontWeight = androidx.compose.ui.text.font.FontWeight.Bold), color = C.fg) diff --git a/wolfskin-design/src/main/res/raw/update_font_license.txt b/wolfskin-design/src/main/assets/update-font-license.txt similarity index 100% rename from wolfskin-design/src/main/res/raw/update_font_license.txt rename to wolfskin-design/src/main/assets/update-font-license.txt diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/Glyph.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/Glyph.kt index 5a9227d3..0039ab4a 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/Glyph.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/Glyph.kt @@ -11,6 +11,9 @@ import androidx.tv.material3.Icon fun Glyph(name: String, color: Color, modifier: Modifier = Modifier) { val resource = when (name) { "gear" -> R.drawable.wolfskin_gear + "updates" -> R.drawable.wolfskin_update + "settings-list" -> R.drawable.wolfskin_settings_list + "settings-right" -> R.drawable.wolfskin_settings_chevron "requests" -> R.drawable.wolfskin_tray "interface" -> R.drawable.wolfskin_grid "play", "playback" -> R.drawable.wolfskin_play diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/NavBar.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/NavBar.kt index e30392ae..17b0af02 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/NavBar.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/NavBar.kt @@ -40,15 +40,16 @@ import org.justinvisser.wolfskin.design.WolfskinTokens.SavedIndicator as V /** Blob bounds retain their measurement while their draw coordinates spring between targets. */ data class NavBox(val left: Dp, val top: Dp, val width: Dp, val height: Dp) -fun navBoxes(tabs: List): List { - var left = L.safeSide + S.wordmarkWidth + L.wordmarkGap + L.navItemGap +fun navBoxes(tabs: List, isUpdatesLayout: Boolean = false): List { + val updates = WolfskinTokens.Update + var left = L.safeSide + (if (isUpdatesLayout) updates.wordmarkWidth else S.wordmarkWidth) + L.wordmarkGap + L.navItemGap return tabs.map { tab -> val width = when (tab) { - "home" -> S.navHomeWidth - "discover" -> S.navDiscoverWidth - "movies" -> S.navMoviesWidth - "shows" -> S.navShowsWidth - else -> S.navAnimeWidth + "home" -> if (isUpdatesLayout) updates.navHomeWidth else S.navHomeWidth + "discover" -> if (isUpdatesLayout) updates.navDiscoverWidth else S.navDiscoverWidth + "movies" -> if (isUpdatesLayout) updates.navMoviesWidth else S.navMoviesWidth + "shows" -> if (isUpdatesLayout) updates.navShowsWidth else S.navShowsWidth + else -> if (isUpdatesLayout) updates.navAnimeWidth else S.navAnimeWidth } NavBox(left, S.navItemTop, width, L.navItemHeight).also { left += width + L.navItemGap } } + NavBox(S.stageWidth - L.safeSide - L.navAvatar, S.navItemTop, L.navAvatar, L.navAvatar) @@ -57,11 +58,11 @@ fun navBoxes(tabs: List): List { /** There is one blob, including when focus wraps around the nav avatar. */ @Composable fun NavBar(state: ShellState, scrolled: Boolean, modifier: Modifier = Modifier) { - val boxes = remember(state.person.hasAnime) { navBoxes(state.tabs) } + val hasSelectedTab = state.route != "settings" && state.route != "updates" + val boxes = remember(state.person.hasAnime, hasSelectedTab) { navBoxes(state.tabs, isUpdatesLayout = !hasSelectedTab) } val reduced = reducedMotion() val labelFade = tween(motionDuration(S.navLabelFade, reduced), easing = CubicBezierEasing(0f, 0f, .58f, 1f)) val index = if (state.navFocused) state.navIndex else state.currentTab - val hasSelectedTab = state.route != "settings" && state.route != "updates" val box = boxes[index] val avatarFocused = state.navFocused && index == state.tabs.size val pad = if (avatarFocused) L.navBlobAvatarPad else S.zero diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/SettingsList.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/SettingsList.kt index e04c344f..fe7adad1 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/SettingsList.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/SettingsList.kt @@ -9,14 +9,12 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.shape.RoundedCornerShape @@ -40,11 +38,11 @@ import org.justinvisser.wolfskin.design.WolfskinTokens.Shell as S import org.justinvisser.wolfskin.design.UpdateTypography as T /** Settings routes identify real upstream destinations rather than stand-in panels. */ -data class SettingsGroup(val key: String, val title: String, val description: String, val wolfskin: Boolean = false) +data class SettingsGroup(val key: String, val title: String, val description: String) val SETTINGS_GROUPS = listOf( SettingsGroup("requests", "Requests", "Coming in: what the household asked for"), - SettingsGroup("updates", "Updates", "Check and install", true), + SettingsGroup("updates", "Updates", "Check and install"), SettingsGroup("interface", "Interface", "Sign-in · Theme music · Subtitles"), SettingsGroup("playback", "Playback", "Skip forward · Skip back · Resume"), SettingsGroup("nextup", "Next up", "Auto-play · Delay · Passout protection"), @@ -74,7 +72,8 @@ fun SettingsList(state: ShellState, modifier: Modifier = Modifier, requestCount: Text("Settings", Modifier.alignByBaseline().exactLineBox(T.screenTitle), style = T.screenTitle, color = C.fg) Text("This TV · ${state.person.name}", Modifier.alignByBaseline(), style = T.nav.copy(fontWeight = FontWeight.Normal), color = C.muted) } - LazyColumn(Modifier.fillMaxWidth().offset(y = WolfskinTokens.Update.rowsTop).height(WolfskinTokens.Update.rowsViewport + S.settingsRowGap), + LazyColumn(Modifier.fillMaxWidth().offset(y = WolfskinTokens.Update.rowsTop) + .height(WolfskinTokens.Update.rowsViewport + L.settingsRowHeight * (WolfskinTokens.Focus.scaleRow - 1f)), state = list, contentPadding = PaddingValues(bottom = S.settingsRowGap)) { itemsIndexed(SETTINGS_GROUPS, key = { _, group -> group.key }) { index, group -> Box(Modifier.height(L.row_srow)) { @@ -104,7 +103,7 @@ fun SettingsRow(group: SettingsGroup, focused: Boolean, requestCount: Int?, modi Text(group.description, Modifier.exactLineBox(T.caption), color = if (focused) C.onFocus else C.muted, style = T.caption, maxLines = 1, overflow = TextOverflow.Ellipsis) } SettingsPill(if (group.key == "requests" || group.key == "updates") "Wolfskin screen" else "upstream screen", focused) - Glyph("right", if (focused) C.onFocus else C.accentText, Modifier.size(S.settingsChevron)) + Glyph("settings-right", if (focused) C.onFocus else C.accentText, Modifier.size(S.settingsIcon)) } } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/UpdateTypography.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/UpdateTypography.kt index 92ad49f0..e777372e 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/UpdateTypography.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/UpdateTypography.kt @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-only package org.justinvisser.wolfskin.design +import androidx.compose.ui.text.PlatformTextStyle +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.LineHeightStyle import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight @@ -8,16 +11,19 @@ import androidx.compose.ui.text.font.FontWeight /** The approved Updates frames resolve system-ui to DejaVu Sans; other screens keep their fonts. */ object UpdateTypography { val family = FontFamily(Font(R.font.update_dejavu_sans), Font(R.font.update_dejavu_sans_bold, FontWeight.Bold)) - val screenTitle = WolfskinTokens.Type.screenTitle.copy(fontFamily = family) - val stateTitle = WolfskinTokens.Type.stateTitle.copy(fontFamily = family) - val heading = WolfskinTokens.Update.heading.copy(fontFamily = family) - val nav = WolfskinTokens.Type.nav.copy(fontFamily = family) - val wordmark = WolfskinTokens.Type.wordmark.copy(fontFamily = family) - val listTitle = WolfskinTokens.Type.listTitle.copy(fontFamily = family) - val body = WolfskinTokens.Type.body.copy(fontFamily = family) - val button = WolfskinTokens.Type.button.copy(fontFamily = family) - val label = WolfskinTokens.Type.label.copy(fontFamily = family) - val caption = WolfskinTokens.Type.caption.copy(fontFamily = family) - val avatarLetterNav = WolfskinTokens.Type.avatarLetterNav.copy(fontFamily = family) - val avatarLetterLibHeader = WolfskinTokens.Type.avatarLetterLibHeader.copy(fontFamily = family) + private val lineBox = LineHeightStyle(LineHeightStyle.Alignment.Center, LineHeightStyle.Trim.None) + private val platform = PlatformTextStyle(includeFontPadding = false) + private fun resolveStyle(style: TextStyle) = style.copy(fontFamily = family, lineHeightStyle = lineBox, platformStyle = platform) + val screenTitle = resolveStyle(WolfskinTokens.Type.screenTitle) + val stateTitle = resolveStyle(WolfskinTokens.Type.stateTitle) + val heading = resolveStyle(WolfskinTokens.Update.heading) + val nav = resolveStyle(WolfskinTokens.Type.nav) + val wordmark = resolveStyle(WolfskinTokens.Type.wordmark) + val listTitle = resolveStyle(WolfskinTokens.Type.listTitle) + val body = resolveStyle(WolfskinTokens.Type.body) + val button = resolveStyle(WolfskinTokens.Type.button) + val label = resolveStyle(WolfskinTokens.Type.label) + val caption = resolveStyle(WolfskinTokens.Type.caption) + val avatarLetterNav = resolveStyle(WolfskinTokens.Type.avatarLetterNav) + val avatarLetterLibHeader = resolveStyle(WolfskinTokens.Type.avatarLetterLibHeader) } diff --git a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt index 5c231d6a..d7e40012 100644 --- a/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt +++ b/wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt @@ -703,6 +703,12 @@ object WolfskinTokens { } object Update { val avatarJustin = ComposeColor(0xFF7AB8FF) + val wordmarkWidth = 81.796875.dp + val navHomeWidth = 74.6640625.dp + val navDiscoverWidth = 99.0703125.dp + val navMoviesWidth = 85.2578125.dp + val navShowsWidth = 80.578125.dp + val navAnimeWidth = 79.234375.dp val notesListTop = 14.0.dp val notesListBottom = 14.0.dp val notesMarkerOffset = 5.5.dp diff --git a/wolfskin-design/src/main/res/drawable/wolfskin_settings_chevron.xml b/wolfskin-design/src/main/res/drawable/wolfskin_settings_chevron.xml new file mode 100644 index 00000000..bbf83f40 --- /dev/null +++ b/wolfskin-design/src/main/res/drawable/wolfskin_settings_chevron.xml @@ -0,0 +1,3 @@ + + + diff --git a/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/ShellCaptureTest.kt b/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/ShellCaptureTest.kt index 6b508fd3..21a783d8 100644 --- a/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/ShellCaptureTest.kt +++ b/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/ShellCaptureTest.kt @@ -68,7 +68,7 @@ class ShellCaptureTest { @Test fun st014_discoverNav() = capture("st-014") { it.pickerVisible = false; it.navFocused = true; it.navIndex = 1 } @Test fun st091_settings() = capture("st-091") { it.pickerVisible = false; it.enterDestination("settings") } @Test fun st092_requestsCountFixture() = capture("st-092", requestCount = 5) { it.pickerVisible = false; it.enterDestination("settings") } - @Test fun st093_profileFocus() = capture("st-093") { it.pickerVisible = false; it.enterDestination("settings"); it.settingsRow = 4 } + @Test fun st093_profileFocus() = capture("st-093") { it.pickerVisible = false; it.enterDestination("settings"); it.settingsRow = 5 } } /** Tests and debug builds share the same shell-only projection of the locked fixture. */ diff --git a/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/ShellKeysTest.kt b/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/ShellKeysTest.kt index ea452a66..3cb4445c 100644 --- a/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/ShellKeysTest.kt +++ b/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/ShellKeysTest.kt @@ -46,6 +46,22 @@ class ShellKeysTest { assertFalse("Requests content, not the nav, must own focus", state.navFocused) } + @Test fun updatesUseTwoPressesFromRequestsWithoutClassicHandOff() { + val actions = mutableListOf() + val shell = ShellState(fixturePeople(), "justin", actions::add).apply { + pickerVisible = false + enterDestination("settings") + } + rule.setContent { WolfskinTheme { ShellSurface(shell) } } + rule.onNodeWithTag("wolfskin-shell").performKeyInput { + pressKey(Key.DirectionDown) + pressKey(Key.DirectionCenter) + } + assertEquals(1, shell.settingsRow) + assertNull(shell.handOff) + assertEquals(listOf(ShellAction.Destination("updates")), actions) + } + @Test fun settingsBackBackInTenPresses() { replay(settings + listOf(Key.Back, Key.Back), 10) assertEquals("home", state.route) diff --git a/wolfskin-design/tokens.css b/wolfskin-design/tokens.css index de9f79e7..7804b4f5 100644 --- a/wolfskin-design/tokens.css +++ b/wolfskin-design/tokens.css @@ -517,6 +517,12 @@ --discover-ambientInset: 80.0px; --discover-ambientBlur: 60.0px; --update-avatarJustin: #7ab8ff; + --update-wordmarkWidth: 163.59375px; + --update-navHomeWidth: 149.328125px; + --update-navDiscoverWidth: 198.140625px; + --update-navMoviesWidth: 170.515625px; + --update-navShowsWidth: 161.15625px; + --update-navAnimeWidth: 158.46875px; --update-notesListTop: 28.0px; --update-notesListBottom: 28.0px; --update-notesMarkerOffset: 11.0px; diff --git a/wolfskin-design/tokens.sha256 b/wolfskin-design/tokens.sha256 index 5b6dd97f..2a9dd865 100644 --- a/wolfskin-design/tokens.sha256 +++ b/wolfskin-design/tokens.sha256 @@ -2,8 +2,8 @@ b3f096b692c395534177cc82ac68f5b801870bc7e28f0dd5cd7c17e2103920a3 discover-token 993d933950e17fb72d0902ffc440e1e4ed4dc088c96a8d12974431c77dc31634 generate_tokens.py 25985087986a46f00e2819917d0421ff2b437ec21c54f6ce6412b84c0eb05302 home-tokens.json be3af0ddcb0d67abef0805d19d7a33cdb55428bcace656b50f0a38935f212028 shell-tokens.json -1b8222d01dc30cbe2591097218a4a93c6ac4b24704cf81b18174b7839eb57e31 src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt +a951ee1e5c433789e22cc995a7ed279d170b24d5bfbd1672fa9799c9282c6fb8 src/main/java/org/justinvisser/wolfskin/design/WolfskinTokens.kt e0a2f5df2f249bce3f6e13f4a0320c7b18b85777eaf04a27a428d6683a6aad28 title-tokens.json -9a4c316e83af3207dd21fa7a3b4a70711460f38b740ee1de3ec9b042b3d4f9a8 tokens.css +27b0e44afaece06f732d24ff847140da6175ea352de620fa6de9d7e9e4c101fa tokens.css 2e5e0476341adec1ec05331af38bc67cd02ba013a0988aea40a70eff21513264 tokens.json -1bedb8e8079b4a954651d8761d18b8be4adb3933370e5f296be27287401ae460 update-tokens.json +19728f99b90bc40c0ebec37c5bcc45b383b89b023211490bb3235c1690237ae5 update-tokens.json diff --git a/wolfskin-design/update-tokens.json b/wolfskin-design/update-tokens.json index a6065c06..57d2454b 100644 --- a/wolfskin-design/update-tokens.json +++ b/wolfskin-design/update-tokens.json @@ -1,6 +1,12 @@ { "update": { "avatarJustin": {"$type": "color", "$value": "#7ab8ff"}, + "wordmarkWidth": {"$type": "dimension", "px": 163.59375, "dp": 81.796875}, + "navHomeWidth": {"$type": "dimension", "px": 149.328125, "dp": 74.6640625}, + "navDiscoverWidth": {"$type": "dimension", "px": 198.140625, "dp": 99.0703125}, + "navMoviesWidth": {"$type": "dimension", "px": 170.515625, "dp": 85.2578125}, + "navShowsWidth": {"$type": "dimension", "px": 161.15625, "dp": 80.578125}, + "navAnimeWidth": {"$type": "dimension", "px": 158.46875, "dp": 79.234375}, "notesListTop": {"$type": "dimension", "px": 28, "dp": 14}, "notesListBottom": {"$type": "dimension", "px": 28, "dp": 14}, "notesMarkerOffset": {"$type": "dimension", "px": 11, "dp": 5.5}, From 83ebf25d9f139928792c0122ade7425a5a592530 Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 18:33:36 +0100 Subject: [PATCH 13/18] Keep updater navigation motion bounded --- .../org/justinvisser/wolfskin/tv/WolfskinApp.kt | 8 +++++++- .../wolfskin/tv/update/UpdateNavigation.kt | 13 +++++++++++++ wolfskin-design/build.gradle.kts | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateNavigation.kt diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/WolfskinApp.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/WolfskinApp.kt index a1d5c5e7..caeb9543 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/WolfskinApp.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/WolfskinApp.kt @@ -305,7 +305,13 @@ fun WolfskinApp( onBack = { if (navigationManager.backStack.last().fullScreen) navigationManager.goBack() else state.key(org.justinvisser.wolfskin.design.ShellKey.Back) }, entryDecorators = listOf(rememberSaveableStateHolderNavEntryDecorator(), rememberViewModelStoreNavEntryDecorator()), entryProvider = { destination -> - NavEntry(destination, contentKey = "${destination}_${server.id}_${user.id}") { + NavEntry( + destination, + contentKey = "${destination}_${server.id}_${user.id}", + metadata = if (destination is Destination.Wolfskin && destination.route == "updates") { + org.justinvisser.wolfskin.tv.update.updatesRouteTransitions + } else emptyMap(), + ) { // Cached entries must not retain the launch shell after sign-in completes. val state = LocalShellState.current val discover = LocalDiscoverState.current diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateNavigation.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateNavigation.kt new file mode 100644 index 00000000..ec5de195 --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateNavigation.kt @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import androidx.compose.animation.EnterTransition +import androidx.compose.animation.ExitTransition +import androidx.compose.animation.togetherWith +import androidx.navigation3.ui.NavDisplay + +/** Updates animates bounded content only; the retained nav never crossfades as a full scene. */ +internal val updatesRouteTransitions = + NavDisplay.transitionSpec { (EnterTransition.None togetherWith ExitTransition.None).using(null) } + + NavDisplay.popTransitionSpec { (EnterTransition.None togetherWith ExitTransition.None).using(null) } + + NavDisplay.predictivePopTransitionSpec { (EnterTransition.None togetherWith ExitTransition.None).using(null) } diff --git a/wolfskin-design/build.gradle.kts b/wolfskin-design/build.gradle.kts index d1275edb..f1eea2d9 100644 --- a/wolfskin-design/build.gradle.kts +++ b/wolfskin-design/build.gradle.kts @@ -30,7 +30,7 @@ val cacheRobolectricSdk by tasks.registering(Copy::class) { } val checkTokenDrift by tasks.registering { - inputs.files(fileTree(projectDir) { include("tokens.json", "shell-tokens.json", "title-tokens.json", "home-tokens.json", "discover-tokens.json", "generate_tokens.py", "tokens.css", "tokens.sha256", "src/main/java/**/WolfskinTokens.kt") }) + inputs.files(fileTree(projectDir) { include("tokens.json", "shell-tokens.json", "title-tokens.json", "home-tokens.json", "discover-tokens.json", "update-tokens.json", "generate_tokens.py", "tokens.css", "tokens.sha256", "src/main/java/**/WolfskinTokens.kt") }) doLast { file("tokens.sha256").readLines().forEach { line -> val (expected, name) = line.split(" ", limit = 2) From d171aaae9e97910a34efd47c34544f4854a17245 Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 18:50:43 +0100 Subject: [PATCH 14/18] Implement verified household TV updates and release tooling --- Makefile | 12 +- app/build.gradle.kts | 11 + app/household-version.gradle.kts | 18 + app/src/main/AndroidManifest.xml | 14 + .../wholphin/preferences/AppPreference.kt | 3 +- .../wholphin/services/UpdateChecker.kt | 18 + .../ui/preferences/PreferencesContent.kt | 10 +- .../wholphin/ui/setup/InstallUpdatePage.kt | 13 + .../wholphin/test/TestUpdateChecker.kt | 10 + .../wholphin/test/VersionCompareTests.kt | 9 +- .../update/HouseholdUpdateControllerTest.kt | 357 +++++++++++++++++ .../wolfskin/tv/update/UpdateManifestTest.kt | 49 +++ .../tv/update/AndroidUpdatePlatform.kt | 90 +++++ .../tv/update/AndroidUpdateService.kt | 58 +++ .../wolfskin/tv/update/ClassicUpdatePage.kt | 82 ++++ .../tv/update/HouseholdUpdateController.kt | 197 ++++++++++ .../wolfskin/tv/update/UpdateChannel.kt | 14 + .../tv/update/UpdateInstallReceiver.kt | 61 +++ .../wolfskin/tv/update/UpdateManifest.kt | 76 ++++ .../wolfskin/tv/update/UpdateTransport.kt | 149 +++++++ .../wolfskin/tv/update/VerifiedUpdateStore.kt | 86 ++++ docker/README.md | 185 +++++++-- docker/gradle.sh | 16 +- docker/test_tv_publish.py | 280 +++++++++++++ docker/test_tv_release.py | 100 +++++ docker/tv-version-codes | 3 + docker/tv_publish.py | 368 ++++++++++++++++++ docker/tv_release.py | 229 +++++++++++ .../wolfskin/design/OwnedSourceAuditTest.kt | 66 ---- 29 files changed, 2485 insertions(+), 99 deletions(-) create mode 100644 app/household-version.gradle.kts create mode 100644 app/src/test/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateControllerTest.kt create mode 100644 app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdateManifestTest.kt create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/AndroidUpdatePlatform.kt create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/AndroidUpdateService.kt create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/ClassicUpdatePage.kt create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateController.kt create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateChannel.kt create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateInstallReceiver.kt create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateManifest.kt create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateTransport.kt create mode 100644 app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/VerifiedUpdateStore.kt create mode 100644 docker/test_tv_publish.py create mode 100644 docker/test_tv_release.py create mode 100644 docker/tv-version-codes create mode 100755 docker/tv_publish.py create mode 100755 docker/tv_release.py delete mode 100644 wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/OwnedSourceAuditTest.kt diff --git a/Makefile b/Makefile index df6bd824..dc06bb0c 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ WOLFSKIN_GRADLE_VOLUME ?= wolfskin-gradle WOLFSKIN_SECRETS_DIR ?= /opt/stacks/ventoy/machine-parity/manifest-tank/secrets/wolfskin export WOLFSKIN_BUILD_IMAGE WOLFSKIN_GRADLE_VOLUME WOLFSKIN_SECRETS_DIR -.PHONY: build-image apk apk-debug test release-tag +.PHONY: build-image apk apk-debug test release-tag tv-release tv-publish tv-tooling-test build-image: docker build --platform linux/amd64 --tag "$(WOLFSKIN_BUILD_IMAGE)" docker @@ -19,3 +19,13 @@ test: build-image release-tag: @bash docker/release-tag.sh + +TV_RELEASE_DIR ?= /var/tmp/wolfskin-tv-release-$(VERSION) +tv-release: build-image + @python3 docker/tv_release.py --version "$(VERSION)" --version-code "$(VERSION_CODE)" --output "$(TV_RELEASE_DIR)" $(TV_RELEASE_FLAGS) + +tv-publish: + @python3 docker/tv_publish.py --directory "$(TV_RELEASE_DIR)" $(TV_PUBLISH_FLAGS) + +tv-tooling-test: + @python3 -m unittest discover -s docker -p 'test_tv_*.py' -v diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 98f03a3a..2da11b20 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -56,6 +56,10 @@ val gitDescribe = .standardOutput.asText .getOrElse("v0.0.0") +val tvVersion = providers.gradleProperty("tvVersion").orElse("1.1.1") +val tvVersionCode = providers.gradleProperty("tvVersionCode") +apply(from = "household-version.gradle.kts") + kotlin { compilerOptions { languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_3 @@ -228,6 +232,13 @@ configure { androidComponents { onVariants(selector().all()) { variant -> + if (variant.name == "defaultOptimized") { + variant.outputs.forEach { + it.versionName.set(tvVersion) + // The sentinel is configuration-only: optimized tasks require the explicit input above. + it.versionCode.set(tvVersionCode.map(String::toInt).orElse(1)) + } + } variant.outputs .map { it as com.android.build.api.variant.impl.VariantOutputImpl } .forEach { output -> diff --git a/app/household-version.gradle.kts b/app/household-version.gradle.kts new file mode 100644 index 00000000..c9ca35d0 --- /dev/null +++ b/app/household-version.gradle.kts @@ -0,0 +1,18 @@ +// Household assembly inputs remain mandatory even through aggregate Gradle tasks. +val tvVersion = providers.gradleProperty("tvVersion").orElse("1.1.1") +val tvVersionCode = providers.gradleProperty("tvVersionCode") + +fun requireHouseholdVersion() { + require(tvVersionCode.isPresent) { "Household builds require -PtvVersionCode=" } + require(tvVersionCode.get().toInt() in 1..2100000000) { "Invalid household versionCode" } + require(Regex("""\d+\.\d+\.\d+""").matches(tvVersion.get())) { "Household versionName must be plain major.minor.patch" } +} + +if (gradle.startParameter.taskNames.any { it.contains("Optimized", ignoreCase = true) }) { + requireHouseholdVersion() +} +tasks.configureEach { + if (name.contains("DefaultOptimized", ignoreCase = true)) { + doFirst { requireHouseholdVersion() } + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 20fc0df0..198782d5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -36,6 +36,13 @@ + + + + + + + + + { val UpdateUrl = AppStringPreference( title = R.string.update_url, - defaultValue = "https://git.justinvisser.org/api/v1/repos/justinzeus/wolfskin/releases/latest", + defaultValue = UpdateChannel.defaultUrl(BuildConfig.APPLICATION_ID), getter = { it.updateUrl }, setter = { prefs, value -> prefs.update { updateUrl = value } diff --git a/app/src/main/java/com/github/damontecres/wholphin/services/UpdateChecker.kt b/app/src/main/java/com/github/damontecres/wholphin/services/UpdateChecker.kt index 706285f2..fa702609 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/services/UpdateChecker.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/services/UpdateChecker.kt @@ -36,6 +36,9 @@ import kotlinx.serialization.json.jsonPrimitive import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response +import org.justinvisser.wolfskin.tv.update.AndroidUpdateService +import org.justinvisser.wolfskin.tv.update.UpdateChannel +import org.justinvisser.wolfskin.tv.update.UpdateTransport import timber.log.Timber import java.io.File import java.io.InputStream @@ -43,6 +46,7 @@ import java.io.OutputStream import java.util.Date import javax.inject.Inject import javax.inject.Singleton +import javax.inject.Provider import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.milliseconds @@ -55,6 +59,7 @@ class UpdateChecker constructor( @param:ApplicationContext private val context: Context, @param:StandardOkHttpClient private val okHttpClient: OkHttpClient, + private val household: Provider, ) { companion object { const val ASSET_NAME = "Wolfskin" @@ -123,6 +128,10 @@ class UpdateChecker updateUrl: String, showNegativeToast: Boolean = false, ) { + if (context.packageName == UpdateChannel.PACKAGE) { + household.get().controller.check(manual = showNegativeToast) + return + } val pref = PreferenceManager.getDefaultSharedPreferences(context) val now = Date() val lastUpdateCheckThreshold = @@ -181,6 +190,12 @@ class UpdateChecker * so this searches the release list instead of fetching a tag. */ suspend fun getRelease(version: Version): Release? { + if (context.packageName == UpdateChannel.PACKAGE) { + return withContext(WholphinDispatchers.IO) { + val releases = UpdateTransport().releasesForLatest(household.get().channelUrl()) + findReleaseByVersion(releases, version)?.let { parseRelease(it, false) } + } + } val request = Request .Builder() @@ -233,6 +248,9 @@ class UpdateChecker release: Release, callback: DownloadCallback, ) { + check(context.packageName != UpdateChannel.PACKAGE) { + "Household updates require the verified update controller" + } withContext(WholphinDispatchers.IO) { cleanup() val request = diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferencesContent.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferencesContent.kt index 0e388213..cd9afc3e 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferencesContent.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/PreferencesContent.kt @@ -47,6 +47,7 @@ import androidx.tv.material3.Text import androidx.tv.material3.surfaceColorAtElevation import coil3.SingletonImageLoader import coil3.imageLoader +import com.github.damontecres.wholphin.BuildConfig import com.github.damontecres.wholphin.R import com.github.damontecres.wholphin.preferences.AppPreference import com.github.damontecres.wholphin.preferences.AppPreferences @@ -89,6 +90,7 @@ import com.github.damontecres.wholphin.util.DataLoadingState import com.github.damontecres.wholphin.util.ExceptionHandler import com.github.damontecres.wholphin.util.LoadingState import kotlinx.coroutines.launch +import org.justinvisser.wolfskin.tv.update.UpdateChannel import timber.log.Timber import java.util.Locale @@ -355,7 +357,9 @@ fun PreferencesContent( AppPreference.Update -> { ClickPreference( title = - if (release != null && updateAvailable) { + if (BuildConfig.APPLICATION_ID == UpdateChannel.PACKAGE) { + stringResource(R.string.check_for_updates) + } else if (release != null && updateAvailable) { stringResource(R.string.install_update) } else if (!preferences.autoCheckForUpdates && release == null) { stringResource(R.string.check_for_updates) @@ -364,7 +368,9 @@ fun PreferencesContent( }, onClick = { if (movementSounds) playOnClickSound(context) - if (release != null && updateAvailable) { + if (BuildConfig.APPLICATION_ID == UpdateChannel.PACKAGE) { + viewModel.navigationManager.navigateTo(Destination.UpdateApp) + } else if (release != null && updateAvailable) { release?.let { viewModel.navigationManager.navigateTo( Destination.UpdateApp, diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/InstallUpdatePage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/InstallUpdatePage.kt index a3bd52e4..67366b9f 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/InstallUpdatePage.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/InstallUpdatePage.kt @@ -44,6 +44,7 @@ import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Text import androidx.tv.material3.surfaceColorAtElevation import com.github.damontecres.wholphin.R +import com.github.damontecres.wholphin.BuildConfig import com.github.damontecres.wholphin.preferences.UserPreferences import com.github.damontecres.wholphin.services.DownloadCallback import com.github.damontecres.wholphin.services.NavigationManager @@ -73,6 +74,9 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import timber.log.Timber +import org.justinvisser.wolfskin.tv.update.ClassicUpdatePage +import org.justinvisser.wolfskin.tv.update.UpdateChannel +import org.justinvisser.wolfskin.tv.update.UpdateController import javax.inject.Inject @HiltViewModel @@ -82,6 +86,7 @@ class UpdateViewModel private val userPreferencesService: UserPreferencesService, val updater: UpdateChecker, val navigationManager: NavigationManager, + val householdController: UpdateController, ) : ViewModel(), DownloadCallback { private val _state = MutableStateFlow(InstallUpdateState()) @@ -93,6 +98,10 @@ class UpdateViewModel val currentVersion = updater.getInstalledVersion() fun init() { + if (BuildConfig.APPLICATION_ID == UpdateChannel.PACKAGE) { + householdController.check(true) + return + } _state.update { it.copy(loading = LoadingState.Loading) } viewModelScope.launchIO { val updateUrl = userPreferencesService.getCurrent().appPreferences.updateUrl @@ -166,6 +175,10 @@ fun InstallUpdatePage( modifier: Modifier = Modifier, viewModel: UpdateViewModel = hiltViewModel(), ) { + if (BuildConfig.APPLICATION_ID == UpdateChannel.PACKAGE) { + ClassicUpdatePage(viewModel.householdController, modifier) + return + } OneTimeLaunchedEffect { viewModel.init() } val state by viewModel.state.collectAsState() diff --git a/app/src/test/java/com/github/damontecres/wholphin/test/TestUpdateChecker.kt b/app/src/test/java/com/github/damontecres/wholphin/test/TestUpdateChecker.kt index 2e84e2ca..925f5701 100644 --- a/app/src/test/java/com/github/damontecres/wholphin/test/TestUpdateChecker.kt +++ b/app/src/test/java/com/github/damontecres/wholphin/test/TestUpdateChecker.kt @@ -18,6 +18,16 @@ import java.nio.file.Paths import kotlin.io.path.readText class TestUpdateChecker { + @Test + fun householdChannelMigrationDoesNotChangeCustomOrOldProductionFeeds() { + val channel = org.justinvisser.wolfskin.tv.update.UpdateChannel + Assert.assertEquals(channel.LATEST_URL, channel.migrateUrl(channel.PACKAGE, channel.LEGACY_URL)) + Assert.assertEquals("https://custom.test/releases/latest", channel.migrateUrl(channel.PACKAGE, "https://custom.test/releases/latest")) + Assert.assertEquals(channel.LEGACY_URL, channel.migrateUrl("org.justinvisser.wolfskin.tv", channel.LEGACY_URL)) + Assert.assertEquals(channel.LEGACY_URL, channel.defaultUrl("org.justinvisser.wolfskin.tv")) + Assert.assertEquals(channel.LATEST_URL, channel.defaultUrl(channel.PACKAGE)) + } + lateinit var releaseJson: JsonObject val assetsJson: JsonArray by lazy { releaseJson["assets"]!!.jsonArray } diff --git a/app/src/test/java/com/github/damontecres/wholphin/test/VersionCompareTests.kt b/app/src/test/java/com/github/damontecres/wholphin/test/VersionCompareTests.kt index fdd45e6a..93842728 100644 --- a/app/src/test/java/com/github/damontecres/wholphin/test/VersionCompareTests.kt +++ b/app/src/test/java/com/github/damontecres/wholphin/test/VersionCompareTests.kt @@ -22,7 +22,14 @@ class VersionCompareTests { @Test fun optimizedVersionRemainsCompatibleWithUpgradeAndUpdateChecks() { val optimizedVersion = Version.fromString(requireNotNull(System.getProperty("wolfskin.optimizedVersionName"))) - Assert.assertEquals(Version.fromString(BuildConfig.VERSION_NAME), optimizedVersion) + Assert.assertTrue(optimizedVersion.isGreaterThan(Version.fromString("1.1.0-140-g5162c299"))) + } + + @Test + fun householdAvailabilityOrdersAndroidCodesNotDisplayVersions() { + Assert.assertTrue(org.justinvisser.wolfskin.tv.update.UpdateChannel.isNewer(100001, 65)) + Assert.assertFalse(org.justinvisser.wolfskin.tv.update.UpdateChannel.isNewer(65, 100001)) + Assert.assertFalse(org.justinvisser.wolfskin.tv.update.UpdateChannel.isNewer(100001, 100001)) } @Test diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateControllerTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateControllerTest.kt new file mode 100644 index 00000000..0c2ebae2 --- /dev/null +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateControllerTest.kt @@ -0,0 +1,357 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import com.sun.net.httpserver.HttpServer +import java.io.File +import java.net.InetSocketAddress +import java.security.MessageDigest +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runTest +import org.junit.After +import org.junit.Assert.* +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder + +/** Exercises the production transport, verification store and state machine against HTTP bytes. */ +@OptIn(ExperimentalCoroutinesApi::class) +class HouseholdUpdateControllerTest { + @get:Rule val temporary = TemporaryFolder() + private lateinit var server: HttpServer + private lateinit var directory: File + private lateinit var base: String + private val apk = ByteArray(128 * 1024) { (it % 251).toByte() } + private var code = 100001L + private var releaseStatus = 200 + private var assetStatus = 200 + private var wireTruncated = false + private var metadataTruncated = false + private var listStatus = 200 + private var listBody = "[]" + private var invalidJson = false + private var badHash = false + private var truncated = false + private var chunked = false + private var unsupported = false + private var redirect = false + private var redirectTarget: String? = null + private val requests = mutableListOf>>() + private val platform = Platform() + + private inner class Platform : UpdatePlatform { + var archive = ApkIdentity(UpdateChannel.PACKAGE, InstalledVersion("1.1.1", 100001), setOf(UpdateChannel.SIGNER)) + var installed = ApkIdentity(UpdateChannel.PACKAGE, InstalledVersion("1.1.0", 65), setOf(UpdateChannel.SIGNER)) + var permission = true + var settingsAvailable = true + var installs = 0 + var outcome = InstallOutcome.Cancelled + override fun installed() = installed + override fun inspect(file: File) = archive + override fun hasInstallPermission() = permission + override fun openPermissionSettings() = settingsAvailable + override fun install(file: File, outcome: (InstallOutcome) -> Unit) { installs++; outcome(this.outcome) } + } + private val preferences = object : UpdatePreferences { + override val autoCheck = MutableStateFlow(true) + override suspend fun url() = "$base/releases/latest" + override suspend fun enabled() = autoCheck.value + override suspend fun setAutoCheck(enabled: Boolean) { autoCheck.value = enabled } + } + + @Before fun start() { + directory = temporary.newFolder() + server = HttpServer.create(InetSocketAddress("127.0.0.1", 0), 0) + base = "http://127.0.0.1:${server.address.port}" + server.createContext("/") { exchange -> + synchronized(requests) { requests += exchange.requestHeaders.mapValues { it.value.toList() } } + val path = exchange.requestURI.path + val status = when (path) { + "/releases/latest" -> releaseStatus + "/releases" -> listStatus + "/apk" -> assetStatus + else -> 200 + } + val content = when (path) { + "/releases/latest", "/redirected" -> if (invalidJson) "not json" else """{"name":"v1.1.1","body":"Household notes","published_at":"2026-11-07T12:00:00Z","assets":[{"name":"wolfskin-update.json","browser_download_url":"$base/manifest"},{"name":"Wolfskin-armeabi-v7a.apk","browser_download_url":"$base/apk"}]}""" + "/manifest" -> UpdateManifest.encode(manifest()) + "/releases" -> listBody + else -> "" + } + if (redirect && path == "/releases/latest") { + exchange.responseHeaders.add("Location", redirectTarget ?: "$base/redirected") + exchange.responseHeaders.add("Set-Cookie", "private-session=never-forward") + exchange.sendResponseHeaders(302, -1) + } else { + val bytes = if (path == "/apk") (if (truncated) apk.copyOf(apk.size / 2) else apk) else content.toByteArray() + val length = when { + chunked && path == "/apk" -> 0L + wireTruncated && path == "/apk" -> apk.size.toLong() + metadataTruncated && path == "/releases/latest" -> bytes.size + 1L + else -> bytes.size.toLong() + } + exchange.sendResponseHeaders(status, length) + exchange.responseBody.use { it.write(bytes) } + } + exchange.close() + } + server.start() + } + @After fun stop() { server.stop(0) } + + private fun manifest() = UpdateManifest(1, UpdateChannel.PACKAGE, "1.1.1", code, + "2026-11-07T12:00:00Z", "a".repeat(40), "pwolfskin-opt-v1.1.1", UpdateChannel.SIGNER, + listOf(UpdateAsset(if (unsupported) "x86_64" else "armeabi-v7a", if (unsupported) "Wolfskin-x86_64.apk" else "Wolfskin-armeabi-v7a.apk", apk.size.toLong(), + if (badHash) "0".repeat(64) else MessageDigest.getInstance("SHA-256").digest(apk).joinToString("") { "%02x".format(it) }, 23))) + + private fun controller(scope: kotlinx.coroutines.CoroutineScope) = HouseholdUpdateController(scope, preferences, platform, + UpdateTransport(allowLocalTestHttp = true), VerifiedUpdateStore(directory, platform), listOf("armeabi-v7a"), 30) + + @Test fun newerReleaseDownloadsVerifiesAndRestoresWithoutInstalling() = runTest { + val controller = controller(this) + controller.check(true); advanceUntilIdle() + assertTrue(controller.state.value is UpdateUiState.Available) + controller.download(); advanceUntilIdle() + assertEquals(UpdateUiState.Ready("1.1.1"), controller.state.value) + assertEquals(0, platform.installs) + val restored = controller(this); advanceUntilIdle() + assertEquals(UpdateUiState.Ready("1.1.1"), restored.state.value) + restored.install(); advanceUntilIdle() + assertEquals(UpdateUiState.InstallCancelled, restored.state.value) + assertEquals(1, platform.installs) + assertTrue(File(directory, "verified.apk").exists()) + } + + @Test fun equalCodeIsUpToDateAndOlderCodeIsNotASuccess() = runTest { + code = 65 + val equal = controller(this); equal.check(true); advanceUntilIdle() + assertEquals(UpdateUiState.UpToDate, equal.state.value) + code = 64 + val older = controller(this); older.check(true); advanceUntilIdle() + assertEquals(UpdateFailure.LowerVersionCode, (older.state.value as UpdateUiState.Failed).kind) + } + + @Test fun emptyChannelIsDistinctFromMissingOrRefusedEndpoint() = runTest { + releaseStatus = 404 + val empty = controller(this); empty.check(true); advanceUntilIdle() + assertEquals(UpdateUiState.NoReleasePublished, empty.state.value) + for (status in listOf(401, 403, 404, 500, 503)) { + listStatus = status + val failure = controller(this); failure.check(true); advanceUntilIdle() + assertEquals(UpdateFailure.HttpRefused, (failure.state.value as UpdateUiState.Failed).kind) + } + } + + @Test fun refusedLatestNeverBecomesUpToDate() = runTest { + for (status in listOf(401, 403, 500, 503)) { + releaseStatus = status + val controller = controller(this); controller.check(true); advanceUntilIdle() + assertEquals(UpdateFailure.HttpRefused, (controller.state.value as UpdateUiState.Failed).kind) + } + } + + @Test fun invalidJsonAndUnavailableAbiAreTypedFailures() = runTest { + invalidJson = true + val invalid = controller(this); invalid.check(true); advanceUntilIdle() + assertEquals(UpdateFailure.InvalidMetadata, (invalid.state.value as UpdateUiState.Failed).kind) + invalidJson = false; unsupported = true + val unsupported = controller(this); unsupported.check(true); advanceUntilIdle() + assertEquals(UpdateFailure.UnsupportedAbi, (unsupported.state.value as UpdateUiState.Failed).kind) + } + + @Test fun checksumAndLengthFailuresNeverCommitReady() = runTest { + for (badChecksum in listOf(true, false)) { + badHash = badChecksum; truncated = !badChecksum + val controller = controller(this); controller.check(true); advanceUntilIdle() + controller.download(); advanceUntilIdle() + assertEquals(UpdateFailure.ChecksumMismatch, (controller.state.value as UpdateUiState.Failed).kind) + assertFalse(File(directory, "ready.json").exists()) + assertFalse(File(directory, "download.part").exists()) + } + } + + @Test fun wrongPackageSignerAndArchiveCodeCannotBecomeReady() = runTest { + val original = platform.archive + for ((archive, expected) in listOf( + original.copy(packageId = "other.package") to UpdateFailure.WrongPackage, + original.copy(signers = setOf("b".repeat(64))) to UpdateFailure.WrongSigner, + original.copy(version = InstalledVersion("1.1.1", 65)) to UpdateFailure.LowerVersionCode, + )) { + platform.archive = archive + val controller = controller(this); controller.check(true); advanceUntilIdle() + controller.download(); advanceUntilIdle() + assertEquals(expected, (controller.state.value as UpdateUiState.Failed).kind) + assertFalse(File(directory, "ready.json").exists()) + } + } + + @Test fun chunkedTransferReportsUnknownTotalAndCancelDeletesPartial() = runTest { + chunked = true + val controller = controller(this) + var observedUnknownLength = false + backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) { + controller.state.collect { state -> + if (state is UpdateUiState.Downloading && state.bytesDone > 0) { + observedUnknownLength = state.bytesTotal == null + controller.cancel() + } + } + } + controller.check(true); advanceUntilIdle() + controller.download(); advanceUntilIdle() + assertTrue(observedUnknownLength) + assertTrue(controller.state.value is UpdateUiState.Available) + assertFalse(File(directory, "download.part").exists()) + assertFalse(File(directory, "ready.json").exists()) + } + + @Test fun redirectRequestsContainNoCredentialsAndRejectUrlUserInfo() = runTest { + redirect = true + redirectTarget = "http://localhost:${server.address.port}/redirected" + val controller = controller(this); controller.check(true); advanceUntilIdle() + assertTrue(controller.state.value is UpdateUiState.Available) + assertTrue(requests.size >= 3) + requests.forEach { headers -> + assertFalse(headers.keys.any { it.equals("Authorization", true) || it.equals("Cookie", true) || + it.contains("Jellyfin", true) || it.contains("Emby", true) || it.contains("MediaBrowser", true) }) + } + redirectTarget = "http://user:password@127.0.0.1:${server.address.port}/redirected" + val rejected = controller(this); rejected.check(true); advanceUntilIdle() + assertEquals(UpdateFailure.InvalidMetadata, (rejected.state.value as UpdateUiState.Failed).kind) + } + + @Test fun manualCheckWorksWithAutoOffAndPermissionDenialKeepsReady() = runTest { + preferences.autoCheck.value = false + val controller = controller(this) + controller.check(false); advanceUntilIdle() + assertEquals(UpdateUiState.Idle, controller.state.value) + controller.check(true); advanceUntilIdle(); controller.download(); advanceUntilIdle() + platform.permission = false + controller.install(); advanceUntilIdle() + assertEquals(UpdateUiState.PermissionNeeded, controller.state.value) + controller.check(true); advanceUntilIdle() + assertEquals(UpdateUiState.PermissionNeeded, controller.state.value) + controller.onResume(); advanceUntilIdle() + assertEquals(UpdateUiState.InstallCancelled, controller.state.value) + assertEquals(0, platform.installs) + platform.settingsAvailable = false + controller.install(); advanceUntilIdle() + assertEquals(UpdateUiState.NoInstaller, controller.state.value) + } + + @Test fun corruptPersistedBytesAndUnverifiedPartialsAreDiscarded() = runTest { + val controller = controller(this); controller.check(true); advanceUntilIdle(); controller.download(); advanceUntilIdle() + File(directory, "verified.apk").appendText("corrupt") + File(directory, "download.part").writeText("incomplete") + val recreated = controller(this); advanceUntilIdle() + assertEquals(UpdateUiState.Idle, recreated.state.value) + assertFalse(File(directory, "verified.apk").exists()) + assertFalse(File(directory, "download.part").exists()) + } + + @Test fun downloadHttpFailureRetriesWithoutFalseSuccess() = runTest { + val controller = controller(this); controller.check(true); advanceUntilIdle() + assetStatus = 403 + controller.download(); advanceUntilIdle() + assertEquals(UpdateFailure.HttpRefused, (controller.state.value as UpdateUiState.Failed).kind) + assetStatus = 200 + controller.retry(); advanceUntilIdle() + assertEquals(UpdateUiState.Ready("1.1.1"), controller.state.value) + } + + @Test fun interruptedWireDownloadDoesNotPersistReady() = runTest { + truncated = true; wireTruncated = true + val controller = controller(this); controller.check(true); advanceUntilIdle() + controller.download(); advanceUntilIdle() + assertTrue(controller.state.value is UpdateUiState.Failed) + assertFalse(File(directory, "ready.json").exists()) + assertFalse(File(directory, "download.part").exists()) + } + + @Test fun exhaustedStorageFailsBeforeDownloading() = runTest { + val fullDirectory = object : File(directory.absolutePath) { override fun getUsableSpace(): Long = 0 } + val controller = HouseholdUpdateController(this, preferences, platform, UpdateTransport(true), + VerifiedUpdateStore(fullDirectory, platform), listOf("armeabi-v7a"), 30) + controller.check(true); advanceUntilIdle() + val before = requests.size + controller.download(); advanceUntilIdle() + assertEquals(UpdateFailure.InsufficientStorage, (controller.state.value as UpdateUiState.Failed).kind) + assertEquals(before, requests.size) + } + + @Test fun successCallbackRefreshesPackageManagerInsteadOfClaimingAnUpgrade() = runTest { + val controller = controller(this); controller.check(true); advanceUntilIdle(); controller.download(); advanceUntilIdle() + platform.outcome = InstallOutcome.Success + controller.install(); advanceUntilIdle() + assertEquals(65L, controller.installedVersion.value.versionCode) + assertTrue(File(directory, "verified.apk").exists()) + platform.installed = platform.archive + controller.onResume(); advanceUntilIdle() + assertEquals(100001L, controller.installedVersion.value.versionCode) + assertEquals(UpdateUiState.Idle, controller.state.value) + assertFalse(File(directory, "verified.apk").exists()) + } + + @Test fun successCallbackDeliveredToTheReplacedProcessDoesNotLeaveAFalseHandoff() = runTest { + val old = controller(this); old.check(true); advanceUntilIdle(); old.download(); advanceUntilIdle() + platform.installed = platform.archive + val replaced = controller(this); advanceUntilIdle() + replaced.handleInstallOutcome(InstallOutcome.Success); advanceUntilIdle() + assertEquals(100001L, replaced.installedVersion.value.versionCode) + assertEquals(UpdateUiState.Idle, replaced.state.value) + replaced.handleInstallOutcome(InstallOutcome.Cancelled); advanceUntilIdle() + assertEquals(UpdateUiState.Idle, replaced.state.value) + assertFalse(File(directory, "verified.apk").exists()) + } + + @Test fun reentryCheckCannotReplacePendingConfirmationOrStartAnotherSession() = runTest { + val controller = controller(this); controller.check(true); advanceUntilIdle(); controller.download(); advanceUntilIdle() + platform.outcome = InstallOutcome.Pending + controller.install(); advanceUntilIdle() + val before = requests.size + controller.check(true); advanceUntilIdle() + assertEquals(UpdateUiState.HandingOff, controller.state.value) + controller.install(); advanceUntilIdle() + assertEquals(1, platform.installs) + assertEquals(before, requests.size) + controller.handleInstallOutcome(InstallOutcome.Cancelled); advanceUntilIdle() + assertEquals(UpdateUiState.InstallCancelled, controller.state.value) + assertTrue(File(directory, "verified.apk").exists()) + } + + @Test fun productionTransportRefusesCleartextBeforeRequesting() = runTest { + try { + UpdateTransport().latest("$base/releases/latest", listOf("armeabi-v7a"), 30) + fail("Cleartext should be refused") + } catch (error: UpdateException) { assertEquals(UpdateFailure.InvalidMetadata, error.kind) } + assertTrue(requests.isEmpty()) + } + + @Test fun unavailableNetworkIsOfflineNotUpToDate() = runTest { + server.stop(0) + val controller = controller(this); controller.check(true); advanceUntilIdle() + assertEquals(UpdateUiState.Offline, controller.state.value) + } + + @Test fun interruptedFirstCheckIsNetworkFailureNotMissingDownloadStorage() = runTest { + directory = File(directory, "not-created") + metadataTruncated = true + val controller = controller(this); controller.check(true); advanceUntilIdle() + assertEquals(UpdateFailure.Network, (controller.state.value as UpdateUiState.Failed).kind) + assertFalse(directory.exists()) + } + + @Test fun compatibleArm32IsPreferredAndUniversalRespectsMinimumSdk() { + val arm32 = manifest().assets.single() + val arm64 = arm32.copy(abi = "arm64-v8a", name = "Wolfskin-arm64-v8a.apk") + val universal = arm32.copy(abi = "universal", name = "Wolfskin.apk", minSdk = 31) + val manifest = manifest().copy(assets = listOf(arm64, arm32, universal)) + assertEquals(arm32, manifest.selectAsset(listOf("arm64-v8a", "armeabi-v7a"), 30)) + try { manifest.selectAsset(listOf("unknown"), 30); fail("Minimum SDK must be enforced") } + catch (error: UpdateException) { assertEquals(UpdateFailure.UnsupportedAbi, error.kind) } + } +} diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdateManifestTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdateManifestTest.kt new file mode 100644 index 00000000..947aace9 --- /dev/null +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdateManifestTest.kt @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import org.junit.Assert.assertEquals +import org.junit.Assert.fail +import org.junit.Test + +/** Malformed channel metadata must never become a compatible version comparison. */ +class UpdateManifestTest { + private val asset = UpdateAsset("armeabi-v7a", "Wolfskin-armeabi-v7a.apk", 128, "a".repeat(64), 23) + private val manifest = UpdateManifest(1, UpdateChannel.PACKAGE, "1.1.1", 100001, + "2026-11-07T12:00:00Z", "b".repeat(40), "pwolfskin-opt-v1.1.1", UpdateChannel.SIGNER, listOf(asset)) + + @Test fun malformedManifestFieldsAreRejectedBeforeVersionComparison() { + val invalid = listOf( + manifest.copy(schemaVersion = 2), + manifest.copy(versionName = "1.1.1-opt"), + manifest.copy(versionCode = 0), + manifest.copy(publishedAt = "yesterday"), + manifest.copy(sourceCommit = "main"), + manifest.copy(sourceTag = ""), + manifest.copy(signerSha256 = "not-a-certificate-fingerprint"), + manifest.copy(assets = emptyList()), + manifest.copy(assets = listOf(asset.copy(bytes = 0))), + manifest.copy(assets = listOf(asset.copy(sha256 = "not-a-checksum"))), + manifest.copy(assets = listOf(asset.copy(abi = "arm64-v8a"))), + manifest.copy(assets = listOf(asset, asset)), + ) + invalid.forEach { candidate -> + try { UpdateManifest.parse(UpdateManifest.encode(candidate)); fail("Invalid manifest was accepted: $candidate") } + catch (error: UpdateException) { assertEquals(UpdateFailure.InvalidMetadata, error.kind) } + } + } + + @Test fun fallbackRequiresACompatibleStandaloneAsset() { + val universal = asset.copy(abi = "universal", name = "Wolfskin.apk", minSdk = 35) + val parsed = UpdateManifest.parse(UpdateManifest.encode(manifest.copy(assets = listOf(universal)))) + assertEquals(universal, parsed.selectAsset(listOf("arm64-v8a"), 35)) + try { parsed.selectAsset(listOf("arm64-v8a"), 34); fail("Unsupported minimum SDK was accepted") } + catch (error: UpdateException) { assertEquals(UpdateFailure.UnsupportedAbi, error.kind) } + } + + @Test fun universalDoesNotMakeAnUnsupportedProcessorCompatible() { + val universal = asset.copy(abi = "universal", name = "Wolfskin.apk") + val parsed = UpdateManifest.parse(UpdateManifest.encode(manifest.copy(assets = listOf(universal)))) + try { parsed.selectAsset(listOf("riscv64"), 34); fail("Unsupported processor was accepted") } + catch (error: UpdateException) { assertEquals(UpdateFailure.UnsupportedAbi, error.kind) } + } +} diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/AndroidUpdatePlatform.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/AndroidUpdatePlatform.kt new file mode 100644 index 00000000..504ef7ba --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/AndroidUpdatePlatform.kt @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.content.pm.PackageInfo +import android.content.pm.PackageInstaller +import android.content.pm.PackageManager +import android.net.Uri +import android.os.Build +import android.provider.Settings +import dagger.hilt.android.qualifiers.ApplicationContext +import java.io.File +import java.security.MessageDigest +import javax.inject.Inject +import javax.inject.Singleton + +/** PackageManager inspection and confirmation-required PackageInstaller sessions. */ +@Singleton +class AndroidUpdatePlatform @Inject constructor(@param:ApplicationContext private val context: Context) : UpdatePlatform { + private val manager = context.packageManager + private val sessions = context.getSharedPreferences("update-install-session", Context.MODE_PRIVATE) + override fun installed(): ApkIdentity = identity(manager.getPackageInfo(context.packageName, signatureFlags())) + override fun inspect(file: File): ApkIdentity? = manager.getPackageArchiveInfo(file.absolutePath, signatureFlags())?.let(::identity) + + @Suppress("DEPRECATION") + private fun signatureFlags(): Int = if (Build.VERSION.SDK_INT >= 28) PackageManager.GET_SIGNING_CERTIFICATES else PackageManager.GET_SIGNATURES + + @Suppress("DEPRECATION") + private fun identity(info: PackageInfo): ApkIdentity { + val certificates = if (Build.VERSION.SDK_INT >= 28) info.signingInfo?.apkContentsSigners else info.signatures + val hashes = certificates.orEmpty().map { + MessageDigest.getInstance("SHA-256").digest(it.toByteArray()).toHexString() + }.toSet() + val code = if (Build.VERSION.SDK_INT >= 28) info.longVersionCode else info.versionCode.toLong() + return ApkIdentity(info.packageName, InstalledVersion(info.versionName.orEmpty(), code), hashes) + } + + override fun hasInstallPermission(): Boolean = if (Build.VERSION.SDK_INT >= 26) manager.canRequestPackageInstalls() + else Settings.Secure.getInt(context.contentResolver, Settings.Secure.INSTALL_NON_MARKET_APPS, 0) == 1 + + override fun openPermissionSettings(): Boolean { + val intent = if (Build.VERSION.SDK_INT >= 26) Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:${context.packageName}")) + else Intent(Settings.ACTION_SECURITY_SETTINGS) + if (intent.resolveActivity(manager) == null) return false + return try { context.startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); true } catch (_: RuntimeException) { false } + } + + override fun install(file: File, outcome: (InstallOutcome) -> Unit) { + if (context.noBackupFilesDir.usableSpace < file.length()) { + outcome(InstallOutcome.InsufficientStorage) + return + } + val installer = manager.packageInstaller + val parameters = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL).apply { + setAppPackageName(context.packageName) + setSize(file.length()) + if (Build.VERSION.SDK_INT >= 31) setRequireUserAction(PackageInstaller.SessionParams.USER_ACTION_REQUIRED) + } + var sessionId: Int? = null + try { + sessionId = installer.createSession(parameters) + check(sessions.edit().putInt("id", sessionId).commit()) + installer.openSession(sessionId).use { session -> + session.openWrite("Wolfskin.apk", 0, file.length()).use { output -> + file.inputStream().use { it.copyTo(output) } + session.fsync(output) + } + val intent = Intent(context, UpdateInstallReceiver::class.java).setAction("${context.packageName}.UPDATE_RESULT") + val flags = PendingIntent.FLAG_UPDATE_CURRENT or if (Build.VERSION.SDK_INT >= 31) PendingIntent.FLAG_MUTABLE else 0 + val result = PendingIntent.getBroadcast(context, sessionId, intent, flags) + session.commit(result.intentSender) + } + } catch (_: Exception) { + sessionId?.let { runCatching { installer.abandonSession(it) } } + outcome(InstallOutcome.Unavailable) + } + } + + fun ownsSession(intent: Intent): Boolean = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1) == sessions.getInt("id", -2) + + fun launchConfirmation(intent: Intent): Boolean { + val activity = Intent(context, UpdateConfirmationActivity::class.java).putExtra("confirmation", intent) + return try { + context.startActivity(activity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) + true + } catch (_: RuntimeException) { false } + } +} diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/AndroidUpdateService.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/AndroidUpdateService.kt new file mode 100644 index 00000000..0410e22e --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/AndroidUpdateService.kt @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import android.content.Context +import android.os.Build +import androidx.datastore.core.DataStore +import com.github.damontecres.wholphin.preferences.AppPreferences +import com.github.damontecres.wholphin.preferences.update +import com.github.damontecres.wholphin.services.hilt.IoCoroutineScope +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import java.io.File +import javax.inject.Inject +import javax.inject.Singleton +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn + +/** Hilt entry point shared by app startup, Wolfskin UI and classic update controls. */ +@Singleton +class AndroidUpdateService @Inject constructor( + @param:ApplicationContext context: Context, + @param:IoCoroutineScope scope: CoroutineScope, + dataStore: DataStore, + val platform: AndroidUpdatePlatform, +) { + private val preferences = object : UpdatePreferences { + override val autoCheck = dataStore.data.map { it.autoCheckForUpdates }.stateIn(scope, SharingStarted.Eagerly, true) + override suspend fun enabled() = dataStore.data.first().autoCheckForUpdates + override suspend fun url(): String { + val prefs = dataStore.updateData { current -> + val url = UpdateChannel.migrateUrl(context.packageName, current.updateUrl) + if (url == current.updateUrl) current else current.update { updateUrl = url } + } + return prefs.updateUrl + } + override suspend fun setAutoCheck(enabled: Boolean) { + dataStore.updateData { it.update { autoCheckForUpdates = enabled } } + } + } + val controller = HouseholdUpdateController(scope, preferences, platform, UpdateTransport(), + VerifiedUpdateStore(File(context.noBackupFilesDir, "updates"), platform), Build.SUPPORTED_ABIS.toList(), Build.VERSION.SDK_INT) + suspend fun channelUrl(): String = preferences.url() +} + +/** Single process-scoped controller binding for every update entry point. */ +@Module +@InstallIn(SingletonComponent::class) +object UpdateModule { + @Provides + @Singleton + fun provideUpdateController(service: AndroidUpdateService): UpdateController = service.controller +} diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/ClassicUpdatePage.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/ClassicUpdatePage.kt new file mode 100644 index 00000000..1c61e943 --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/ClassicUpdatePage.kt @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleEventObserver +import androidx.lifecycle.compose.LocalLifecycleOwner +import androidx.tv.material3.Button +import androidx.tv.material3.Text +import com.github.damontecres.wholphin.ui.components.ScrollableDialog +import com.mikepenz.markdown.m3.Markdown +import org.justinvisser.wolfskin.design.WolfskinTokens + +/** Trial entry point uses the same verified service, never the legacy download-and-install path. */ +@Composable +fun ClassicUpdatePage(controller: UpdateController, modifier: Modifier = Modifier) { + val state by controller.state.collectAsState() + val installed by controller.installedVersion.collectAsState() + val lifecycle = LocalLifecycleOwner.current.lifecycle + var notes by remember { mutableStateOf(null) } + LaunchedEffect(controller) { controller.check(true) } + DisposableEffect(lifecycle, controller) { + val observer = LifecycleEventObserver { _, event -> if (event == Lifecycle.Event.ON_RESUME) controller.onResume() } + lifecycle.addObserver(observer) + onDispose { lifecycle.removeObserver(observer) } + } + Column(modifier, verticalArrangement = Arrangement.spacedBy(WolfskinTokens.Shell.settingsRowGap)) { + Text("Installed: ${installed.versionName}") + when (val current = state) { + is UpdateUiState.Available -> { + Text("${current.versionName} · ${current.bytes} bytes · ${current.dateText}") + Button(onClick = controller::download) { Text("Download") } + if (current.notes.isNotBlank()) { + Button(onClick = { notes = current.notes }) { Text("Release notes") } + } + } + is UpdateUiState.Downloading -> { + Text("${current.bytesDone} / ${current.bytesTotal ?: "—"} bytes") + Button(onClick = controller::cancel) { Text("Cancel download") } + } + is UpdateUiState.Ready, UpdateUiState.InstallCancelled, UpdateUiState.PermissionNeeded, UpdateUiState.NoInstaller -> { + Text(when (current) { + UpdateUiState.InstallCancelled -> "Installation cancelled; verified download retained" + UpdateUiState.PermissionNeeded -> "Allow updates from this app in Android settings" + UpdateUiState.NoInstaller -> "Android installer or permission settings unavailable" + else -> "Verified update ready" + }) + Button(onClick = controller::install) { Text("Install update") } + } + is UpdateUiState.Failed -> { + Text(current.message) + Button(onClick = controller::retry) { Text("Retry") } + } + UpdateUiState.HandingOff -> Text("Confirm installation in Android") + else -> { + Text(when (current) { + UpdateUiState.UpToDate -> "Up to date" + UpdateUiState.NoReleasePublished -> "No release published" + UpdateUiState.Offline -> "No network" + UpdateUiState.Checking -> "Checking" + else -> "Check for an update" + }) + Button(onClick = { controller.check(true) }) { Text("Check again") } + } + } + } + notes?.let { body -> + ScrollableDialog(onDismissRequest = { notes = null }) { + item { Markdown(content = body) } + } + } +} diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateController.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateController.kt new file mode 100644 index 00000000..92975631 --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateController.kt @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import java.io.IOException +import java.net.ConnectException +import java.net.UnknownHostException +import java.time.Instant +import java.time.ZoneId +import java.time.format.DateTimeFormatter +import java.util.Locale +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.async +import kotlinx.coroutines.currentCoroutineContext +import kotlinx.coroutines.ensureActive +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch + +/** Existing app preferences, not a separate updater preference store. */ +interface UpdatePreferences { + val autoCheck: StateFlow + suspend fun url(): String + suspend fun enabled(): Boolean + suspend fun setAutoCheck(enabled: Boolean) +} + +/** Process-owned operations outlive screens; only explicit install() crosses into Android. */ +class HouseholdUpdateController( + private val scope: CoroutineScope, + private val preferences: UpdatePreferences, + private val platform: UpdatePlatform, + private val transport: UpdateTransport, + private val store: VerifiedUpdateStore, + private val abis: List, + private val sdk: Int, +) : UpdateController { + private val mutableState = MutableStateFlow(UpdateUiState.Idle) + private val mutableVersion = MutableStateFlow(platform.installed().version) + override val state = mutableState.asStateFlow() + override val installedVersion = mutableVersion.asStateFlow() + override val autoCheck = preferences.autoCheck + private var candidate: UpdateCandidate? = null + private var ready: UpdateManifest? = null + private var operation: Job? = null + private var retryOperation: () -> Unit = { check(true) } + private val restored = scope.async { + ready = store.restore(abis, sdk) + ready?.let { mutableState.value = UpdateUiState.Ready(it.versionName) } + } + + @Synchronized + private fun runOperation(action: suspend () -> Unit): Unit { + if (operation?.isActive == true) return + operation = scope.launch { + restored.await() + try { action() } + catch (error: CancellationException) { throw error } + catch (error: UpdateException) { mutableState.value = UpdateUiState.Failed(error.kind, error.message) } + catch (_: UnknownHostException) { mutableState.value = UpdateUiState.Offline } + catch (_: ConnectException) { mutableState.value = UpdateUiState.Offline } + catch (error: IOException) { + val release = candidate + val full = state.value is UpdateUiState.Downloading && release != null && + store.directory.usableSpace < release.asset.bytes + mutableState.value = UpdateUiState.Failed(if (full) UpdateFailure.InsufficientStorage else UpdateFailure.Network, + if (full) "Not enough storage for the update" else "Update transfer failed; try again") + } + catch (_: Exception) { mutableState.value = UpdateUiState.Failed(UpdateFailure.InvalidMetadata, "Update could not be processed") } + } + } + + private fun systemOwnsFlow(current: UpdateUiState): Boolean = + current == UpdateUiState.HandingOff || current == UpdateUiState.PermissionNeeded + + override fun check(manual: Boolean): Unit = runOperation { + if (systemOwnsFlow(state.value)) return@runOperation + if (!manual && !preferences.enabled()) return@runOperation + ready?.let { manifest -> + mutableState.update { if (systemOwnsFlow(it)) it else UpdateUiState.Ready(manifest.versionName) } + return@runOperation + } + retryOperation = { check(true) } + mutableState.value = UpdateUiState.Checking + val release = transport.latest(preferences.url(), abis, sdk) + if (release == null) { mutableState.value = UpdateUiState.NoReleasePublished; return@runOperation } + val installed = platform.installed() + mutableVersion.value = installed.version + if (release.manifest.packageId != installed.packageId) throw UpdateException(UpdateFailure.WrongPackage, "Release belongs to a different application") + if (installed.signers != setOf(release.manifest.signerSha256)) throw UpdateException(UpdateFailure.WrongSigner, "Release signer differs from this installation") + if (release.manifest.versionCode < installed.version.versionCode) throw UpdateException(UpdateFailure.LowerVersionCode, "Channel release is older than this installation") + if (release.manifest.versionCode == installed.version.versionCode) { + candidate = null + mutableState.value = UpdateUiState.UpToDate + } else { candidate = release; mutableState.value = available(release) } + } + + private fun available(release: UpdateCandidate): UpdateUiState.Available { + val date = DateTimeFormatter.ofLocalizedDate(java.time.format.FormatStyle.MEDIUM).withLocale(Locale.getDefault()) + .withZone(ZoneId.systemDefault()).format(Instant.parse(release.manifest.publishedAt)) + return UpdateUiState.Available(release.manifest.versionName, release.asset.bytes, date, release.notes) + } + + override fun download(): Unit = runOperation { + if (systemOwnsFlow(state.value)) return@runOperation + if (ready != null) return@runOperation + val release = candidate ?: return@runOperation + retryOperation = { download() } + store.prepare() + if (store.directory.usableSpace < release.asset.bytes) throw UpdateException(UpdateFailure.InsufficientStorage, "Not enough storage for the update") + mutableState.value = UpdateUiState.Downloading(0, null) + try { + transport.download(release, store.partial) { done, total -> mutableState.value = UpdateUiState.Downloading(done, total) } + currentCoroutineContext().ensureActive() + store.commit(release.manifest, release.asset) + currentCoroutineContext().ensureActive() + ready = release.manifest + mutableState.value = UpdateUiState.Ready(release.manifest.versionName) + } catch (error: Exception) { + store.clear() + throw error + } finally { store.partial.delete() } + } + + @Synchronized + override fun cancel() { + if (systemOwnsFlow(state.value)) return + transport.cancel() + val previous = operation + previous?.cancel() + operation = scope.launch { + previous?.join() + store.partial.delete() + mutableState.value = ready?.let { UpdateUiState.Ready(it.versionName) } + ?: candidate?.let { available(it) } ?: UpdateUiState.Idle + } + } + + override fun install(): Unit = runOperation { + if (state.value == UpdateUiState.HandingOff) return@runOperation + val manifest = ready ?: return@runOperation + retryOperation = { install() } + try { store.verify(store.apk, manifest, manifest.selectAsset(abis, sdk)) } catch (error: Exception) { + store.clear(); ready = null + retryOperation = { if (candidate != null) download() else check(true) } + throw error + } + if (!platform.hasInstallPermission()) { + mutableState.value = if (platform.openPermissionSettings()) UpdateUiState.PermissionNeeded else UpdateUiState.NoInstaller + return@runOperation + } + mutableState.value = UpdateUiState.HandingOff + platform.install(store.apk, ::handleInstallOutcome) + } + + fun handleInstallOutcome(outcome: InstallOutcome) { + scope.launch { + restored.await() + if (ready == null && outcome != InstallOutcome.Pending) { + retryOperation = { check(true) } + mutableState.value = UpdateUiState.Idle + onResume() + return@launch + } + mutableState.value = when (outcome) { + InstallOutcome.Pending -> UpdateUiState.HandingOff + InstallOutcome.Cancelled -> UpdateUiState.InstallCancelled + InstallOutcome.Unavailable -> UpdateUiState.NoInstaller + InstallOutcome.InsufficientStorage -> UpdateUiState.Failed(UpdateFailure.InsufficientStorage, "Android needs more storage to install the retained update") + InstallOutcome.Failed -> UpdateUiState.Failed(UpdateFailure.InvalidMetadata, "Android could not install the update; the verified download is retained") + InstallOutcome.Success -> UpdateUiState.HandingOff + } + if (outcome != InstallOutcome.Pending) onResume() + } + } + + override fun retry() { retryOperation() } + override fun setAutoCheck(enabled: Boolean) { scope.launch { preferences.setAutoCheck(enabled) } } + override fun onResume() { + scope.launch { + operation?.join() + restored.await() + mutableVersion.value = platform.installed().version + val manifest = ready ?: return@launch + if (mutableVersion.value.versionCode >= manifest.versionCode) { + store.clear(); ready = null; candidate = null; mutableState.value = UpdateUiState.Idle + } else if (state.value == UpdateUiState.PermissionNeeded) { + // Returning from settings requires another explicit Install press. + mutableState.value = if (platform.hasInstallPermission()) UpdateUiState.Ready(manifest.versionName) + else UpdateUiState.InstallCancelled + } + } + } +} diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateChannel.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateChannel.kt new file mode 100644 index 00000000..6b0c12ab --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateChannel.kt @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +/** Package-scoped channel policy; the old production sandbox retains its original feed. */ +object UpdateChannel { + const val PACKAGE = "org.justinvisser.wolfskin.tv.opt" + const val SIGNER = "182bac72e292b9ea4d3d4e6383f92eb2161fa28ba5afcff0337cb7d5a9d5341d" + const val LEGACY_URL = "https://git.justinvisser.org/api/v1/repos/justinzeus/wolfskin/releases/latest" + const val LATEST_URL = "https://git.justinvisser.org/api/v1/repos/justinzeus/wolfskin-tv-updates/releases/latest" + fun defaultUrl(packageId: String): String = if (packageId == PACKAGE) LATEST_URL else LEGACY_URL + fun migrateUrl(packageId: String, saved: String): String = + if (packageId == PACKAGE && (saved == LEGACY_URL || saved.isBlank())) LATEST_URL else saved + fun isNewer(candidateCode: Long, installedCode: Long): Boolean = candidateCode > installedCode +} diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateInstallReceiver.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateInstallReceiver.kt new file mode 100644 index 00000000..497060af --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateInstallReceiver.kt @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import androidx.activity.ComponentActivity +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.pm.PackageInstaller +import android.os.Bundle +import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject + +/** Explicit, non-exported callback target accepts only the locally recorded install session. */ +@AndroidEntryPoint +class UpdateInstallReceiver : BroadcastReceiver() { + @Inject lateinit var service: AndroidUpdateService + @Suppress("DEPRECATION") + override fun onReceive(context: Context, intent: Intent) { + if (!service.platform.ownsSession(intent)) return + val outcome = when (intent.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE)) { + PackageInstaller.STATUS_PENDING_USER_ACTION -> { + val confirmation = intent.getParcelableExtra(Intent.EXTRA_INTENT) + if (confirmation != null && service.platform.launchConfirmation(confirmation)) InstallOutcome.Pending else InstallOutcome.Unavailable + } + PackageInstaller.STATUS_SUCCESS -> InstallOutcome.Success + PackageInstaller.STATUS_FAILURE_ABORTED -> InstallOutcome.Cancelled + PackageInstaller.STATUS_FAILURE_STORAGE -> InstallOutcome.InsufficientStorage + else -> InstallOutcome.Failed + } + service.controller.handleInstallOutcome(outcome) + } +} + +/** System confirmation is launched for result so cancelling retains the already-verified APK. */ +@AndroidEntryPoint +class UpdateConfirmationActivity : ComponentActivity() { + @Inject lateinit var service: AndroidUpdateService + @Suppress("DEPRECATION") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (savedInstanceState != null) return + val confirmation = intent.getParcelableExtra("confirmation") + if (confirmation == null || confirmation.resolveActivity(packageManager) == null) { + service.controller.handleInstallOutcome(InstallOutcome.Unavailable) + finish() + return + } + try { startActivityForResult(confirmation, 1) } catch (_: RuntimeException) { + service.controller.handleInstallOutcome(InstallOutcome.Unavailable) + finish() + } + } + + @Deprecated("System installer uses the activity result contract") + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == 1 && resultCode == RESULT_CANCELED) service.controller.handleInstallOutcome(InstallOutcome.Cancelled) + service.controller.onResume() + finish() + } +} diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateManifest.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateManifest.kt new file mode 100644 index 00000000..66a0240a --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateManifest.kt @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import java.time.Instant +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json + +/** Signed APK metadata published only after the final APKs have been inspected. */ +@Serializable +data class UpdateManifest( + val schemaVersion: Int, + val packageId: String, + val versionName: String, + val versionCode: Long, + val publishedAt: String, + val sourceCommit: String, + val sourceTag: String, + val signerSha256: String, + val assets: List, +) { + fun selectAsset(abis: List, sdk: Int): UpdateAsset { + fun compatible(abi: String) = assets.firstOrNull { it.abi == abi && it.minSdk <= sdk } + if ("armeabi-v7a" in abis) compatible("armeabi-v7a")?.let { return it } + for (abi in abis) { + if (abi != "armeabi-v7a" && abi != "universal") compatible(abi)?.let { return it } + } + if (abis.any { it != "universal" && it in supportedAbis }) { + compatible("universal")?.let { return it } + } + throw UpdateException(UpdateFailure.UnsupportedAbi, "No compatible APK for this device") + } + + companion object { + private val json = Json { ignoreUnknownKeys = true } + private val versionPattern = Regex("[0-9]+\\.[0-9]+\\.[0-9]+") + private val commitPattern = Regex("[0-9a-f]{40}") + private val hashPattern = Regex("[0-9a-f]{64}") + private val supportedAbis = setOf("armeabi-v7a", "arm64-v8a", "x86_64", "universal") + fun parse(text: String): UpdateManifest { + try { + val manifest = json.decodeFromString(text) + require(manifest.schemaVersion == 1) + require(manifest.packageId.isNotBlank()) + require(versionPattern.matches(manifest.versionName)) + require(manifest.versionCode in 1..2100000000) + Instant.parse(manifest.publishedAt) + require(commitPattern.matches(manifest.sourceCommit)) + require(manifest.sourceTag.isNotBlank()) + require(isHash(manifest.signerSha256)) + require(manifest.assets.isNotEmpty()) + require(manifest.assets.map { it.abi }.distinct().size == manifest.assets.size) + require(manifest.assets.map { it.name }.distinct().size == manifest.assets.size) + manifest.assets.forEach { + require(it.abi in supportedAbis) + require(it.name == if (it.abi == "universal") "Wolfskin.apk" else "Wolfskin-${it.abi}.apk") + require(it.bytes > 0 && it.minSdk > 0 && isHash(it.sha256)) + } + return manifest + } catch (error: Exception) { + throw UpdateException(UpdateFailure.InvalidMetadata, "Invalid update manifest", error) + } + } + private fun isHash(value: String) = hashPattern.matches(value) + fun encode(manifest: UpdateManifest): String = json.encodeToString(manifest) + } +} + +/** A standalone APK, not a split installation dependency. */ +@Serializable +data class UpdateAsset(val abi: String, val name: String, val bytes: Long, val sha256: String, val minSdk: Int) + +/** Selected immutable release metadata and its anonymous asset URL. */ +data class UpdateCandidate(val manifest: UpdateManifest, val asset: UpdateAsset, val url: String, val notes: String) + +/** Typed boundary error, never interpreted as an up-to-date result. */ +class UpdateException(val kind: UpdateFailure, override val message: String, cause: Throwable? = null) : Exception(message, cause) diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateTransport.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateTransport.kt new file mode 100644 index 00000000..b6c83467 --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateTransport.kt @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import com.github.damontecres.wholphin.BuildConfig +import java.io.File +import java.util.concurrent.atomic.AtomicReference +import kotlinx.coroutines.currentCoroutineContext +import kotlinx.coroutines.ensureActive +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlin.coroutines.resumeWithException +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.contentOrNull +import kotlinx.serialization.json.jsonArray +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive +import okhttp3.Call +import okhttp3.HttpUrl.Companion.toHttpUrlOrNull +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response + +/** Dedicated unauthenticated client; redirects are individually validated before any request. */ +class UpdateTransport(private val allowLocalTestHttp: Boolean = false) { + private val client = OkHttpClient.Builder().followRedirects(false).followSslRedirects(false).build() + private val activeCall = AtomicReference() + + fun cancel() { activeCall.get()?.cancel() } + + private fun validateUrl(value: String): okhttp3.HttpUrl { + val url = value.toHttpUrlOrNull() + ?: throw UpdateException(UpdateFailure.InvalidMetadata, "Invalid update URL") + val fixture = BuildConfig.DEBUG && allowLocalTestHttp && url.host in listOf("localhost", "127.0.0.1", "::1") + if ((!url.isHttps && !fixture) || url.username.isNotEmpty() || url.password.isNotEmpty()) { + throw UpdateException(UpdateFailure.InvalidMetadata, "Update URLs must use credential-free HTTPS") + } + return url + } + + private suspend fun request(value: String): Response { + var url = validateUrl(value) + repeat(6) { + val call = client.newCall(Request.Builder().url(url).get().build()) + activeCall.set(call) + val response = suspendCancellableCoroutine { continuation -> + continuation.invokeOnCancellation { call.cancel() } + try { + continuation.resume(call.execute()) { _, response, _ -> response.close() } + } catch (error: Exception) { continuation.resumeWithException(error) } + } + if (response.code !in listOf(301, 302, 303, 307, 308)) return response + response.use { + val location = it.header("Location") + ?: throw UpdateException(UpdateFailure.InvalidMetadata, "Redirect has no location") + url = validateUrl(url.resolve(location)?.toString() + ?: throw UpdateException(UpdateFailure.InvalidMetadata, "Invalid redirect")) + } + } + throw UpdateException(UpdateFailure.HttpRefused, "Too many update redirects") + } + + private suspend fun readJson(url: String): kotlinx.serialization.json.JsonElement = request(url).use { + requireSuccess(it) + val source = it.body.source() + if (source.request(MAX_METADATA_BYTES + 1) && source.buffer.size > MAX_METADATA_BYTES) { + throw UpdateException(UpdateFailure.InvalidMetadata, "Update metadata is too large") + } + try { Json.parseToJsonElement(source.readUtf8()) } catch (error: java.io.IOException) { throw error } catch (error: Exception) { + throw UpdateException(UpdateFailure.InvalidMetadata, "Invalid release JSON", error) + } + } + + /** Installed-release notes share the same anonymous redirect policy as checks and assets. */ + suspend fun releasesForLatest(url: String, limit: Int = 50): JsonArray { + val latest = validateUrl(url) + val list = latest.newBuilder() + var last = latest.pathSegments.lastIndex + while (last > 0 && latest.pathSegments[last].isEmpty()) { + list.removePathSegment(last) + last-- + } + return readJson(list.removePathSegment(last).setQueryParameter("limit", limit.toString()).build().toString()).jsonArray + } + + /** A latest 404 is empty only when the release-list endpoint successfully returns an empty array. */ + suspend fun latest(url: String, abis: List, sdk: Int): UpdateCandidate? { + try { + val release = request(url).use { + if (it.code == 404) { + if (releasesForLatest(url, 1).isEmpty()) return null + } + requireSuccess(it) + val source = it.body.source() + if (source.request(MAX_METADATA_BYTES + 1) && source.buffer.size > MAX_METADATA_BYTES) { + throw UpdateException(UpdateFailure.InvalidMetadata, "Release metadata is too large") + } + Json.parseToJsonElement(source.readUtf8()).jsonObject + } + return candidate(release, abis, sdk) + } catch (error: UpdateException) { throw error } catch (error: java.io.IOException) { throw error } + catch (error: kotlinx.coroutines.CancellationException) { throw error } + catch (error: Exception) { throw UpdateException(UpdateFailure.InvalidMetadata, "Invalid release metadata", error) } + } + + private suspend fun candidate(release: JsonObject, abis: List, sdk: Int): UpdateCandidate { + val assets = release.getValue("assets").jsonArray.map { it.jsonObject } + val manifestAsset = assets.single { it["name"]?.jsonPrimitive?.content == "wolfskin-update.json" } + val manifest = UpdateManifest.parse(readJson(manifestAsset.getValue("browser_download_url").jsonPrimitive.content).toString()) + val selected = manifest.selectAsset(abis, sdk) + val asset = assets.single { it["name"]?.jsonPrimitive?.content == selected.name } + return UpdateCandidate(manifest, selected, validateUrl(asset.getValue("browser_download_url").jsonPrimitive.content).toString(), + release["body"]?.jsonPrimitive?.contentOrNull.orEmpty()) + } + + /** A fresh transfer always truncates partials; no unvalidated HTTP range concatenation. */ + suspend fun download(candidate: UpdateCandidate, file: File, progress: (Long, Long?) -> Unit) { + currentCoroutineContext().ensureActive() + request(candidate.url).use { response -> + requireSuccess(response) + val length = response.body.contentLength().takeIf { it >= 0 } + if (length != null && length != candidate.asset.bytes) { + throw UpdateException(UpdateFailure.ChecksumMismatch, "APK length differs from manifest") + } + response.body.byteStream().use { input -> + file.outputStream().use { output -> + val buffer = ByteArray(64 * 1024) + var done = 0L + while (true) { + currentCoroutineContext().ensureActive() + val count = input.read(buffer) + if (count == -1) break + done += count + if (done > candidate.asset.bytes) throw UpdateException(UpdateFailure.ChecksumMismatch, "APK exceeds manifest length") + output.write(buffer, 0, count) + progress(done, length) + } + output.fd.sync() + } + } + } + } + + private fun requireSuccess(response: Response) { + if (!response.isSuccessful) throw UpdateException(UpdateFailure.HttpRefused, "Update server refused request (HTTP ${response.code})") + } + + companion object { private const val MAX_METADATA_BYTES = 1024L * 1024 } +} diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/VerifiedUpdateStore.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/VerifiedUpdateStore.kt new file mode 100644 index 00000000..5018865b --- /dev/null +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/VerifiedUpdateStore.kt @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import java.io.File +import java.security.MessageDigest + +/** Actual APK identity, read independently of channel metadata. */ +data class ApkIdentity(val packageId: String, val version: InstalledVersion, val signers: Set) + +/** Android boundary replaced by an in-process fixture in controller tests. */ +interface UpdatePlatform { + fun installed(): ApkIdentity + fun inspect(file: File): ApkIdentity? + fun hasInstallPermission(): Boolean + fun openPermissionSettings(): Boolean + fun install(file: File, outcome: (InstallOutcome) -> Unit) +} + +/** Installer results do not imply the running process has been replaced. */ +enum class InstallOutcome { Pending, Success, Cancelled, Failed, Unavailable, InsufficientStorage } + +/** Private staging; a metadata commit occurs only after independently verifying the APK. */ +class VerifiedUpdateStore(val directory: File, private val platform: UpdatePlatform) { + val partial = File(directory, "download.part") + val apk = File(directory, "verified.apk") + private val record = File(directory, "ready.json") + + fun prepare() { + if (!directory.isDirectory && !directory.mkdirs()) { + throw UpdateException(UpdateFailure.InsufficientStorage, "Cannot create private update storage") + } + } + + fun verify(file: File, manifest: UpdateManifest, asset: UpdateAsset) { + if (file.length() != asset.bytes || sha256(file) != asset.sha256) { + throw UpdateException(UpdateFailure.ChecksumMismatch, "APK length or checksum does not match") + } + val identity = platform.inspect(file) + ?: throw UpdateException(UpdateFailure.InvalidMetadata, "Android could not inspect the APK") + val installed = platform.installed() + if (identity.packageId != installed.packageId || identity.packageId != manifest.packageId) { + throw UpdateException(UpdateFailure.WrongPackage, "APK belongs to a different application") + } + if (identity.signers != installed.signers || identity.signers != setOf(manifest.signerSha256)) { + throw UpdateException(UpdateFailure.WrongSigner, "APK signer does not match this installation") + } + if (!UpdateChannel.isNewer(identity.version.versionCode, installed.version.versionCode)) { + throw UpdateException(UpdateFailure.LowerVersionCode, "APK is not newer than the installed application") + } + if (identity.version.versionCode != manifest.versionCode || identity.version.versionName != manifest.versionName) { + throw UpdateException(UpdateFailure.InvalidMetadata, "APK version differs from manifest") + } + } + + fun commit(manifest: UpdateManifest, asset: UpdateAsset) { + verify(partial, manifest, asset) + check(partial.renameTo(apk)) { "Could not commit verified APK" } + val temporary = File(directory, "ready.pending") + temporary.outputStream().use { it.write(UpdateManifest.encode(manifest).toByteArray()); it.fd.sync() } + check(temporary.renameTo(record)) { "Could not commit verified metadata" } + } + + /** Re-hash and re-inspect after process death; a marker alone never establishes trust. */ + fun restore(abis: List, sdk: Int): UpdateManifest? { + partial.delete() + File(directory, "ready.pending").delete() + if (!record.exists()) { apk.delete(); return null } + return try { + val manifest = UpdateManifest.parse(record.readText()) + verify(apk, manifest, manifest.selectAsset(abis, sdk)) + manifest + } catch (_: Exception) { clear(); null } + } + + fun clear() { record.delete(); apk.delete(); partial.delete() } + companion object { + fun sha256(file: File): String { + val digest = MessageDigest.getInstance("SHA-256") + file.inputStream().use { input -> + val buffer = ByteArray(64 * 1024) + while (true) { val count = input.read(buffer); if (count < 0) break; digest.update(buffer, 0, count) } + } + return digest.digest().toHexString() + } + } +} diff --git a/docker/README.md b/docker/README.md index efe8d3c6..83b607ee 100644 --- a/docker/README.md +++ b/docker/README.md @@ -11,7 +11,7 @@ make test # app default/debug suite plus wolfskin-design JVM/capture suite make apk-debug # default debug, no secrets; MPV stub and no extra codec decoders ``` -APKs remain under `app/build/outputs/apk/default/{release,debug}/`. Debug builds +APKs remain under `app/build/outputs/apk/default/{release,debug,optimized}/`. Debug builds are not playback-complete and must not be distributed as releases. Upstream's `.github/workflows` and dependency version catalog are unchanged; release builds use the catalog's exact Wholphin extension version (currently `0.2.4`). Do not @@ -27,6 +27,134 @@ Upstream enables JVM unit tests only for debug variants; there is no `testDefaultReleaseUnitTest` task. `make test` uses the closest default-flavor task without changing upstream's test configuration. +## Household update channel + +The household assembly remains `defaultOptimized`: R8/resource shrinking, +non-debuggable, baseline profiles, pinned playback extensions and no debug +fixtures. Its installation identity is `org.justinvisser.wolfskin.tv.opt`. +The persistent external Android debug keystore is now the **household signing +authority**, not a disposable development key. Certificate SHA-256: +`182bac72e292b9ea4d3d4e6383f92eb2161fa28ba5afcff0337cb7d5a9d5341d`. +Never print/copy that keystore into artifacts or regenerate it for a release. +The household wrapper fails if it is missing; protect and escrow the original. + +Same package + same signer + strictly higher Android versionCode allows an +in-place upgrade retaining Jellyfin logins, databases and preferences. Never +uninstall, clear data, change identity or replace the key as an update recovery +step. An older ephemeral signer is a separate, owner-approved migration gate; +this change does not prove the TV's installed signer or retained-login behavior. + +The dedicated public distribution repository is +`justinzeus/wolfskin-tv-updates`; its default API is +`https://git.justinvisser.org/api/v1/repos/justinzeus/wolfskin-tv-updates/releases/latest`. +Repository creation and each actual publication are separate owner gates. +Neither command creates a repository. Source remains in `justinzeus/wolfskin`. +Initialize the distribution repository's default branch (for example with a +README) before its first draft; Forgejo needs a commit on which to create a +distribution tag. That tag is not the source tag in the separate source repo. +The old production package keeps its old release API and parser. Only the Opt +package migrates the exact old default saved URL; intentional custom URLs remain. +Installed-release notes use the household channel too. + +### Build, inspect and reserve a code + +```sh +make tv-release VERSION=1.1.1 VERSION_CODE=100001 \ + TV_RELEASE_DIR=/var/tmp/wolfskin-tv-release-1.1.1 +# Prerequisites only: no build, tag, ledger mutation or publication. +make tv-release VERSION=1.1.1 VERSION_CODE=100001 \ + TV_RELEASE_DIR=/var/tmp/wolfskin-tv-release-dry TV_RELEASE_FLAGS=--dry-run +``` + +Required: a clean committed source checkout, the existing persistent key, native +package credentials through the existing secret mount, no local AAR overrides, +and an explicit code above every entry in `docker/tv-version-codes`. Known Opt +code 65 seeds that ledger; old production code 28 and Wholphin code 62 belong +to different packages. Proposed first household code 100001 exceeds all three. +No household code derives from tag counts. Direct optimized Gradle tasks also +require `-PtvVersionCode`; the packaging command additionally enforces the ledger. + +The builder inspects final signed APKs with aapt2/apksigner and checks package, +version/code, signer, non-debuggable flag, minimum SDK, native ABI inventory, +fixture exclusion and both dexopt profiles. It emits four standalone APKs: +`Wolfskin-armeabi-v7a.apk`, `Wolfskin-arm64-v8a.apk`, `Wolfskin-x86_64.apk`, +and universal `Wolfskin.apk`; plus `wolfskin-update.json`, `RELEASE-NOTES.md` +and `SHA256SUMS`. Hashes and sizes come from final signed bytes. Universal +32-bit x86 is not MPV-complete and is not a supported playback ABI. + +Manifest schema 1 contains `packageId`, `versionName`, `versionCode`, +`publishedAt` (UTC ISO-8601), immutable `sourceCommit`, `sourceTag`, +`signerSha256`, and `assets[]` with `abi`, `name`, `bytes`, `sha256`, `minSdk`. +All ABI outputs share one code/signer/identity. The local source tag is +`pwolfskin-opt-v`; the distribution tag is `wolfskin-opt-v`. +After successful packaging the builder appends the code to the tracked ledger. +Commit that reservation and explicitly push the source tag before distribution. +An existing output directory is refused to preserve previous evidence. + +Keep `private/` private: build/dependency logs, R8 mapping/effective configuration, +APK metadata/certificate inspection and native/ZIP inventory. Publication uploads +only the seven named public files, never that directory, credentials or keys. +Review release notes and corresponding-source/native links before promotion. + +### Explicit draft publication + +```sh +make tv-publish TV_RELEASE_DIR=/var/tmp/wolfskin-tv-release-1.1.1 \ + TV_PUBLISH_FLAGS=--dry-run +# Only after owner approval to upload: +make tv-publish TV_RELEASE_DIR=/var/tmp/wolfskin-tv-release-1.1.1 +# Only after owner approval to publish the verified draft (use its printed id): +make tv-publish TV_RELEASE_DIR=/var/tmp/wolfskin-tv-release-1.1.1 \ + TV_PUBLISH_FLAGS='--draft-id --promote' +make tv-tooling-test +``` + +The publisher reads git's credential helper into process memory, not arguments, +logs or files. It creates a draft, uploads all public files, then downloads and +hashes their bytes while still draft. Existing matching drafts can be resumed +and reverified. Upload/verification failures remain draft. Promotion requires +the explicit flag; then anonymous latest/asset hash checks must pass. A failed +post-promotion check attempts withdrawal to draft and reports failure, not +success. Cross-origin credential forwarding and non-HTTPS URLs are refused. +`--test-server` permits only a loopback HTTP fake Forgejo; production defaults +cannot be redirected to a different repository by a CLI repository argument. +Dry-run never fetches a credential or makes publication requests. + +### Client trust and installation + +`UpdateController` is the process-scoped UI contract with `StateFlow` state, +shared auto-check preference, refreshed PackageManager installed version and +explicit check/download/cancel/install/retry/resume actions. Its capture fake +does not perform real operations. Classic Opt update controls use that same +controller; the old package retains its original updater. + +The client uses a dedicated anonymous OkHttp client, validating every redirect: +HTTPS, no URL user-info, no cookies/Jellyfin token/repository credential. +Loopback HTTP is available only through the test transport constructor flag. +It selects armeabi-v7a first when supported, then remaining device ABIs and +a universal fallback, subject to minSdk. Universal fallback is limited to +the channel's supported playback ABIs: armeabi-v7a, arm64-v8a and x86_64. +It cannot make an unsupported processor compatible. Empty-release-list success +is distinct from a latest-endpoint 404, authorization failure, invalid metadata +or up-to-date code. + +Downloads are app-private. Retry starts a new truncated partial rather than +concatenating unvalidated ranges; cancel and process recreation discard partials. +Length, SHA-256, APK PackageManager package/version/current signer and manifest +signer must agree before Ready. Restoring Ready re-hashes/re-inspects the APK. +Checksum files on the same server are not an independent trust authority: +the installed Android signer is the installation boundary. + +EOF never starts installation. Install requires a separate OK, per-package +unknown-app permission and a confirmation-required PackageInstaller session. +Returning from permission settings requires another explicit Install press. +Denial, cancellation and missing system handlers retain the verified download. +No broad FileProvider, public Downloads write, silent install or automatic +uninstall is involved. PackageManager is re-read on return; a successful callback +is not proof that the running process is the new version. Real OEM confirmation, +process replacement and retained-login acceptance remain device-walk gates. + + ### Full-suite test diagnostics The Gradle daemon heap (`org.gradle.jvmargs` in `gradle.properties`) is separate @@ -89,13 +217,12 @@ wait for either response. The minified SDK log tag is not stable across builds. The `optimized` build type inherits `release`: R8 optimization/minification, resource shrinking, non-debuggable code, dependency consumer keep rules and -dependency baseline profiles. It changes only signing (the Android debug key), -package (`org.justinvisser.wolfskin.tv.opt`) and launcher label (`Wolfskin (Opt)`). -The launcher icon/banner and release-compatible version name are unchanged: -the shared upgrade/updater parser rejects extra suffixes such as `-opt`. -`make apk` remains the clean, release-key-signed production build. Debug and -optimized containers share the persistent debug key described below; release -signing is unchanged. +dependency baseline profiles. Its package (`org.justinvisser.wolfskin.tv.opt`), +launcher label (`Wolfskin (Opt)`) and persistent signer remain unchanged. It is +the household release assembly, with plain versionName `1.1.1` and an explicit +monotonic versionCode; source commit identity is recorded separately. +`make apk` remains the old `org.justinvisser.wolfskin.tv` production assembly and +release signer. It must never publish to the household channel. Build all four default-flavor outputs in one invocation through the container wrapper, without a release keystore. On a host whose Gradle cache already holds @@ -103,6 +230,7 @@ the pinned native extensions and their metadata: ```sh bash docker/gradle.sh optimized --offline \ + -PtvVersion=1.1.1 -PtvVersionCode=100001 \ -PWholphinExtensionsUsername=JustinZeus \ -PWholphinExtensionsPassword=unused \ :app:assembleDefaultOptimized @@ -926,14 +1054,12 @@ Jellyfin read by the selected person's saved Jellyfin user ID, so a lost Conductarr operator or a renamed household profile does not hide that user's own library. A different saved user ID still fails closed. -`make test` runs `OwnedSourceAuditTest` through the design module's JVM suite. -It scans the owned Kotlin sources in `wolfskin-design/src/main/java` and -`app/src/wolfskin`, rejecting untokened `.dp`/`.sp` conversions and numeric Color -constructors outside generated tokens, token font sizes below 12 sp, raw -household library labels, and page-counter/navigation wording. Its negative -cases plant each violation independently. Existing native capture checks also -verify rendered font sizes and wording. `LibraryProgressiveSurfaceTest` captures -the usable first chunk while the final read is still suspended. +`make test` keeps the native capture checks for rendered font sizes and visible +surface behavior, plus generated-token drift checks. Styling uses generated +tokens rather than raw dimensions. The source-regex wording/style audit was +removed: source spelling is not a consumer-visible behavior contract. +`LibraryProgressiveSurfaceTest` captures the usable first chunk while the final +read is still suspended. ## Toolchain and disk use @@ -980,21 +1106,25 @@ the checkout when building on another host, for example: WOLFSKIN_DEBUG_KEYSTORE="$HOME/.local/share/wolfskin-signing/debug.keystore" make apk-debug ``` -The wrapper creates a missing key once using the build image's `keytool`: RSA -2048, 10,000-day validity, alias `androiddebugkey`, store/key passwords `android`, -and subject `CN=Android Debug`. The containing directory is mode `0700`, the -file mode `0600`. Existing keys are reused, never regenerated; generation errors -abort the build rather than falling back to an ephemeral container key. +For ordinary debug builds only, the wrapper creates a missing key once using +the build image's `keytool`: RSA 2048, 10,000-day validity, alias +`androiddebugkey`, store/key passwords `android`, subject `CN=Android Debug`. +Household and optimized modes require the existing key and refuse generation. +The directory is mode `0700`, the file mode `0600`; existing keys are reused. +Generation errors abort rather than falling back to an ephemeral container key. The file is bind-mounted read-only at `/tmp/.android/debug.keystore`, with `ANDROID_USER_HOME=/tmp/.android`, for every non-release Gradle container. Keep and back up this file across clean builds, disposable worktrees, container rebuilds and Gradle cache resets. Never commit it. The standard debug passwords -are public; this key is for local debug/optimized builds, not release signing. +are public; the private key is nevertheless the permanent household signing +authority. It is distinct from the old production package's release signer. ### Preserve household TV data -Install and update the household TV app only in place with `adb install -r`, -using the same package and persistent debug signer. Its certificate SHA-256 is: +Normal household updates use the in-app verified download and explicit Android +confirmation, preserving the same package and persistent signer. A separately +authorized bootstrap may use operator `adb install -r`; that is not a substitute +for the in-app update acceptance walk. The certificate SHA-256 is: ```text 182bac72e292b9ea4d3d4e6383f92eb2161fa28ba5afcff0337cb7d5a9d5341d @@ -1012,9 +1142,10 @@ a **keep app data** choice during interactive uninstall. Choose it when available; older Android versions ignore the attribute. This is a retention prompt, not an automatic backup or a guarantee against data clearing. -For an in-place update, compare `dumpsys package ` before and after: -`firstInstallTime` must remain unchanged. The guarded installer that checks -the signer and this timestamp lives in the operator's tooling, not this repo. +An operator can compare `dumpsys package ` before and after an in-place +update: `firstInstallTime` must remain unchanged. The in-app service checks +package, current signer, checksum and higher code; real-device timestamp and +retained-login proof remain a separate operator walk, not a JVM-test claim. ## Release credentials diff --git a/docker/gradle.sh b/docker/gradle.sh index 461018bc..7249cf82 100755 --- a/docker/gradle.sh +++ b/docker/gradle.sh @@ -45,6 +45,10 @@ else signing_directory=$(dirname "$debug_keystore") mkdir -p "$signing_directory" chmod 700 "$signing_directory" + if [[ ( $mode == household || $mode == optimized ) && ! -s $debug_keystore ]]; then + printf 'Household signing key is required; refusing to generate an identity\n' >&2 + exit 1 + fi if [[ ! -e $debug_keystore ]]; then temporary_directory=$(mktemp -d "$signing_directory/.debug-keystore.XXXXXX") trap 'rm -rf -- "$temporary_directory"' EXIT @@ -66,5 +70,15 @@ else chmod 600 "$debug_keystore" arguments+=(--env ANDROID_USER_HOME=/tmp/.android --mount "type=bind,src=$debug_keystore,dst=/tmp/.android/debug.keystore,readonly") - docker run "${arguments[@]}" "$image" ./gradlew "${gradle_arguments[@]}" "$@" + if [[ $mode == household ]]; then + [[ -s $secrets/github-packages-token ]] || { printf 'Missing native package credential\n' >&2; exit 1; } + arguments+=(--mount "type=bind,src=$secrets/github-packages-token,dst=/run/native-token,readonly") + docker run "${arguments[@]}" "$image" bash -euc ' + export ORG_GRADLE_PROJECT_WholphinExtensionsUsername=JustinZeus + export ORG_GRADLE_PROJECT_WholphinExtensionsPassword=$(cat /run/native-token) + exec ./gradlew "$@" + ' bash "${gradle_arguments[@]}" "$@" + else + docker run "${arguments[@]}" "$image" ./gradlew "${gradle_arguments[@]}" "$@" + fi fi diff --git a/docker/test_tv_publish.py b/docker/test_tv_publish.py new file mode 100644 index 00000000..2c7673d8 --- /dev/null +++ b/docker/test_tv_publish.py @@ -0,0 +1,280 @@ +"""Exercise the release CLI against a local Forgejo-shaped HTTP server.""" + +import email.parser +import email.policy +import hashlib +import json +import os +import subprocess +import sys +import tempfile +import threading +import unittest +import urllib.parse +from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer +from pathlib import Path +from typing import Any +from unittest.mock import patch + +from tv_publish import REQUIRED, Forge +from tv_release import PACKAGE, SIGNER + + +class FakeForge: + """Draft assets require authentication; anonymous reads work only after promotion.""" + + def __init__(self) -> None: + self.release: dict[str, Any] = {} + self.assets: dict[str, bytes] = {} + self.events: list[tuple[str, bool]] = [] + self.corrupt_draft = False + self.corrupt_public = False + self.redirect_url: str | None = None + fixture = self + + class Handler(BaseHTTPRequestHandler): + def log_message(self, format: str, *args: Any) -> None: + pass + + def respond(self, value: Any, code: int = 200) -> None: + data = value if isinstance(value, bytes) else json.dumps(value).encode() + self.send_response(code) + self.send_header("Content-Length", str(len(data))) + self.end_headers() + self.wfile.write(data) + + def do_POST(self) -> None: + authenticated = bool(self.headers.get("Authorization")) + fixture.events.append(("POST " + self.path, authenticated)) + if not authenticated: + self.respond({}, 401) + return + data = self.rfile.read(int(self.headers["Content-Length"])) + if self.path.endswith("/releases"): + fixture.release = json.loads(data) | {"id": 17, "assets": []} + self.respond(fixture.release) + else: + name = urllib.parse.parse_qs( + urllib.parse.urlsplit(self.path).query + )["name"][0] + message = email.parser.BytesParser( + policy=email.policy.default + ).parsebytes( + b"Content-Type: " + + self.headers["Content-Type"].encode() + + b"\r\n\r\n" + + data + ) + fixture.assets[name] = next(message.iter_parts()).get_payload( + decode=True + ) + asset = { + "name": name, + "browser_download_url": fixture.base + "/assets/" + name, + "size": len(fixture.assets[name]), + } + fixture.release["assets"].append(asset) + self.respond(asset) + + def do_PATCH(self) -> None: + fixture.events.append( + ("PATCH", bool(self.headers.get("Authorization"))) + ) + fixture.release.update( + json.loads(self.rfile.read(int(self.headers["Content-Length"]))) + ) + self.respond(fixture.release) + + def do_GET(self) -> None: + authenticated = bool(self.headers.get("Authorization")) + fixture.events.append(("GET " + self.path, authenticated)) + if fixture.redirect_url: + self.send_response(302) + self.send_header("Location", fixture.redirect_url) + self.end_headers() + return + if self.path.startswith("/assets/"): + if fixture.release["draft"] and not authenticated: + self.respond({}, 404) + return + data = fixture.assets[self.path.removeprefix("/assets/")] + corrupt = ( + fixture.corrupt_draft + if fixture.release["draft"] + else fixture.corrupt_public + ) + self.respond(data + b"corrupt" if corrupt else data) + elif self.path.endswith("/latest") and fixture.release.get( + "draft", True + ): + self.respond({}, 404) + else: + self.respond(fixture.release) + + self.server = ThreadingHTTPServer(("127.0.0.1", 0), Handler) + self.base = f"http://127.0.0.1:{self.server.server_port}" + self.thread = threading.Thread(target=self.server.serve_forever, daemon=True) + self.thread.start() + + def close(self) -> None: + """Release fixture resources after each independent publication scenario.""" + self.server.shutdown() + self.server.server_close() + self.thread.join() + + +class PublishTest(unittest.TestCase): + """Permanent tests assert safety transitions and real uploaded bytes, not script wording.""" + + def setUp(self) -> None: + self.temporary = tempfile.TemporaryDirectory() + self.directory = Path(self.temporary.name) + self.forge = FakeForge() + self.addCleanup(self.forge.close) + self.addCleanup(self.temporary.cleanup) + assets = [] + for abi in ("armeabi-v7a", "arm64-v8a", "x86_64", "universal"): + name = "Wolfskin.apk" if abi == "universal" else f"Wolfskin-{abi}.apk" + data = f"fixture APK bytes for {abi}".encode() + (self.directory / name).write_bytes(data) + assets.append( + { + "name": name, + "abi": abi, + "bytes": len(data), + "sha256": hashlib.sha256(data).hexdigest(), + "minSdk": 23, + } + ) + manifest = { + "schemaVersion": 1, + "packageId": PACKAGE, + "versionName": "1.1.1", + "versionCode": 100001, + "publishedAt": "2026-11-07T12:00:00Z", + "sourceCommit": "a" * 40, + "sourceTag": "pwolfskin-opt-v1.1.1", + "signerSha256": SIGNER, + "assets": assets, + } + (self.directory / "wolfskin-update.json").write_text(json.dumps(manifest)) + (self.directory / "RELEASE-NOTES.md").write_text("Fixture release notes") + self.checksums() + + def checksums(self) -> None: + """Hash fixture files after deliberately constructing or mutating the bundle.""" + (self.directory / "SHA256SUMS").write_text( + "".join( + f"{hashlib.sha256((self.directory / name).read_bytes()).hexdigest()} {name}\n" + for name in sorted(REQUIRED - {"SHA256SUMS"}) + ) + ) + + def cli(self, *flags: str) -> subprocess.CompletedProcess[str]: + """Drive the real CLI and real git credential-helper protocol with a fake credential.""" + environment = os.environ | { + "GIT_CONFIG_COUNT": "2", + "GIT_CONFIG_KEY_0": "credential.helper", + "GIT_CONFIG_VALUE_0": "", + "GIT_CONFIG_KEY_1": "credential.helper", + "GIT_CONFIG_VALUE_1": "!printf 'username=fixture\npassword=fixture-secret\n'", + } + result = subprocess.run( + [ + sys.executable, + str(Path(__file__).with_name("tv_publish.py")), + "--directory", + str(self.directory), + "--test-server", + self.forge.base, + *flags, + ], + capture_output=True, + text=True, + env=environment, + timeout=30, + check=False, + ) + self.assertNotIn("fixture-secret", result.stdout + result.stderr) + return result + + def test_dry_run_never_requests_or_fetches_credentials(self) -> None: + result = self.cli("--dry-run", "--promote") + self.assertEqual(0, result.returncode, result.stderr) + self.assertEqual([], self.forge.events) + + def test_draft_then_explicit_promotion_reverifies_all_bytes(self) -> None: + result = self.cli() + self.assertEqual(0, result.returncode, result.stderr) + self.assertTrue(self.forge.release["draft"]) + self.assertEqual(REQUIRED, set(self.forge.assets)) + self.assertTrue(all(auth for _, auth in self.forge.events)) + result = self.cli("--draft-id", "17", "--promote") + self.assertEqual(0, result.returncode, result.stderr) + self.assertFalse(self.forge.release["draft"]) + for name, data in self.forge.assets.items(): + self.assertEqual((self.directory / name).read_bytes(), data) + anonymous = [ + event for event, authenticated in self.forge.events if not authenticated + ] + self.assertEqual(8, len(anonymous)) + + def test_corrupt_uploaded_bytes_remain_draft(self) -> None: + self.forge.corrupt_draft = True + result = self.cli("--promote") + self.assertNotEqual(0, result.returncode) + self.assertTrue(self.forge.release["draft"]) + self.assertFalse(any(event == "PATCH" for event, _ in self.forge.events)) + + def test_failed_anonymous_verification_withdraws_promoted_release(self) -> None: + self.forge.corrupt_public = True + result = self.cli("--promote") + self.assertNotEqual(0, result.returncode) + self.assertTrue(self.forge.release["draft"]) + self.assertEqual(2, sum(event == "PATCH" for event, _ in self.forge.events)) + + def test_invalid_local_checksum_never_creates_draft(self) -> None: + (self.directory / "Wolfskin.apk").write_bytes(b"tampered") + result = self.cli() + self.assertNotEqual(0, result.returncode) + self.assertEqual([], self.forge.events) + + def test_manifest_size_mismatch_never_creates_draft(self) -> None: + path = self.directory / "wolfskin-update.json" + manifest = json.loads(path.read_text()) + manifest["assets"][0]["bytes"] += 1 + path.write_text(json.dumps(manifest)) + self.checksums() + result = self.cli() + self.assertNotEqual(0, result.returncode) + self.assertEqual([], self.forge.events) + + def test_empty_manifest_asset_set_never_creates_draft(self) -> None: + path = self.directory / "wolfskin-update.json" + manifest = json.loads(path.read_text()) + manifest["assets"] = [] + path.write_text(json.dumps(manifest)) + self.checksums() + result = self.cli() + self.assertNotEqual(0, result.returncode) + self.assertEqual([], self.forge.events) + + def test_credential_helper_tracing_is_disabled(self) -> None: + trace = self.directory / "credential.trace" + with patch.dict(os.environ, {"GIT_TRACE": str(trace)}): + result = self.cli() + self.assertEqual(0, result.returncode, result.stderr) + self.assertFalse(trace.exists()) + + def test_authenticated_redirect_never_reaches_another_origin(self) -> None: + other = FakeForge() + self.addCleanup(other.close) + self.forge.redirect_url = other.base + "/asset" + forge = Forge(self.forge.base, "Basic fixture-authorization", test_server=True) + with self.assertRaises(ValueError): + forge.verify(self.forge.base + "/redirect", "0" * 64, authenticated=True) + self.assertEqual([], other.events) + + +if __name__ == "__main__": + unittest.main() diff --git a/docker/test_tv_release.py b/docker/test_tv_release.py new file mode 100644 index 00000000..31dbef1f --- /dev/null +++ b/docker/test_tv_release.py @@ -0,0 +1,100 @@ +"""Exercise source cleanliness, monotonic codes and fail-closed signing prerequisites.""" + +import contextlib +import io +import os +import subprocess +import tempfile +import unittest +from pathlib import Path +from unittest.mock import patch + +import tv_release + + +class ReleaseInputTest(unittest.TestCase): + """Use a disposable Git fixture, never a build or a real signing key.""" + + def setUp(self) -> None: + self.temporary = tempfile.TemporaryDirectory() + self.addCleanup(self.temporary.cleanup) + self.root = Path(self.temporary.name) / "source" + self.root.mkdir() + (self.root / "docker").mkdir() + (self.root / "docker/tv-version-codes").write_text("65 installed-opt\n") + self.git("init", "--quiet") + self.git("add", "docker/tv-version-codes") + self.git( + "-c", + "user.name=Fixture", + "-c", + "user.email=fixture@example.invalid", + "commit", + "--quiet", + "-m", + "Record used code", + ) + self.previous_root = tv_release.ROOT + tv_release.ROOT = self.root + self.addCleanup(setattr, tv_release, "ROOT", self.previous_root) + + def git(self, *args: str) -> str: + """Run the isolated source fixture's actual Git commands.""" + return subprocess.check_output(["git", *args], cwd=self.root, text=True).strip() + + def test_new_code_identifies_clean_source(self) -> None: + self.assertEqual( + self.git("rev-parse", "HEAD"), tv_release.validate_inputs("1.1.1", 100001) + ) + + def test_reused_and_lower_codes_are_rejected(self) -> None: + for code in (1, 64, 65): + with self.subTest(code=code), self.assertRaises(ValueError): + tv_release.validate_inputs("1.1.1", code) + + def test_dirty_source_is_rejected(self) -> None: + (self.root / "untracked").write_text("not part of the source commit") + with self.assertRaises(ValueError): + tv_release.validate_inputs("1.1.1", 100001) + + def test_unparseable_version_and_invalid_codes_are_rejected(self) -> None: + for version, code in ( + ("1.1.1-opt", 100001), + ("1.1.1", 0), + ("1.1.1", 2100000001), + ): + with ( + self.subTest(version=version, code=code), + self.assertRaises(ValueError), + ): + tv_release.validate_inputs(version, code) + + def test_missing_signing_key_never_generates_identity(self) -> None: + key = Path(self.temporary.name) / "absent-key" + with ( + patch.dict(os.environ, {"WOLFSKIN_DEBUG_KEYSTORE": str(key)}), + self.assertRaises(ValueError), + ): + tv_release.release( + "1.1.1", 100001, Path(self.temporary.name) / "output", True + ) + self.assertFalse(key.exists()) + + def test_dry_run_never_builds_tags_or_mutates_ledger(self) -> None: + key = Path(self.temporary.name) / "fixture-key-presence-only" + key.write_bytes(b"not an actual keystore; dry run must not open it") + output = Path(self.temporary.name) / "output" + with ( + patch.dict(os.environ, {"WOLFSKIN_DEBUG_KEYSTORE": str(key)}), + contextlib.redirect_stdout(io.StringIO()), + ): + tv_release.release("1.1.1", 100001, output, True) + self.assertFalse(output.exists()) + self.assertEqual("", self.git("tag", "--list")) + self.assertEqual( + "65 installed-opt\n", (self.root / "docker/tv-version-codes").read_text() + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/docker/tv-version-codes b/docker/tv-version-codes new file mode 100644 index 00000000..63071ca8 --- /dev/null +++ b/docker/tv-version-codes @@ -0,0 +1,3 @@ +# Household org.justinvisser.wolfskin.tv.opt codes already used. +# Append successful tv-release codes; commit this ledger before another release. +65 installed-opt diff --git a/docker/tv_publish.py b/docker/tv_publish.py new file mode 100755 index 00000000..99f4d040 --- /dev/null +++ b/docker/tv_publish.py @@ -0,0 +1,368 @@ +#!/usr/bin/env python3 +"""Upload a verified draft; promote only with explicit --promote owner approval.""" + +import argparse +import base64 +import datetime +import hashlib +import json +import os +import re +import subprocess +import urllib.error +import urllib.parse +import urllib.request +import uuid +from collections.abc import Iterable +from pathlib import Path +from typing import Any + +SERVER = "https://git.justinvisser.org" +REPOSITORY = "justinzeus/wolfskin-tv-updates" +REQUIRED = { + "Wolfskin-armeabi-v7a.apk", + "Wolfskin-arm64-v8a.apk", + "Wolfskin-x86_64.apk", + "Wolfskin.apk", + "wolfskin-update.json", + "RELEASE-NOTES.md", + "SHA256SUMS", +} + + +class NoRedirect(urllib.request.HTTPRedirectHandler): + """Validate every redirect before forwarding distribution-tool credentials.""" + + def redirect_request( + self, req: Any, fp: Any, code: int, msg: str, headers: Any, newurl: str + ) -> None: + return None + + +class Forge: + """Credential-scoped release API; credentials exist only in process memory.""" + + def __init__( + self, server: str, authorization: str, test_server: bool = False + ) -> None: + self.server = server.rstrip("/") + self.origin = urllib.parse.urlsplit(self.server) + self.authorization = authorization + self.test_server = test_server + self.opener = urllib.request.build_opener(NoRedirect) + self.api = self.server + "/api/v1/repos/" + REPOSITORY + + def request( + self, + method: str, + url: str, + data: Any = None, + content_type: str | None = None, + length: int | None = None, + authenticated: bool = True, + ) -> Any: + """Reject cross-origin credential forwarding and non-HTTPS production URLs.""" + for _ in range(6): + parsed = urllib.parse.urlsplit(url) + local = self.test_server and parsed.hostname in ( + "localhost", + "127.0.0.1", + "::1", + ) + if ( + parsed.username + or parsed.password + or (parsed.scheme != "https" and not local) + ): + raise ValueError( + "Distribution requests require credential-free HTTPS URLs" + ) + if authenticated and (parsed.scheme, parsed.netloc) != ( + self.origin.scheme, + self.origin.netloc, + ): + raise ValueError( + "Refusing to send release credentials to another origin" + ) + headers = {"Accept": "application/json"} + if authenticated: + headers["Authorization"] = self.authorization + if content_type: + headers["Content-Type"] = content_type + if length is not None: + headers["Content-Length"] = str(length) + request = urllib.request.Request( + url, data=data, method=method, headers=headers + ) + try: + return self.opener.open(request, timeout=60) + except urllib.error.HTTPError as error: + if method != "GET" or error.code not in (301, 302, 303, 307, 308): + raise RuntimeError( + f"Forgejo {method} failed: HTTP {error.code}" + ) from None + location = error.headers.get("Location") + error.close() + if not location: + raise ValueError("Forgejo redirect has no location") + url = urllib.parse.urljoin(url, location) + raise ValueError("Too many Forgejo redirects") + + def json( + self, + method: str, + path: str, + value: dict[str, Any] | None = None, + authenticated: bool = True, + ) -> Any: + """Read or mutate release metadata without exposing HTTP authorization.""" + data = None if value is None else json.dumps(value).encode() + with self.request( + method, + self.api + path, + data, + "application/json", + authenticated=authenticated, + ) as response: + return json.load(response) + + def upload(self, release_id: int, file: Path) -> dict[str, Any]: + """Stream multipart APK bytes instead of copying a universal APK into memory.""" + boundary = uuid.uuid4().hex + prefix = ( + f'--{boundary}\r\nContent-Disposition: form-data; name="attachment"; filename="{file.name}"\r\n' + "Content-Type: application/octet-stream\r\n\r\n" + ).encode() + suffix = f"\r\n--{boundary}--\r\n".encode() + + def chunks() -> Iterable[bytes]: + yield prefix + with file.open("rb") as stream: + while chunk := stream.read(1024 * 1024): + yield chunk + yield suffix + + url = f"{self.api}/releases/{release_id}/assets?name={urllib.parse.quote(file.name)}" + with self.request( + "POST", + url, + chunks(), + f"multipart/form-data; boundary={boundary}", + len(prefix) + file.stat().st_size + len(suffix), + ) as response: + return json.load(response) + + def verify(self, url: str, expected: str, authenticated: bool) -> None: + """Verify bytes fetched from Forgejo, not only its declared asset size.""" + with self.request("GET", url, authenticated=authenticated) as response: + actual = hashlib.file_digest(response, "sha256").hexdigest() + if actual != expected: + raise ValueError("Uploaded artifact checksum mismatch") + + +def credential(server: str) -> str: + """Read git's existing credential helper without secrets in argv, stdout or disk.""" + parsed = urllib.parse.urlsplit(server) + environment = { + name: value + for name, value in os.environ.items() + if not name.startswith("GIT_TRACE") + and name not in {"GIT_CURL_VERBOSE", "SHELLOPTS", "BASHOPTS", "BASH_ENV", "ENV"} + } + environment["GIT_TERMINAL_PROMPT"] = "0" + result = subprocess.run( + ["git", "credential", "fill"], + input=f"protocol={parsed.scheme}\nhost={parsed.netloc}\n\n", + text=True, + capture_output=True, + check=False, + env=environment, + ) + if result.returncode: + raise RuntimeError("Git credential helper failed; no release created") + fields = dict( + line.split("=", 1) for line in result.stdout.splitlines() if "=" in line + ) + if not fields.get("password"): + raise ValueError("Git credential helper returned no release credential") + encoded = base64.b64encode( + f"{fields.get('username', '')}:{fields['password']}".encode() + ).decode() + return "Basic " + encoded + + +def validate_bundle(directory: Path) -> tuple[dict[str, Any], dict[str, str]]: + """Require every public asset and verify the local final-byte checksum set.""" + for name in REQUIRED: + if not (directory / name).is_file(): + raise ValueError(f"Required release asset missing: {name}") + hashes: dict[str, str] = {} + for line in (directory / "SHA256SUMS").read_text().splitlines(): + match = re.fullmatch(r"([0-9a-f]{64}) ([A-Za-z0-9_.-]+)", line) + if match is None or match[2] in hashes: + raise ValueError("Invalid or duplicate SHA256SUMS entry") + hashes[match[2]] = match[1] + if set(hashes) != REQUIRED - {"SHA256SUMS"}: + raise ValueError("Checksum set must cover exactly the public artifacts") + for name, expected in hashes.items(): + with (directory / name).open("rb") as stream: + if hashlib.file_digest(stream, "sha256").hexdigest() != expected: + raise ValueError(f"Local checksum mismatch: {name}") + hashes["SHA256SUMS"] = hashlib.sha256( + (directory / "SHA256SUMS").read_bytes() + ).hexdigest() + manifest = json.loads((directory / "wolfskin-update.json").read_text()) + if ( + manifest["schemaVersion"] != 1 + or manifest["packageId"] != "org.justinvisser.wolfskin.tv.opt" + ): + raise ValueError("Wrong household manifest identity") + if ( + manifest["signerSha256"] + != "182bac72e292b9ea4d3d4e6383f92eb2161fa28ba5afcff0337cb7d5a9d5341d" + ): + raise ValueError("Wrong household signing authority") + version = manifest["versionName"] + code = manifest["versionCode"] + if ( + not re.fullmatch(r"\d+\.\d+\.\d+", version) + or type(code) is not int + or not 1 <= code <= 2100000000 + ): + raise ValueError("Invalid household version identity") + if ( + not re.fullmatch(r"[0-9a-f]{40}", manifest["sourceCommit"]) + or manifest["sourceTag"] != f"pwolfskin-opt-v{version}" + ): + raise ValueError("Invalid immutable source identity") + published = datetime.datetime.fromisoformat( + manifest["publishedAt"].replace("Z", "+00:00") + ) + if published.utcoffset() is None: + raise ValueError("Publication time must include a timezone") + expected_abis = {"armeabi-v7a", "arm64-v8a", "x86_64", "universal"} + if ( + len(manifest["assets"]) != 4 + or {asset["abi"] for asset in manifest["assets"]} != expected_abis + ): + raise ValueError("Manifest must describe all four standalone APKs") + for asset in manifest["assets"]: + expected_name = ( + "Wolfskin.apk" + if asset["abi"] == "universal" + else f"Wolfskin-{asset['abi']}.apk" + ) + if asset["name"] != expected_name or asset["minSdk"] < 23: + raise ValueError("Invalid APK asset identity or minimum SDK") + path = directory / asset["name"] + if ( + hashes.get(path.name) != asset["sha256"] + or path.stat().st_size != asset["bytes"] + ): + raise ValueError("Manifest does not match final APK bytes") + return manifest, hashes + + +def publish( + directory: Path, + server: str, + promote: bool, + dry_run: bool, + test_server: bool = False, + draft_id: int | None = None, +) -> None: + """Keep incomplete uploads draft; withdraw a failed promoted release from latest.""" + manifest, hashes = validate_bundle(directory) + version = manifest["versionName"] + tag = f"wolfskin-opt-v{version}" + if dry_run: + print( + f"Dry run: draft {REPOSITORY} {tag}; upload and verify {len(hashes)} assets; promote={promote}; no requests or credentials" + ) + return + forge = Forge(server, credential(server), test_server) + if draft_id is None: + release = forge.json( + "POST", + "/releases", + { + "name": f"v{version}", + "tag_name": tag, + "body": (directory / "RELEASE-NOTES.md").read_text(), + "draft": True, + "prerelease": False, + }, + ) + else: + release = forge.json("GET", f"/releases/{draft_id}") + if not release["draft"] or release["tag_name"] != tag: + raise ValueError("Resume target must be the matching draft release") + release_id = release["id"] + existing = {asset["name"]: asset for asset in release.get("assets", [])} + print( + f"Verifying draft release {release_id}; it stays draft on any verification failure" + ) + uploaded: dict[str, str] = {} + for name, expected in hashes.items(): + asset = existing.get(name) or forge.upload(release_id, directory / name) + url = asset["browser_download_url"] + forge.verify(url, expected, authenticated=True) + uploaded[name] = url + if not promote: + print( + "Draft upload verified. Publication requires owner approval and explicit --promote." + ) + return + try: + forge.json("PATCH", f"/releases/{release_id}", {"draft": False}) + latest = forge.json("GET", "/releases/latest", authenticated=False) + if latest["id"] != release_id or latest["tag_name"] != tag: + raise ValueError("Anonymous latest does not identify the promoted release") + for name, url in uploaded.items(): + forge.verify(url, hashes[name], authenticated=False) + except (ValueError, RuntimeError, OSError, KeyError, TypeError): + try: + forge.json("PATCH", f"/releases/{release_id}", {"draft": True}) + except (ValueError, RuntimeError, OSError): + raise RuntimeError( + "Post-publication verification AND withdrawal failed; release may remain public" + ) from None + raise RuntimeError( + "Post-publication verification failed; release withdrawn to draft" + ) from None + print(f"Published and anonymously verified {tag}") + + +def main() -> None: + """Expose a deliberately separate publication command.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--directory", required=True, type=Path) + parser.add_argument("--promote", action="store_true") + parser.add_argument("--dry-run", action="store_true") + parser.add_argument( + "--draft-id", type=int, help="Resume and reverify an existing matching draft" + ) + parser.add_argument( + "--test-server", help="Local fake Forgejo only; HTTP loopback permitted" + ) + args = parser.parse_args() + if args.test_server: + parsed = urllib.parse.urlsplit(args.test_server) + if parsed.scheme != "http" or parsed.hostname not in ( + "localhost", + "127.0.0.1", + "::1", + ): + parser.error("--test-server is restricted to an HTTP loopback fixture") + publish( + args.directory.resolve(), + args.test_server or SERVER, + args.promote, + args.dry_run, + bool(args.test_server), + args.draft_id, + ) + + +if __name__ == "__main__": + main() diff --git a/docker/tv_release.py b/docker/tv_release.py new file mode 100755 index 00000000..8a147ce3 --- /dev/null +++ b/docker/tv_release.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python3 +"""Build and inspect the household assembly without creating a signing identity.""" + +import argparse +import datetime +import hashlib +import json +import os +import re +import shutil +import subprocess +import zipfile +from pathlib import Path + +PACKAGE = "org.justinvisser.wolfskin.tv.opt" +SIGNER = "182bac72e292b9ea4d3d4e6383f92eb2161fa28ba5afcff0337cb7d5a9d5341d" +ABIS = ("armeabi-v7a", "arm64-v8a", "x86_64", "universal") +ROOT = Path(__file__).resolve().parent.parent + + +def run(*arguments: str) -> str: + """Run a checked command whose arguments contain no credentials.""" + return subprocess.check_output(arguments, cwd=ROOT, text=True).strip() + + +def digest(path: Path) -> str: + """Hash final artifact bytes without loading an APK into memory.""" + with path.open("rb") as stream: + return hashlib.file_digest(stream, "sha256").hexdigest() + + +def validate_inputs(version: str, code: int) -> str: + """Require a clean immutable source and a code newer than the tracked history.""" + if not re.fullmatch(r"\d+\.\d+\.\d+", version) or not 1 <= code <= 2100000000: + raise ValueError("Supply a plain VERSION and a positive Android VERSION_CODE") + if run("git", "status", "--porcelain"): + raise ValueError( + "Release source must be clean, including the version-code ledger" + ) + used = [ + int(line.split()[0]) + for line in (ROOT / "docker/tv-version-codes").read_text().splitlines() + if line and not line.startswith("#") + ] + if code <= max(used): + raise ValueError(f"VERSION_CODE must exceed ledger maximum {max(used)}") + if list((ROOT / "app/libs").glob("*.aar")): + raise ValueError("Local AAR overrides are forbidden for household releases") + return run("git", "rev-parse", "HEAD") + + +def inspect_apk(path: Path, version: str, code: int, abi: str, proof: Path) -> int: + """Verify identity, final signature, optimization and playback-complete native inventory.""" + image = os.environ.get("WOLFSKIN_BUILD_IMAGE", "wolfskin-build:sdk37-jdk21") + mount = f"type=bind,src={path.parent},dst=/artifacts,readonly" + base = ( + "docker", + "run", + "--rm", + "--platform", + "linux/amd64", + "--mount", + mount, + image, + ) + badging = run(*base, "aapt2", "dump", "badging", f"/artifacts/{path.name}") + certificate = run( + *base, + "apksigner", + "verify", + "--verbose", + "--print-certs", + f"/artifacts/{path.name}", + ) + proof.write_text(badging + "\n" + certificate + "\n") + package = re.search( + r"package: name='([^']+)' versionCode='(\d+)' versionName='([^']+)'", badging + ) + if package is None or package.groups() != (PACKAGE, str(code), version): + raise ValueError(f"Wrong APK identity: {path.name}") + fingerprints = re.findall( + r"Signer #\d+ certificate SHA-256 digest: ([0-9a-fA-F]+)", certificate + ) + if fingerprints != [SIGNER]: + raise ValueError(f"Wrong household signer: {path.name}") + if "application-debuggable" in badging: + raise ValueError("Household APK must not be debuggable") + minimum = re.search(r"sdkVersion:'(\d+)'", badging) + if minimum is None: + raise ValueError("APK minimum SDK is missing") + with zipfile.ZipFile(path) as archive: + names = archive.namelist() + for profile in ("assets/dexopt/baseline.prof", "assets/dexopt/baseline.profm"): + if profile not in names: + raise ValueError(f"Missing optimized profile: {profile}") + if any( + name.startswith(("assets/wolfskin-", "assets/library/")) for name in names + ): + raise ValueError("Debug fixtures leaked into the household assembly") + for target in ABIS[:-1] if abi == "universal" else (abi,): + libraries = [name for name in names if name.startswith(f"lib/{target}/")] + for component in ("mpv", "ffmpeg", "av1"): + if not any(component in name.lower() for name in libraries): + raise ValueError(f"Missing native {component} for {target}") + proof.with_suffix(".inventory").write_text("\n".join(names) + "\n") + return int(minimum.group(1)) + + +def release(version: str, code: int, output: Path, dry_run: bool) -> None: + """Produce named APKs, inspected metadata, checksums and source-linked release notes.""" + commit = validate_inputs(version, code) + tag = f"pwolfskin-opt-v{version}" + key = Path( + os.environ.get( + "WOLFSKIN_DEBUG_KEYSTORE", + "/root/.treehouse/firstmate-7bab20/2/firstmate/data/signing/debug.keystore", + ) + ) + if not key.is_file() or key.stat().st_size == 0: + raise ValueError( + "Existing household signing key required; never generate a replacement" + ) + if output.exists(): + raise ValueError("Release output must not exist; preserve previous proof") + if dry_run: + print( + f"Dry run: source {commit}; defaultOptimized {version} code {code}; four APKs, manifest, notes and SHA256SUMS; no build, tag or publication" + ) + return + existing = run("git", "tag", "--list", tag) + if existing and run("git", "rev-parse", f"{tag}^{{commit}}") != commit: + raise ValueError("Source tag already identifies another commit") + output.mkdir(parents=True) + private = output / "private" + private.mkdir(mode=0o700) + with (private / "build.log").open("w") as log: + subprocess.run( + [ + "bash", + "docker/gradle.sh", + "household", + f"-PtvVersion={version}", + f"-PtvVersionCode={code}", + "assembleDefaultOptimized", + ":app:dependencies", + "--configuration", + "defaultOptimizedRuntimeClasspath", + ], + cwd=ROOT, + check=True, + stdout=log, + stderr=subprocess.STDOUT, + ) + assets: list[dict[str, object]] = [] + for abi in ABIS: + suffix = "" if abi == "universal" else f"-{abi}" + source = ( + ROOT + / f"app/build/outputs/apk/default/optimized/Wholphin-default-optimized-{version}-{code}{suffix}.apk" + ) + target = output / f"Wolfskin{suffix}.apk" + shutil.copyfile(source, target) + minimum = inspect_apk(target, version, code, abi, private / f"{abi}.inspection") + assets.append( + { + "abi": abi, + "name": target.name, + "bytes": target.stat().st_size, + "sha256": digest(target), + "minSdk": minimum, + } + ) + mapping = ROOT / "app/build/outputs/mapping/defaultOptimized" + shutil.copytree(mapping, private / "mapping") + manifest = { + "schemaVersion": 1, + "packageId": PACKAGE, + "versionName": version, + "versionCode": code, + "publishedAt": datetime.datetime.now(datetime.UTC) + .isoformat() + .replace("+00:00", "Z"), + "sourceCommit": commit, + "sourceTag": tag, + "signerSha256": SIGNER, + "assets": assets, + } + (output / "wolfskin-update.json").write_text(json.dumps(manifest, indent=2) + "\n") + source = f"https://git.justinvisser.org/justinzeus/wolfskin/src/tag/{tag}" + (output / "RELEASE-NOTES.md").write_text( + f"# Wolfskin TV {version}\n\nIn-app verified household updates with explicit Android confirmation.\n\n" + f"Package `{PACKAGE}`, code {code}, signer SHA-256 `{SIGNER}`.\n" + "Same-package, same-signer upgrades retain app data; never uninstall or clear data to update. " + "An earlier ephemeral signer needs a separately authorized migration, not an automatic reinstall.\n\n" + "Android 6 (API 23) or later. Standalone armeabi-v7a, arm64-v8a and x86_64 APKs; " + "universal fallback. 32-bit x86 is not MPV-complete and is unsupported for playback. " + "MPV, ffmpeg and AV1 extensions: pinned Wholphin extensions 0.2.4.\n\n" + f"GPL-2.0-only; Wolfskin derives from Wholphin by damontecres and contributors. " + f"Corresponding source: [{commit}]({source}); " + f"[source archive](https://git.justinvisser.org/justinzeus/wolfskin/archive/{tag}.tar.gz).\n" + "[Upstream Wholphin](https://github.com/damontecres/wholphin), " + "[native extension source 0.2.4](https://github.com/damontecres/wholphin-extensions/tree/v0.2.4).\n" + ) + files = sorted(path for path in output.iterdir() if path.is_file()) + (output / "SHA256SUMS").write_text( + "".join(f"{digest(path)} {path.name}\n" for path in files) + ) + if not existing: + run("git", "tag", tag, commit) + with (ROOT / "docker/tv-version-codes").open("a") as ledger: + ledger.write(f"{code} {version} {commit}\n") + print( + f"Release packaged at {output}; commit the code ledger and push source tag {tag} before distribution. Nothing published." + ) + + +def main() -> None: + """Expose the make tv-release build contract.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--version", required=True) + parser.add_argument("--version-code", required=True, type=int) + parser.add_argument("--output", type=Path, required=True) + parser.add_argument("--dry-run", action="store_true") + args = parser.parse_args() + release(args.version, args.version_code, args.output.resolve(), args.dry_run) + + +if __name__ == "__main__": + main() diff --git a/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/OwnedSourceAuditTest.kt b/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/OwnedSourceAuditTest.kt deleted file mode 100644 index ec217257..00000000 --- a/wolfskin-design/src/test/java/org/justinvisser/wolfskin/design/OwnedSourceAuditTest.kt +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -package org.justinvisser.wolfskin.design - -import java.io.File -import org.junit.Assert.* -import org.junit.Test - -/** The normal JVM gate rejects untokened styling, undersized typography and internal screen wording. */ -class OwnedSourceAuditTest { - @Test fun ownedScreensUseTokensReadableTextAndViewerFacingNames() { - val roots = listOf(File("src/main/java"), File("../app/src/wolfskin")) - roots.forEach { assertTrue("Missing owned source root: $it", it.isDirectory) } - val violations = roots.flatMap { root -> - root.walkTopDown().filter { it.isFile && it.extension == "kt" }.flatMap { source -> - audit(source.name, source.readText()).map { "$source:$it" } - }.toList() - } - assertTrue(violations.joinToString("\n"), violations.isEmpty()) - } - - @Test fun plantedViolationsFailEachDoneBarRule() { - val cases = listOf( - Triple("Screen.kt", "Box(Modifier.width(12.dp))", "unit"), - Triple("Screen.kt", "Box(Modifier.width(12f.dp))", "unit"), - Triple("Screen.kt", "Text(fontSize = 14.sp)", "unit"), - Triple("Screen.kt", "Box(Modifier.width((width + gap).dp))", "unit"), - Triple("Screen.kt", "Text(color = Color(0xFF123456))", "color"), - Triple("Screen.kt", "Text(color = ComposeColor(red = 1f, green = 0f, blue = 0f))", "color"), - Triple("WolfskinTokens.kt", "val tiny = TextStyle(fontSize = 11.5.sp)", "font-floor"), - Triple("Screen.kt", "Text(\"Recs Movies\")", "wording"), - Triple("Screen.kt", "Text(\"DGiC\")", "wording"), - Triple("Screen.kt", "Text(\"Justin Shows\")", "wording"), - Triple("Screen.kt", "Text(\"Next page\")", "wording"), - Triple("Screen.kt", "Text(\"Previous page\")", "wording"), - Triple("Screen.kt", "Text(\"Page 2\")", "wording"), - ) - cases.forEach { (name, source, rule) -> - assertTrue("$rule accepted $source", audit(name, source).any { it.endsWith(":$rule") }) - } - assertTrue(audit("WolfskinTokens.kt", "val body = TextStyle(fontSize = 12.sp); val fill = Color(0xFF123456)").isEmpty()) - assertTrue(audit("Screen.kt", "import androidx.compose.ui.unit.dp\nText(\"This title can’t be read\", style = WolfskinTokens.Type.body)").isEmpty()) - } - - private fun audit(name: String, source: String): List { - val generated = name == "WolfskinTokens.kt" - return source.lineSequence().mapIndexedNotNull { index, line -> - val code = line.trimStart() - if (code.startsWith("import ") || code.startsWith("//") || code.startsWith("*") || code.startsWith("/*")) return@mapIndexedNotNull null - val rules = buildList { - if (!generated && units.containsMatchIn(line)) add("unit") - if (!generated && colors.containsMatchIn(line)) add("color") - if (fonts.findAll(line).any { it.groupValues[1].toDouble() < 12 }) add("font-floor") - if (strings.findAll(line).any { forbidden.containsMatchIn(it.value) }) add("wording") - } - rules.map { "${index + 1}:$it" } - }.flatten().toList() - } - - companion object { - private val units = Regex("\\.(?:dp|sp)\\b") - private val colors = Regex("\\b(?:Compose)?Color\\s*\\(\\s*(?:0[xX]|[0-9.]|(?:red|green|blue|alpha|color)\\s*=)") - private val fonts = Regex("\\bfontSize\\s*=\\s*([0-9]+(?:\\.[0-9]+)?)[fF]?\\.sp\\b") - private val strings = Regex("\"(?:\\\\.|[^\"\\\\])*\"") - private val forbidden = Regex("Recs (?:Movies|Shows)|DGiC|(?:Justin|Mindel|Shared) (?:Movies|Shows)|(?:Next|Previous) page|Page (?:[0-9]|\\$)|\\bpagination\\b", RegexOption.IGNORE_CASE) - } -} From c78a8dfa8dc8b9b6ce89673cee8f0116e3c78a78 Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 19:12:21 +0100 Subject: [PATCH 15/18] Cache each Robolectric SDK without version conflicts --- docker/README.md | 4 ++++ wolfskin-design/build.gradle.kts | 20 +++++++++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/docker/README.md b/docker/README.md index 83b607ee..dde55ef2 100644 --- a/docker/README.md +++ b/docker/README.md @@ -11,6 +11,10 @@ make test # app default/debug suite plus wolfskin-design JVM/capture suite make apk-debug # default debug, no secrets; MPV stub and no extra codec decoders ``` +Offline JVM tests use instrumented Android 9, 11 and 14 SDK jars. Cache preparation +resolves each SDK independently; putting all three versions in one Gradle +configuration selects only the newest and prevents older-SDK tests from starting. + APKs remain under `app/build/outputs/apk/default/{release,debug,optimized}/`. Debug builds are not playback-complete and must not be distributed as releases. Upstream's `.github/workflows` and dependency version catalog are unchanged; release builds diff --git a/wolfskin-design/build.gradle.kts b/wolfskin-design/build.gradle.kts index d1275edb..74caf761 100644 --- a/wolfskin-design/build.gradle.kts +++ b/wolfskin-design/build.gradle.kts @@ -19,13 +19,18 @@ android { } kotlin.compilerOptions.jvmTarget = JvmTarget.JVM_11 -val robolectricSdk by configurations.creating { - isCanBeResolved = true - isCanBeConsumed = false - isTransitive = false -} val cacheRobolectricSdk by tasks.registering(Copy::class) { - from(robolectricSdk) + val versions = listOf( + "9-robolectric-4913185-2-i7", + "11-robolectric-6757853-i7", + "14-robolectric-10818077-i7", + ) + // One configuration would evict the older SDKs through version conflict resolution. + from(versions.map { version -> + project.configurations.detachedConfiguration( + project.dependencies.create("org.robolectric:android-all-instrumented:$version"), + ).apply { isTransitive = false } + }) into(layout.buildDirectory.dir("robolectric-sdk")) } @@ -50,9 +55,6 @@ tasks.withType().configureEach { } dependencies { - robolectricSdk("org.robolectric:android-all-instrumented:9-robolectric-4913185-2-i7") - robolectricSdk("org.robolectric:android-all-instrumented:11-robolectric-6757853-i7") - robolectricSdk("org.robolectric:android-all-instrumented:14-robolectric-10818077-i7") implementation(platform(libs.androidx.compose.bom)) implementation(libs.androidx.compose.ui) implementation(libs.androidx.tv.material) From 8be769b67c176dd07f8809deb03c8f74a79742bf Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 19:48:04 +0100 Subject: [PATCH 16/18] Launch trailers with the vnd.youtube authority form SmartTube can parse --- .../org/justinvisser/wolfskin/tv/TitleTrailerTest.kt | 10 ++++++---- .../java/org/justinvisser/wolfskin/tv/TitleTrailer.kt | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/TitleTrailerTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleTrailerTest.kt index afa137ee..b2b6b3e6 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/TitleTrailerTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleTrailerTest.kt @@ -19,21 +19,23 @@ import org.robolectric.annotation.Config @Config(sdk = [34], application = Application::class) class TitleTrailerTest { private val context = ApplicationProvider.getApplicationContext() - private val url = "https://www.youtube.com/watch?v=abcdefghijk" + private val url = "https://www.youtube.com/watch?v=ab_-defghij" @Test fun missingYoutubeHandlerStaysOnTheTitleEvenWhenABrowserExists() { - register(Intent(Intent.ACTION_VIEW, Uri.parse(url)), "test.browser") + register(Intent(Intent.ACTION_VIEW, Uri.parse("https://www.youtube.com/watch?v=ab_-defghij")), "test.browser") assertFalse(TitleTrailer(context).open(url)) assertNull(shadowOf(context as Application).nextStartedActivity) } @Test fun installedYoutubeHandlerReceivesAnExplicitPackageAndNoBrowserUrl() { - register(Intent(Intent.ACTION_VIEW, Uri.parse("vnd.youtube:abcdefghijk")), "test.youtube") + register(Intent(Intent.ACTION_VIEW, Uri.parse("vnd.youtube://ab_-defghij")), "test.youtube") assertTrue(TitleTrailer(context).open(url)) val launched = shadowOf(context as Application).nextStartedActivity + assertEquals(Intent.ACTION_VIEW, launched.action) assertEquals("test.youtube", launched.`package`) assertEquals("vnd.youtube", launched.data?.scheme) - assertEquals("abcdefghijk", launched.data?.schemeSpecificPart) + // SmartTube (IntentExtractor.extractVideoId) takes the id from Uri.getHost() for this scheme; the opaque `vnd.youtube:ID` form yields null there. + assertEquals("ab_-defghij", launched.data?.host) } @Test fun nonYoutubeTrailerNeverOpensAGeneralViewHandler() { diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/TitleTrailer.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/TitleTrailer.kt index 0dce1f9f..7cf330d3 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/TitleTrailer.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/TitleTrailer.kt @@ -17,7 +17,8 @@ class TitleTrailer(private val context: Context) { ?: source.pathSegments.takeIf { it.firstOrNull() in setOf("shorts", "embed") }?.getOrNull(1) else -> null } ?: return false - val intent = Intent(Intent.ACTION_VIEW, Uri.parse("vnd.youtube:$video")).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + // Authority form: SmartTube's IntentExtractor reads the id from Uri.getHost(), which is null for the opaque `vnd.youtube:ID`. + val intent = Intent(Intent.ACTION_VIEW, Uri.parse("vnd.youtube://$video")).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) val handler = context.packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY) .firstOrNull { it.activityInfo.exported } ?: return false intent.setPackage(handler.activityInfo.packageName) From 383802611cda836a9cac017f65acf609c73bf169 Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 20:19:02 +0100 Subject: [PATCH 17/18] Enforce monotonic household releases and staged APK integrity --- .../update/HouseholdUpdateControllerTest.kt | 14 ++- .../tv/update/UpdateSessionStreamTest.kt | 34 ++++++ .../tv/update/AndroidUpdatePlatform.kt | 31 ++++- .../tv/update/HouseholdUpdateController.kt | 17 +-- .../wolfskin/tv/update/VerifiedUpdateStore.kt | 2 +- docker/README.md | 40 +++++-- docker/test_tv_publish.py | 109 ++++++++++++++++-- docker/test_tv_release.py | 59 ++++++++++ docker/tv_publish.py | 51 +++++++- docker/tv_release.py | 39 +++++-- 10 files changed, 351 insertions(+), 45 deletions(-) create mode 100644 app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdateSessionStreamTest.kt diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateControllerTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateControllerTest.kt index 0c2ebae2..1a7929f1 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateControllerTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateControllerTest.kt @@ -38,6 +38,7 @@ class HouseholdUpdateControllerTest { private var truncated = false private var chunked = false private var unsupported = false + private var manifestSigner = UpdateChannel.SIGNER private var redirect = false private var redirectTarget: String? = null private val requests = mutableListOf>>() @@ -54,7 +55,7 @@ class HouseholdUpdateControllerTest { override fun inspect(file: File) = archive override fun hasInstallPermission() = permission override fun openPermissionSettings() = settingsAvailable - override fun install(file: File, outcome: (InstallOutcome) -> Unit) { installs++; outcome(this.outcome) } + override fun install(file: File, asset: UpdateAsset, outcome: (InstallOutcome) -> Unit) { installs++; outcome(this.outcome) } } private val preferences = object : UpdatePreferences { override val autoCheck = MutableStateFlow(true) @@ -104,7 +105,7 @@ class HouseholdUpdateControllerTest { @After fun stop() { server.stop(0) } private fun manifest() = UpdateManifest(1, UpdateChannel.PACKAGE, "1.1.1", code, - "2026-11-07T12:00:00Z", "a".repeat(40), "pwolfskin-opt-v1.1.1", UpdateChannel.SIGNER, + "2026-11-07T12:00:00Z", "a".repeat(40), "pwolfskin-opt-v1.1.1", manifestSigner, listOf(UpdateAsset(if (unsupported) "x86_64" else "armeabi-v7a", if (unsupported) "Wolfskin-x86_64.apk" else "Wolfskin-armeabi-v7a.apk", apk.size.toLong(), if (badHash) "0".repeat(64) else MessageDigest.getInstance("SHA-256").digest(apk).joinToString("") { "%02x".format(it) }, 23))) @@ -163,6 +164,15 @@ class HouseholdUpdateControllerTest { assertEquals(UpdateFailure.UnsupportedAbi, (unsupported.state.value as UpdateUiState.Failed).kind) } + @Test fun manifestSignerDifferentFromInstallationFailsBeforeDownload() = runTest { + manifestSigner = "b".repeat(64) + val controller = controller(this) + controller.check(true); advanceUntilIdle() + assertEquals(UpdateFailure.WrongSigner, (controller.state.value as UpdateUiState.Failed).kind) + assertFalse(File(directory, "verified.apk").exists()) + assertEquals(0, platform.installs) + } + @Test fun checksumAndLengthFailuresNeverCommitReady() = runTest { for (badChecksum in listOf(true, false)) { badHash = badChecksum; truncated = !badChecksum diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdateSessionStreamTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdateSessionStreamTest.kt new file mode 100644 index 00000000..4f5f3159 --- /dev/null +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/update/UpdateSessionStreamTest.kt @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-only +package org.justinvisser.wolfskin.tv.update + +import java.io.ByteArrayOutputStream +import java.security.MessageDigest +import org.junit.Assert.assertEquals +import org.junit.Assert.fail +import org.junit.Test + +/** A replacement or incomplete stream must never reach the session commit boundary. */ +class UpdateSessionStreamTest { + private val original = ByteArray(128 * 1024) { (it % 251).toByte() } + private val asset = UpdateAsset("armeabi-v7a", "Wolfskin-armeabi-v7a.apk", original.size.toLong(), + MessageDigest.getInstance("SHA-256").digest(original).toHexString(), 23) + + @Test fun sameLengthReplacementAfterVerificationIsRejected() { + val replaced = original.copyOf().also { it[it.lastIndex] = (it.last() + 1).toByte() } + expectMismatch(replaced) + } + + @Test fun truncatedAndOversizedSessionStreamsAreRejected() { + expectMismatch(original.copyOf(original.size - 1)) + expectMismatch(original + byteArrayOf(1)) + } + + private fun expectMismatch(bytes: ByteArray) { + try { + bytes.inputStream().use { copyVerifiedUpdate(it, ByteArrayOutputStream(), asset) } + fail("Changed installation bytes were accepted") + } catch (error: UpdateException) { + assertEquals(UpdateFailure.ChecksumMismatch, error.kind) + } + } +} diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/AndroidUpdatePlatform.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/AndroidUpdatePlatform.kt index 504ef7ba..aa30e022 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/AndroidUpdatePlatform.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/AndroidUpdatePlatform.kt @@ -12,6 +12,8 @@ import android.os.Build import android.provider.Settings import dagger.hilt.android.qualifiers.ApplicationContext import java.io.File +import java.io.InputStream +import java.io.OutputStream import java.security.MessageDigest import javax.inject.Inject import javax.inject.Singleton @@ -47,7 +49,7 @@ class AndroidUpdatePlatform @Inject constructor(@param:ApplicationContext privat return try { context.startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); true } catch (_: RuntimeException) { false } } - override fun install(file: File, outcome: (InstallOutcome) -> Unit) { + override fun install(file: File, asset: UpdateAsset, outcome: (InstallOutcome) -> Unit) { if (context.noBackupFilesDir.usableSpace < file.length()) { outcome(InstallOutcome.InsufficientStorage) return @@ -55,7 +57,7 @@ class AndroidUpdatePlatform @Inject constructor(@param:ApplicationContext privat val installer = manager.packageInstaller val parameters = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL).apply { setAppPackageName(context.packageName) - setSize(file.length()) + setSize(asset.bytes) if (Build.VERSION.SDK_INT >= 31) setRequireUserAction(PackageInstaller.SessionParams.USER_ACTION_REQUIRED) } var sessionId: Int? = null @@ -63,8 +65,8 @@ class AndroidUpdatePlatform @Inject constructor(@param:ApplicationContext privat sessionId = installer.createSession(parameters) check(sessions.edit().putInt("id", sessionId).commit()) installer.openSession(sessionId).use { session -> - session.openWrite("Wolfskin.apk", 0, file.length()).use { output -> - file.inputStream().use { it.copyTo(output) } + session.openWrite("Wolfskin.apk", 0, asset.bytes).use { output -> + file.inputStream().use { copyVerifiedUpdate(it, output, asset) } session.fsync(output) } val intent = Intent(context, UpdateInstallReceiver::class.java).setAction("${context.packageName}.UPDATE_RESULT") @@ -72,8 +74,9 @@ class AndroidUpdatePlatform @Inject constructor(@param:ApplicationContext privat val result = PendingIntent.getBroadcast(context, sessionId, intent, flags) session.commit(result.intentSender) } - } catch (_: Exception) { + } catch (error: Exception) { sessionId?.let { runCatching { installer.abandonSession(it) } } + if (error is UpdateException) throw error outcome(InstallOutcome.Unavailable) } } @@ -88,3 +91,21 @@ class AndroidUpdatePlatform @Inject constructor(@param:ApplicationContext privat } catch (_: RuntimeException) { false } } } + +/** Check the bytes actually staged into Android, not a prior read of the private path. */ +internal fun copyVerifiedUpdate(input: InputStream, output: OutputStream, asset: UpdateAsset) { + val digest = MessageDigest.getInstance("SHA-256") + val buffer = ByteArray(64 * 1024) + var count = 0L + while (true) { + val length = input.read(buffer) + if (length < 0) break + count += length + if (count > asset.bytes) throw UpdateException(UpdateFailure.ChecksumMismatch, "APK changed while staging installation") + digest.update(buffer, 0, length) + output.write(buffer, 0, length) + } + if (count != asset.bytes || digest.digest().toHexString() != asset.sha256) { + throw UpdateException(UpdateFailure.ChecksumMismatch, "APK changed while staging installation") + } +} diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateController.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateController.kt index 92975631..9955f1cb 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateController.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateController.kt @@ -143,17 +143,20 @@ class HouseholdUpdateController( if (state.value == UpdateUiState.HandingOff) return@runOperation val manifest = ready ?: return@runOperation retryOperation = { install() } - try { store.verify(store.apk, manifest, manifest.selectAsset(abis, sdk)) } catch (error: Exception) { + val asset = manifest.selectAsset(abis, sdk) + try { + store.verify(store.apk, manifest, asset) + if (!platform.hasInstallPermission()) { + mutableState.value = if (platform.openPermissionSettings()) UpdateUiState.PermissionNeeded else UpdateUiState.NoInstaller + return@runOperation + } + mutableState.value = UpdateUiState.HandingOff + platform.install(store.apk, asset, ::handleInstallOutcome) + } catch (error: Exception) { store.clear(); ready = null retryOperation = { if (candidate != null) download() else check(true) } throw error } - if (!platform.hasInstallPermission()) { - mutableState.value = if (platform.openPermissionSettings()) UpdateUiState.PermissionNeeded else UpdateUiState.NoInstaller - return@runOperation - } - mutableState.value = UpdateUiState.HandingOff - platform.install(store.apk, ::handleInstallOutcome) } fun handleInstallOutcome(outcome: InstallOutcome) { diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/VerifiedUpdateStore.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/VerifiedUpdateStore.kt index 5018865b..d5f406b4 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/VerifiedUpdateStore.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/VerifiedUpdateStore.kt @@ -13,7 +13,7 @@ interface UpdatePlatform { fun inspect(file: File): ApkIdentity? fun hasInstallPermission(): Boolean fun openPermissionSettings(): Boolean - fun install(file: File, outcome: (InstallOutcome) -> Unit) + fun install(file: File, asset: UpdateAsset, outcome: (InstallOutcome) -> Unit) } /** Installer results do not imply the running process has been replaced. */ diff --git a/docker/README.md b/docker/README.md index dde55ef2..e35d146e 100644 --- a/docker/README.md +++ b/docker/README.md @@ -72,11 +72,13 @@ make tv-release VERSION=1.1.1 VERSION_CODE=100001 \ Required: a clean committed source checkout, the existing persistent key, native package credentials through the existing secret mount, no local AAR overrides, -and an explicit code above every entry in `docker/tv-version-codes`. Known Opt -code 65 seeds that ledger; old production code 28 and Wholphin code 62 belong -to different packages. Proposed first household code 100001 exceeds all three. -No household code derives from tag counts. Direct optimized Gradle tasks also -require `-PtvVersionCode`; the packaging command additionally enforces the ledger. +and an explicit code above the committed ledgers at HEAD and freshly fetched +`origin/main`, plus every local consumed-code reservation. Fetch failure refuses +the build, including a dry-run. Known Opt code 65 seeds the ledger; old production +code 28 and Wholphin code 62 belong to different packages. Proposed first household +code 100001 exceeds all three. No household code derives from tag counts. +Only `make tv-release` produces an installable household release; direct optimized +Gradle builds bypass reservation and must never be installed on the household box. The builder inspects final signed APKs with aapt2/apksigner and checks package, version/code, signer, non-debuggable flag, minimum SDK, native ABI inventory, @@ -91,8 +93,13 @@ Manifest schema 1 contains `packageId`, `versionName`, `versionCode`, `signerSha256`, and `assets[]` with `abi`, `name`, `bytes`, `sha256`, `minSdk`. All ABI outputs share one code/signer/identity. The local source tag is `pwolfskin-opt-v`; the distribution tag is `wolfskin-opt-v`. +Before building, the code is consumed in the local Git ref +`refs/wolfskin-tv/version-codes/`. This survives discarding a working-tree +ledger append or checking out an older source commit. A failed real build also +consumes its code: use a higher code rather than deleting the reservation. After successful packaging the builder appends the code to the tracked ledger. -Commit that reservation and explicitly push the source tag before distribution. +Commit that reservation and explicitly push the source tag before distribution; +new producer checkouts obtain the committed floor by fetching `origin/main`. An existing output directory is refused to preserve previous evidence. Keep `private/` private: build/dependency logs, R8 mapping/effective configuration, @@ -120,6 +127,12 @@ and reverified. Upload/verification failures remain draft. Promotion requires the explicit flag; then anonymous latest/asset hash checks must pass. A failed post-promotion check attempts withdrawal to draft and reports failure, not success. Cross-origin credential forwarding and non-HTTPS URLs are refused. + +Before creating/resuming a draft and immediately before promotion, the publisher +anonymously reads latest and its manifest. The bundle code must be strictly newer. +Only a latest 404 followed by a successful empty release list permits a first +release; other errors fail closed. A channel advance during upload leaves the +verified upload draft rather than publishing an equal or lower code. `--test-server` permits only a loopback HTTP fake Forgejo; production defaults cannot be redirected to a different repository by a CLI repository argument. Dry-run never fetches a credential or makes publication requests. @@ -151,6 +164,8 @@ the installed Android signer is the installation boundary. EOF never starts installation. Install requires a separate OK, per-package unknown-app permission and a confirmation-required PackageInstaller session. +The bytes streamed into that session are checked again against the manifest length +and hash; any mismatch abandons the session before commit and discards invalid Ready. Returning from permission settings requires another explicit Install press. Denial, cancellation and missing system handlers retain the verified download. No broad FileProvider, public Downloads write, silent install or automatic @@ -228,13 +243,15 @@ monotonic versionCode; source commit identity is recorded separately. `make apk` remains the old `org.justinvisser.wolfskin.tv` production assembly and release signer. It must never publish to the household channel. -Build all four default-flavor outputs in one invocation through the container -wrapper, without a release keystore. On a host whose Gradle cache already holds -the pinned native extensions and their metadata: +For build-only diagnostics, build all four outputs through the container wrapper +with a deliberately non-release code. **Direct optimized builds must never be +installed on the household box or published.** Use `make tv-release` for every +household installation. On a host whose Gradle cache already holds the pinned +native extensions and their metadata: ```sh bash docker/gradle.sh optimized --offline \ - -PtvVersion=1.1.1 -PtvVersionCode=100001 \ + -PtvVersion=1.1.1 -PtvVersionCode=1 \ -PWholphinExtensionsUsername=JustinZeus \ -PWholphinExtensionsPassword=unused \ :app:assembleDefaultOptimized @@ -247,7 +264,8 @@ through the existing `ORG_GRADLE_PROJECT_WholphinExtensionsUsername` and or securely seeded cached artifacts. No release signing inputs are needed. Without native extension configuration, the existing dependency selection uses the MPV stub and omits ffmpeg/AV1, just like `make apk-debug`; that is not a -playback-complete comparison. Inspect native libraries before installing. +playback-complete comparison. Inspect native libraries for diagnostic evidence; +do not install these direct-build APKs on the household box. Outputs are in `app/build/outputs/apk/default/optimized/`: universal, arm64-v8a, armeabi-v7a and x86_64. Keep diff --git a/docker/test_tv_publish.py b/docker/test_tv_publish.py index 2c7673d8..86ccce49 100644 --- a/docker/test_tv_publish.py +++ b/docker/test_tv_publish.py @@ -30,6 +30,12 @@ class FakeForge: self.corrupt_draft = False self.corrupt_public = False self.redirect_url: str | None = None + self.published_code: int | None = None + self.channel_manifest: dict[str, Any] = {} + self.latest_status = 200 + self.release_list: list[dict[str, Any]] = [] + self.latest_reads = 0 + self.advance_before_promote: int | None = None fixture = self class Handler(BaseHTTPRequestHandler): @@ -104,10 +110,39 @@ class FakeForge: else fixture.corrupt_public ) self.respond(data + b"corrupt" if corrupt else data) - elif self.path.endswith("/latest") and fixture.release.get( - "draft", True - ): - self.respond({}, 404) + elif self.path == "/channel/wolfskin-update.json": + self.respond( + fixture.channel_manifest + | {"versionCode": fixture.published_code} + ) + elif self.path.endswith("/latest"): + fixture.latest_reads += 1 + if ( + fixture.latest_reads == 2 + and fixture.advance_before_promote is not None + ): + fixture.published_code = fixture.advance_before_promote + if fixture.latest_status != 200: + self.respond({}, fixture.latest_status) + elif fixture.release and not fixture.release["draft"]: + self.respond(fixture.release) + elif fixture.published_code is not None: + self.respond( + { + "id": 9, + "assets": [ + { + "name": "wolfskin-update.json", + "browser_download_url": fixture.base + + "/channel/wolfskin-update.json", + } + ], + } + ) + else: + self.respond({}, 404) + elif urllib.parse.urlsplit(self.path).path.endswith("/releases"): + self.respond(fixture.release_list) else: self.respond(fixture.release) @@ -157,6 +192,7 @@ class PublishTest(unittest.TestCase): "signerSha256": SIGNER, "assets": assets, } + self.forge.channel_manifest = manifest (self.directory / "wolfskin-update.json").write_text(json.dumps(manifest)) (self.directory / "RELEASE-NOTES.md").write_text("Fixture release notes") self.checksums() @@ -208,16 +244,18 @@ class PublishTest(unittest.TestCase): self.assertEqual(0, result.returncode, result.stderr) self.assertTrue(self.forge.release["draft"]) self.assertEqual(REQUIRED, set(self.forge.assets)) - self.assertTrue(all(auth for _, auth in self.forge.events)) + self.assertTrue( + all( + not auth + for path, auth in self.forge.events + if "/latest" in path or "?limit=" in path + ) + ) result = self.cli("--draft-id", "17", "--promote") self.assertEqual(0, result.returncode, result.stderr) self.assertFalse(self.forge.release["draft"]) for name, data in self.forge.assets.items(): self.assertEqual((self.directory / name).read_bytes(), data) - anonymous = [ - event for event, authenticated in self.forge.events if not authenticated - ] - self.assertEqual(8, len(anonymous)) def test_corrupt_uploaded_bytes_remain_draft(self) -> None: self.forge.corrupt_draft = True @@ -266,6 +304,59 @@ class PublishTest(unittest.TestCase): self.assertEqual(0, result.returncode, result.stderr) self.assertFalse(trace.exists()) + def test_equal_and_lower_bundle_codes_never_create_a_draft(self) -> None: + for published_code in (100001, 100002): + with self.subTest(published_code=published_code): + self.forge.published_code = published_code + result = self.cli("--promote") + self.assertNotEqual(0, result.returncode) + self.assertEqual({}, self.forge.release) + self.assertTrue(all(not auth for _, auth in self.forge.events)) + + def test_newer_bundle_reads_live_manifest_anonymously(self) -> None: + self.forge.published_code = 100000 + result = self.cli() + self.assertEqual(0, result.returncode, result.stderr) + self.assertTrue(self.forge.release["draft"]) + live_reads = [ + auth + for path, auth in self.forge.events + if path.endswith("/latest") or path.startswith("GET /channel/") + ] + self.assertTrue(live_reads) + self.assertFalse(any(live_reads)) + + def test_channel_advance_during_upload_prevents_promotion(self) -> None: + self.forge.advance_before_promote = 100001 + result = self.cli("--promote") + self.assertNotEqual(0, result.returncode) + self.assertTrue(self.forge.release["draft"]) + self.assertFalse(any(path == "PATCH" for path, _ in self.forge.events)) + + def test_empty_channel_404_permits_first_draft(self) -> None: + result = self.cli() + self.assertEqual(0, result.returncode, result.stderr) + self.assertTrue(self.forge.release["draft"]) + self.assertIn( + ( + "GET /api/v1/repos/justinzeus/wolfskin-tv-updates/releases?limit=1", + False, + ), + self.forge.events, + ) + + def test_missing_latest_with_nonempty_channel_is_not_first_release(self) -> None: + self.forge.release_list = [{"id": 9}] + result = self.cli() + self.assertNotEqual(0, result.returncode) + self.assertEqual({}, self.forge.release) + + def test_refused_live_channel_never_creates_draft(self) -> None: + self.forge.latest_status = 403 + result = self.cli() + self.assertNotEqual(0, result.returncode) + self.assertEqual({}, self.forge.release) + def test_authenticated_redirect_never_reaches_another_origin(self) -> None: other = FakeForge() self.addCleanup(other.close) diff --git a/docker/test_tv_release.py b/docker/test_tv_release.py index 31dbef1f..4a5d679a 100644 --- a/docker/test_tv_release.py +++ b/docker/test_tv_release.py @@ -34,6 +34,12 @@ class ReleaseInputTest(unittest.TestCase): "-m", "Record used code", ) + self.remote = Path(self.temporary.name) / "origin.git" + subprocess.run( + ["git", "init", "--bare", "--quiet", str(self.remote)], check=True + ) + self.git("remote", "add", "origin", str(self.remote)) + self.git("push", "--quiet", "origin", "HEAD:main") self.previous_root = tv_release.ROOT tv_release.ROOT = self.root self.addCleanup(setattr, tv_release, "ROOT", self.previous_root) @@ -94,6 +100,59 @@ class ReleaseInputTest(unittest.TestCase): self.assertEqual( "65 installed-opt\n", (self.root / "docker/tv-version-codes").read_text() ) + self.assertEqual( + "", self.git("for-each-ref", "refs/wolfskin-tv/version-codes/") + ) + + def test_stale_branch_uses_fetched_main_ledger(self) -> None: + stale = self.git("rev-parse", "HEAD") + (self.root / "docker/tv-version-codes").write_text( + "65 installed-opt\n100001 released\n" + ) + self.git("add", "docker/tv-version-codes") + self.git( + "-c", + "user.name=Fixture", + "-c", + "user.email=fixture@example.invalid", + "commit", + "--quiet", + "-m", + "Reserve published code", + ) + self.git("push", "--quiet", "origin", "HEAD:main") + self.git("checkout", "--quiet", "--detach", stale) + with self.assertRaises(ValueError): + tv_release.validate_inputs("1.1.2", 100001) + self.assertEqual(stale, tv_release.validate_inputs("1.1.2", 100002)) + + def test_discarding_ledger_append_cannot_reuse_reserved_code(self) -> None: + commit = self.git("rev-parse", "HEAD") + tv_release.reserve_code(100001, commit) + with (self.root / "docker/tv-version-codes").open("a") as ledger: + ledger.write("100001 1.1.1 consumed\n") + self.git("restore", "docker/tv-version-codes") + with self.assertRaises(ValueError): + tv_release.validate_inputs("1.1.2", 100001) + self.assertEqual(commit, tv_release.validate_inputs("1.1.2", 100002)) + + def test_head_reservation_wins_over_older_main(self) -> None: + (self.root / "docker/tv-version-codes").write_text( + "65 installed-opt\n100002 released\n" + ) + self.git("add", "docker/tv-version-codes") + self.git( + "-c", + "user.name=Fixture", + "-c", + "user.email=fixture@example.invalid", + "commit", + "--quiet", + "-m", + "Reserve newer branch code", + ) + with self.assertRaises(ValueError): + tv_release.validate_inputs("1.1.3", 100002) if __name__ == "__main__": diff --git a/docker/tv_publish.py b/docker/tv_publish.py index 99f4d040..7a1a131f 100755 --- a/docker/tv_publish.py +++ b/docker/tv_publish.py @@ -30,6 +30,14 @@ REQUIRED = { } +class ForgeHttpError(RuntimeError): + """Retain HTTP status without exposing response bodies or authorization.""" + + def __init__(self, method: str, status: int) -> None: + super().__init__(f"Forgejo {method} failed: HTTP {status}") + self.status = status + + class NoRedirect(urllib.request.HTTPRedirectHandler): """Validate every redirect before forwarding distribution-tool credentials.""" @@ -98,9 +106,9 @@ class Forge: return self.opener.open(request, timeout=60) except urllib.error.HTTPError as error: if method != "GET" or error.code not in (301, 302, 303, 307, 308): - raise RuntimeError( - f"Forgejo {method} failed: HTTP {error.code}" - ) from None + status = error.code + error.close() + raise ForgeHttpError(method, status) from None location = error.headers.get("Location") error.close() if not location: @@ -159,6 +167,41 @@ class Forge: if actual != expected: raise ValueError("Uploaded artifact checksum mismatch") + def require_newer_code(self, code: int) -> None: + """Read the public channel anonymously and fail closed on an uncertain floor.""" + try: + release = self.json("GET", "/releases/latest", authenticated=False) + except ForgeHttpError as error: + if error.status != 404: + raise + releases = self.json("GET", "/releases?limit=1", authenticated=False) + if releases == []: + return + raise ValueError("Latest is missing but the channel is not empty") from None + assets = [ + asset + for asset in release["assets"] + if asset["name"] == "wolfskin-update.json" + ] + if len(assets) != 1: + raise ValueError("Latest release must have exactly one update manifest") + with self.request( + "GET", assets[0]["browser_download_url"], authenticated=False + ) as response: + manifest = json.load(response) + latest_code = manifest["versionCode"] + if ( + manifest["schemaVersion"] != 1 + or manifest["packageId"] != "org.justinvisser.wolfskin.tv.opt" + or type(latest_code) is not int + or not 1 <= latest_code <= 2100000000 + ): + raise ValueError("Invalid live household version identity") + if code <= latest_code: + raise ValueError( + f"Bundle versionCode must exceed live channel code {latest_code}" + ) + def credential(server: str) -> str: """Read git's existing credential helper without secrets in argv, stdout or disk.""" @@ -280,6 +323,7 @@ def publish( f"Dry run: draft {REPOSITORY} {tag}; upload and verify {len(hashes)} assets; promote={promote}; no requests or credentials" ) return + Forge(server, "", test_server).require_newer_code(manifest["versionCode"]) forge = Forge(server, credential(server), test_server) if draft_id is None: release = forge.json( @@ -313,6 +357,7 @@ def publish( "Draft upload verified. Publication requires owner approval and explicit --promote." ) return + forge.require_newer_code(manifest["versionCode"]) try: forge.json("PATCH", f"/releases/{release_id}", {"draft": False}) latest = forge.json("GET", "/releases/latest", authenticated=False) diff --git a/docker/tv_release.py b/docker/tv_release.py index 8a147ce3..5ce4b890 100755 --- a/docker/tv_release.py +++ b/docker/tv_release.py @@ -37,16 +37,40 @@ def validate_inputs(version: str, code: int) -> str: raise ValueError( "Release source must be clean, including the version-code ledger" ) - used = [ - int(line.split()[0]) - for line in (ROOT / "docker/tv-version-codes").read_text().splitlines() - if line and not line.startswith("#") - ] + commit = run("git", "rev-parse", "HEAD") + run( + "git", + "fetch", + "--no-tags", + "origin", + "refs/heads/main:refs/remotes/origin/main", + ) + used = [] + for reference in (commit, "refs/remotes/origin/main"): + if run("git", "ls-tree", "--name-only", reference, "docker/tv-version-codes"): + ledger = run("git", "show", f"{reference}:docker/tv-version-codes") + used.extend( + int(line.split()[0]) + for line in ledger.splitlines() + if line and not line.startswith("#") + ) + reservations = run( + "git", + "for-each-ref", + "--format=%(refname:strip=3)", + "refs/wolfskin-tv/version-codes/", + ) + used.extend(int(value) for value in reservations.splitlines()) if code <= max(used): - raise ValueError(f"VERSION_CODE must exceed ledger maximum {max(used)}") + raise ValueError(f"VERSION_CODE must exceed reserved maximum {max(used)}") if list((ROOT / "app/libs").glob("*.aar")): raise ValueError("Local AAR overrides are forbidden for household releases") - return run("git", "rev-parse", "HEAD") + return commit + + +def reserve_code(code: int, commit: str) -> None: + """Keep a consumed code reserved even if its working-tree ledger append is discarded.""" + run("git", "update-ref", f"refs/wolfskin-tv/version-codes/{code}", commit, "") def inspect_apk(path: Path, version: str, code: int, abi: str, proof: Path) -> int: @@ -130,6 +154,7 @@ def release(version: str, code: int, output: Path, dry_run: bool) -> None: existing = run("git", "tag", "--list", tag) if existing and run("git", "rev-parse", f"{tag}^{{commit}}") != commit: raise ValueError("Source tag already identifies another commit") + reserve_code(code, commit) output.mkdir(parents=True) private = output / "private" private.mkdir(mode=0o700) From 51799669e7a47cdb9dc11247884a0ff32d2ffbcb Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 20:29:58 +0100 Subject: [PATCH 18/18] Expose persistent update metadata and safe UI dismissals --- .../update/HouseholdUpdateControllerTest.kt | 92 ++++++++++++++++++- .../tv/update/FakeUpdateController.kt | 8 +- .../tv/update/HouseholdUpdateController.kt | 73 ++++++++++----- .../wolfskin/tv/update/UpdateController.kt | 7 +- .../wolfskin/tv/update/VerifiedUpdateStore.kt | 26 ++++-- docker/README.md | 10 ++ 6 files changed, 181 insertions(+), 35 deletions(-) diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateControllerTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateControllerTest.kt index 1a7929f1..fc9c246b 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateControllerTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateControllerTest.kt @@ -50,11 +50,13 @@ class HouseholdUpdateControllerTest { var permission = true var settingsAvailable = true var installs = 0 + var settingsOpens = 0 + var inspectAction: (() -> Unit)? = null var outcome = InstallOutcome.Cancelled override fun installed() = installed - override fun inspect(file: File) = archive + override fun inspect(file: File): ApkIdentity { inspectAction?.invoke(); return archive } override fun hasInstallPermission() = permission - override fun openPermissionSettings() = settingsAvailable + override fun openPermissionSettings(): Boolean { settingsOpens++; return settingsAvailable } override fun install(file: File, asset: UpdateAsset, outcome: (InstallOutcome) -> Unit) { installs++; outcome(this.outcome) } } private val preferences = object : UpdatePreferences { @@ -116,17 +118,32 @@ class HouseholdUpdateControllerTest { val controller = controller(this) controller.check(true); advanceUntilIdle() assertTrue(controller.state.value is UpdateUiState.Available) + val metadata = controller.release.value + assertEquals(controller.state.value, metadata) controller.download(); advanceUntilIdle() assertEquals(UpdateUiState.Ready("1.1.1"), controller.state.value) + assertEquals(metadata, controller.release.value) assertEquals(0, platform.installs) val restored = controller(this); advanceUntilIdle() assertEquals(UpdateUiState.Ready("1.1.1"), restored.state.value) + assertEquals(metadata, restored.release.value) restored.install(); advanceUntilIdle() assertEquals(UpdateUiState.InstallCancelled, restored.state.value) assertEquals(1, platform.installs) assertTrue(File(directory, "verified.apk").exists()) } + @Test fun existingManifestOnlyReadyRecordRemainsReadable() = runTest { + val old = controller(this); old.check(true); advanceUntilIdle(); old.download(); advanceUntilIdle() + val metadata = old.release.value!! + assertEquals(manifest(), UpdateManifest.parse(File(directory, "ready.json").readText())) + File(directory, "ready.json").writeText(UpdateManifest.encode(manifest())) + val recreated = controller(this); advanceUntilIdle() + assertEquals(UpdateUiState.Ready("1.1.1"), recreated.state.value) + assertEquals(metadata.copy(notes = ""), recreated.release.value) + assertEquals(0, platform.installs) + } + @Test fun equalCodeIsUpToDateAndOlderCodeIsNotASuccess() = runTest { code = 65 val equal = controller(this); equal.check(true); advanceUntilIdle() @@ -253,6 +270,53 @@ class HouseholdUpdateControllerTest { assertEquals(UpdateUiState.NoInstaller, controller.state.value) } + @Test fun permissionDismissalRetainsReadyAndInstallReopensSettings() = runTest { + val controller = controller(this); controller.check(true); advanceUntilIdle(); controller.download(); advanceUntilIdle() + val metadata = controller.release.value + platform.permission = false + controller.install(); advanceUntilIdle() + assertEquals(UpdateUiState.PermissionNeeded, controller.state.value) + controller.install(); advanceUntilIdle() + assertEquals(2, platform.settingsOpens) + controller.cancel(); advanceUntilIdle() + assertEquals(UpdateUiState.Ready("1.1.1"), controller.state.value) + assertEquals(metadata, controller.release.value) + assertArrayEquals(apk, File(directory, "verified.apk").readBytes()) + controller.install(); advanceUntilIdle() + assertEquals(UpdateUiState.PermissionNeeded, controller.state.value) + assertEquals(3, platform.settingsOpens) + assertEquals(0, platform.installs) + } + + @Test fun handoffDismissalKeepsReadyWithoutAllowingAnotherOwnedSession() = runTest { + val controller = controller(this); controller.check(true); advanceUntilIdle(); controller.download(); advanceUntilIdle() + platform.outcome = InstallOutcome.Pending + controller.install(); advanceUntilIdle() + controller.cancel(); advanceUntilIdle() + assertEquals(UpdateUiState.Ready("1.1.1"), controller.state.value) + controller.handleInstallOutcome(InstallOutcome.Pending); advanceUntilIdle() + assertEquals(UpdateUiState.Ready("1.1.1"), controller.state.value) + val before = requests.size + controller.install(); advanceUntilIdle() + controller.check(true); advanceUntilIdle() + controller.download(); advanceUntilIdle() + assertEquals(1, platform.installs) + assertEquals(before, requests.size) + assertArrayEquals(apk, File(directory, "verified.apk").readBytes()) + controller.handleInstallOutcome(InstallOutcome.Cancelled); advanceUntilIdle() + controller.install(); advanceUntilIdle() + assertEquals(2, platform.installs) + } + + @Test fun dismissalDuringInstallVerificationDoesNotDiscardVerifiedBytes() = runTest { + val controller = controller(this); controller.check(true); advanceUntilIdle(); controller.download(); advanceUntilIdle() + platform.inspectAction = { controller.cancel() } + controller.install(); advanceUntilIdle() + assertEquals(UpdateUiState.Ready("1.1.1"), controller.state.value) + assertArrayEquals(apk, File(directory, "verified.apk").readBytes()) + assertEquals(0, platform.installs) + } + @Test fun corruptPersistedBytesAndUnverifiedPartialsAreDiscarded() = runTest { val controller = controller(this); controller.check(true); advanceUntilIdle(); controller.download(); advanceUntilIdle() File(directory, "verified.apk").appendText("corrupt") @@ -273,6 +337,26 @@ class HouseholdUpdateControllerTest { assertEquals(UpdateUiState.Ready("1.1.1"), controller.state.value) } + @Test fun failuresIdentifyCheckDownloadAndInstallWithoutParsingMessages() = runTest { + val controller = controller(this) + releaseStatus = 403 + controller.check(true); advanceUntilIdle() + assertEquals(UpdateOperation.Check, (controller.state.value as UpdateUiState.Failed).operation) + releaseStatus = 200 + controller.retry(); advanceUntilIdle() + assetStatus = 403 + controller.download(); advanceUntilIdle() + assertEquals(UpdateOperation.Download, (controller.state.value as UpdateUiState.Failed).operation) + assetStatus = 200 + controller.retry(); advanceUntilIdle() + File(directory, "verified.apk").writeBytes(ByteArray(apk.size)) + controller.install(); advanceUntilIdle() + val failed = controller.state.value as UpdateUiState.Failed + assertEquals(UpdateOperation.Install, failed.operation) + assertEquals(UpdateFailure.ChecksumMismatch, failed.kind) + assertFalse(File(directory, "ready.json").exists()) + } + @Test fun interruptedWireDownloadDoesNotPersistReady() = runTest { truncated = true; wireTruncated = true val controller = controller(this); controller.check(true); advanceUntilIdle() @@ -299,6 +383,8 @@ class HouseholdUpdateControllerTest { controller.install(); advanceUntilIdle() assertEquals(65L, controller.installedVersion.value.versionCode) assertTrue(File(directory, "verified.apk").exists()) + controller.cancel(); advanceUntilIdle(); controller.install(); advanceUntilIdle() + assertEquals(1, platform.installs) platform.installed = platform.archive controller.onResume(); advanceUntilIdle() assertEquals(100001L, controller.installedVersion.value.versionCode) @@ -316,6 +402,8 @@ class HouseholdUpdateControllerTest { replaced.handleInstallOutcome(InstallOutcome.Cancelled); advanceUntilIdle() assertEquals(UpdateUiState.Idle, replaced.state.value) assertFalse(File(directory, "verified.apk").exists()) + replaced.check(true); advanceUntilIdle() + assertEquals(UpdateUiState.UpToDate, replaced.state.value) } @Test fun reentryCheckCannotReplacePendingConfirmationOrStartAnotherSession() = runTest { diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/FakeUpdateController.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/FakeUpdateController.kt index 3976489b..ebac04ed 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/FakeUpdateController.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/FakeUpdateController.kt @@ -9,16 +9,22 @@ class FakeUpdateController( initialState: UpdateUiState = UpdateUiState.Idle, initialAutoCheck: Boolean = true, initialVersion: InstalledVersion = InstalledVersion("1.1.1", 100001), + initialRelease: UpdateUiState.Available? = initialState as? UpdateUiState.Available, ) : UpdateController { private val mutableState = MutableStateFlow(initialState) private val mutableAutoCheck = MutableStateFlow(initialAutoCheck) private val mutableVersion = MutableStateFlow(initialVersion) + private val mutableRelease = MutableStateFlow(initialRelease) override val state = mutableState.asStateFlow() override val autoCheck = mutableAutoCheck.asStateFlow() override val installedVersion = mutableVersion.asStateFlow() + override val release = mutableRelease.asStateFlow() val actions = mutableListOf() - fun show(state: UpdateUiState) { mutableState.value = state } + fun show(state: UpdateUiState) { + if (state is UpdateUiState.Available) mutableRelease.value = state + mutableState.value = state + } fun showInstalled(version: InstalledVersion) { mutableVersion.value = version } override fun check(manual: Boolean) { actions += "check:$manual" } override fun download() { actions += "download" } diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateController.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateController.kt index 9955f1cb..091be7a9 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateController.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/HouseholdUpdateController.kt @@ -40,26 +40,32 @@ class HouseholdUpdateController( ) : UpdateController { private val mutableState = MutableStateFlow(UpdateUiState.Idle) private val mutableVersion = MutableStateFlow(platform.installed().version) + private val mutableRelease = MutableStateFlow(null) override val state = mutableState.asStateFlow() override val installedVersion = mutableVersion.asStateFlow() override val autoCheck = preferences.autoCheck + override val release = mutableRelease.asStateFlow() private var candidate: UpdateCandidate? = null private var ready: UpdateManifest? = null private var operation: Job? = null + @Volatile private var installerActive = false private var retryOperation: () -> Unit = { check(true) } private val restored = scope.async { - ready = store.restore(abis, sdk) - ready?.let { mutableState.value = UpdateUiState.Ready(it.versionName) } + store.restore(abis, sdk)?.let { + ready = it.manifest + mutableRelease.value = available(it.manifest, it.asset, it.notes) + mutableState.value = UpdateUiState.Ready(it.manifest.versionName) + } } @Synchronized - private fun runOperation(action: suspend () -> Unit): Unit { + private fun runOperation(operationKind: UpdateOperation, action: suspend () -> Unit): Unit { if (operation?.isActive == true) return operation = scope.launch { restored.await() try { action() } catch (error: CancellationException) { throw error } - catch (error: UpdateException) { mutableState.value = UpdateUiState.Failed(error.kind, error.message) } + catch (error: UpdateException) { mutableState.value = UpdateUiState.Failed(error.kind, error.message, operationKind) } catch (_: UnknownHostException) { mutableState.value = UpdateUiState.Offline } catch (_: ConnectException) { mutableState.value = UpdateUiState.Offline } catch (error: IOException) { @@ -67,16 +73,16 @@ class HouseholdUpdateController( val full = state.value is UpdateUiState.Downloading && release != null && store.directory.usableSpace < release.asset.bytes mutableState.value = UpdateUiState.Failed(if (full) UpdateFailure.InsufficientStorage else UpdateFailure.Network, - if (full) "Not enough storage for the update" else "Update transfer failed; try again") + if (full) "Not enough storage for the update" else "Update transfer failed; try again", operationKind) } - catch (_: Exception) { mutableState.value = UpdateUiState.Failed(UpdateFailure.InvalidMetadata, "Update could not be processed") } + catch (_: Exception) { mutableState.value = UpdateUiState.Failed(UpdateFailure.InvalidMetadata, "Update could not be processed", operationKind) } } } private fun systemOwnsFlow(current: UpdateUiState): Boolean = - current == UpdateUiState.HandingOff || current == UpdateUiState.PermissionNeeded + installerActive || current == UpdateUiState.HandingOff || current == UpdateUiState.PermissionNeeded - override fun check(manual: Boolean): Unit = runOperation { + override fun check(manual: Boolean): Unit = runOperation(UpdateOperation.Check) { if (systemOwnsFlow(state.value)) return@runOperation if (!manual && !preferences.enabled()) return@runOperation ready?.let { manifest -> @@ -86,25 +92,34 @@ class HouseholdUpdateController( retryOperation = { check(true) } mutableState.value = UpdateUiState.Checking val release = transport.latest(preferences.url(), abis, sdk) - if (release == null) { mutableState.value = UpdateUiState.NoReleasePublished; return@runOperation } + if (release == null) { + candidate = null; mutableRelease.value = null + mutableState.value = UpdateUiState.NoReleasePublished + return@runOperation + } val installed = platform.installed() mutableVersion.value = installed.version if (release.manifest.packageId != installed.packageId) throw UpdateException(UpdateFailure.WrongPackage, "Release belongs to a different application") if (installed.signers != setOf(release.manifest.signerSha256)) throw UpdateException(UpdateFailure.WrongSigner, "Release signer differs from this installation") if (release.manifest.versionCode < installed.version.versionCode) throw UpdateException(UpdateFailure.LowerVersionCode, "Channel release is older than this installation") if (release.manifest.versionCode == installed.version.versionCode) { - candidate = null + candidate = null; mutableRelease.value = null mutableState.value = UpdateUiState.UpToDate - } else { candidate = release; mutableState.value = available(release) } + } else { + candidate = release + val metadata = available(release.manifest, release.asset, release.notes) + mutableRelease.value = metadata + mutableState.value = metadata + } } - private fun available(release: UpdateCandidate): UpdateUiState.Available { + private fun available(manifest: UpdateManifest, asset: UpdateAsset, notes: String): UpdateUiState.Available { val date = DateTimeFormatter.ofLocalizedDate(java.time.format.FormatStyle.MEDIUM).withLocale(Locale.getDefault()) - .withZone(ZoneId.systemDefault()).format(Instant.parse(release.manifest.publishedAt)) - return UpdateUiState.Available(release.manifest.versionName, release.asset.bytes, date, release.notes) + .withZone(ZoneId.systemDefault()).format(Instant.parse(manifest.publishedAt)) + return UpdateUiState.Available(manifest.versionName, asset.bytes, date, notes) } - override fun download(): Unit = runOperation { + override fun download(): Unit = runOperation(UpdateOperation.Download) { if (systemOwnsFlow(state.value)) return@runOperation if (ready != null) return@runOperation val release = candidate ?: return@runOperation @@ -115,7 +130,7 @@ class HouseholdUpdateController( try { transport.download(release, store.partial) { done, total -> mutableState.value = UpdateUiState.Downloading(done, total) } currentCoroutineContext().ensureActive() - store.commit(release.manifest, release.asset) + store.commit(release.manifest, release.asset, release.notes) currentCoroutineContext().ensureActive() ready = release.manifest mutableState.value = UpdateUiState.Ready(release.manifest.versionName) @@ -127,20 +142,19 @@ class HouseholdUpdateController( @Synchronized override fun cancel() { - if (systemOwnsFlow(state.value)) return transport.cancel() val previous = operation - previous?.cancel() + if (!installerActive) previous?.cancel() operation = scope.launch { previous?.join() store.partial.delete() mutableState.value = ready?.let { UpdateUiState.Ready(it.versionName) } - ?: candidate?.let { available(it) } ?: UpdateUiState.Idle + ?: candidate?.let { mutableRelease.value } ?: UpdateUiState.Idle } } - override fun install(): Unit = runOperation { - if (state.value == UpdateUiState.HandingOff) return@runOperation + override fun install(): Unit = runOperation(UpdateOperation.Install) { + if (installerActive || state.value == UpdateUiState.HandingOff) return@runOperation val manifest = ready ?: return@runOperation retryOperation = { install() } val asset = manifest.selectAsset(abis, sdk) @@ -150,9 +164,15 @@ class HouseholdUpdateController( mutableState.value = if (platform.openPermissionSettings()) UpdateUiState.PermissionNeeded else UpdateUiState.NoInstaller return@runOperation } + currentCoroutineContext().ensureActive() + installerActive = true mutableState.value = UpdateUiState.HandingOff platform.install(store.apk, asset, ::handleInstallOutcome) + } catch (error: CancellationException) { + installerActive = false + throw error } catch (error: Exception) { + installerActive = false store.clear(); ready = null retryOperation = { if (candidate != null) download() else check(true) } throw error @@ -162,18 +182,20 @@ class HouseholdUpdateController( fun handleInstallOutcome(outcome: InstallOutcome) { scope.launch { restored.await() + installerActive = outcome == InstallOutcome.Pending || outcome == InstallOutcome.Success if (ready == null && outcome != InstallOutcome.Pending) { + installerActive = false retryOperation = { check(true) } mutableState.value = UpdateUiState.Idle onResume() return@launch } mutableState.value = when (outcome) { - InstallOutcome.Pending -> UpdateUiState.HandingOff + InstallOutcome.Pending -> if (state.value is UpdateUiState.Ready) state.value else UpdateUiState.HandingOff InstallOutcome.Cancelled -> UpdateUiState.InstallCancelled InstallOutcome.Unavailable -> UpdateUiState.NoInstaller - InstallOutcome.InsufficientStorage -> UpdateUiState.Failed(UpdateFailure.InsufficientStorage, "Android needs more storage to install the retained update") - InstallOutcome.Failed -> UpdateUiState.Failed(UpdateFailure.InvalidMetadata, "Android could not install the update; the verified download is retained") + InstallOutcome.InsufficientStorage -> UpdateUiState.Failed(UpdateFailure.InsufficientStorage, "Android needs more storage to install the retained update", UpdateOperation.Install) + InstallOutcome.Failed -> UpdateUiState.Failed(UpdateFailure.InvalidMetadata, "Android could not install the update; the verified download is retained", UpdateOperation.Install) InstallOutcome.Success -> UpdateUiState.HandingOff } if (outcome != InstallOutcome.Pending) onResume() @@ -189,7 +211,8 @@ class HouseholdUpdateController( mutableVersion.value = platform.installed().version val manifest = ready ?: return@launch if (mutableVersion.value.versionCode >= manifest.versionCode) { - store.clear(); ready = null; candidate = null; mutableState.value = UpdateUiState.Idle + installerActive = false + store.clear(); ready = null; candidate = null; mutableRelease.value = null; mutableState.value = UpdateUiState.Idle } else if (state.value == UpdateUiState.PermissionNeeded) { // Returning from settings requires another explicit Install press. mutableState.value = if (platform.hasInstallPermission()) UpdateUiState.Ready(manifest.versionName) diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt index c7faa29e..b46bb0e2 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/UpdateController.kt @@ -8,9 +8,11 @@ interface UpdateController { val state: StateFlow val autoCheck: StateFlow val installedVersion: StateFlow + val release: StateFlow fun check(manual: Boolean) fun download() + /** Discard partial bytes; retain verified bytes and restore Ready without duplicating a system session. */ fun cancel() fun install() fun retry() @@ -35,11 +37,14 @@ sealed interface UpdateUiState { data object PermissionNeeded : UpdateUiState data object HandingOff : UpdateUiState data object InstallCancelled : UpdateUiState - data class Failed(val kind: UpdateFailure, val message: String) : UpdateUiState + data class Failed(val kind: UpdateFailure, val message: String, val operation: UpdateOperation) : UpdateUiState data object Offline : UpdateUiState data object NoInstaller : UpdateUiState } +/** The failed action is structured; UI must not infer it from a reason string. */ +enum class UpdateOperation { Check, Download, Install } + /** Failures are distinct from a successful version comparison or an empty channel. */ enum class UpdateFailure { Network, HttpRefused, InvalidMetadata, UnsupportedAbi, InsufficientStorage, diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/VerifiedUpdateStore.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/VerifiedUpdateStore.kt index d5f406b4..a28e80c1 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/VerifiedUpdateStore.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/update/VerifiedUpdateStore.kt @@ -3,6 +3,12 @@ package org.justinvisser.wolfskin.tv.update import java.io.File import java.security.MessageDigest +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.contentOrNull +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive /** Actual APK identity, read independently of channel metadata. */ data class ApkIdentity(val packageId: String, val version: InstalledVersion, val signers: Set) @@ -19,6 +25,9 @@ interface UpdatePlatform { /** Installer results do not imply the running process has been replaced. */ enum class InstallOutcome { Pending, Success, Cancelled, Failed, Unavailable, InsufficientStorage } +/** Metadata returned only after verifying the persisted APK against this release. */ +data class VerifiedRelease(val manifest: UpdateManifest, val asset: UpdateAsset, val notes: String) + /** Private staging; a metadata commit occurs only after independently verifying the APK. */ class VerifiedUpdateStore(val directory: File, private val platform: UpdatePlatform) { val partial = File(directory, "download.part") @@ -52,23 +61,28 @@ class VerifiedUpdateStore(val directory: File, private val platform: UpdatePlatf } } - fun commit(manifest: UpdateManifest, asset: UpdateAsset) { + fun commit(manifest: UpdateManifest, asset: UpdateAsset, notes: String) { verify(partial, manifest, asset) check(partial.renameTo(apk)) { "Could not commit verified APK" } val temporary = File(directory, "ready.pending") - temporary.outputStream().use { it.write(UpdateManifest.encode(manifest).toByteArray()); it.fd.sync() } + val metadata = Json.parseToJsonElement(UpdateManifest.encode(manifest)).jsonObject + val stored = JsonObject(metadata + ("releaseNotes" to JsonPrimitive(notes))) + temporary.outputStream().use { it.write(stored.toString().toByteArray()); it.fd.sync() } check(temporary.renameTo(record)) { "Could not commit verified metadata" } } /** Re-hash and re-inspect after process death; a marker alone never establishes trust. */ - fun restore(abis: List, sdk: Int): UpdateManifest? { + fun restore(abis: List, sdk: Int): VerifiedRelease? { partial.delete() File(directory, "ready.pending").delete() if (!record.exists()) { apk.delete(); return null } return try { - val manifest = UpdateManifest.parse(record.readText()) - verify(apk, manifest, manifest.selectAsset(abis, sdk)) - manifest + val text = record.readText() + val manifest = UpdateManifest.parse(text) + val asset = manifest.selectAsset(abis, sdk) + verify(apk, manifest, asset) + val notes = Json.parseToJsonElement(text).jsonObject["releaseNotes"]?.jsonPrimitive?.contentOrNull.orEmpty() + VerifiedRelease(manifest, asset, notes) } catch (_: Exception) { clear(); null } } diff --git a/docker/README.md b/docker/README.md index e35d146e..92dc7adf 100644 --- a/docker/README.md +++ b/docker/README.md @@ -145,6 +145,16 @@ explicit check/download/cancel/install/retry/resume actions. Its capture fake does not perform real operations. Classic Opt update controls use that same controller; the old package retains its original updater. +`release: StateFlow` retains version, size, localized +date and release notes through download, Ready and installation cancellation. +Verified records persist notes as an optional `releaseNotes` field alongside +the manifest; existing manifest-only records remain readable. `Failed.operation` +is `UpdateOperation.Check`, `Download` or `Install`, never inferred from message text. +Permission and handoff dismissals restore verified Ready without discarding its +APK. Installer ownership is tracked separately from the visible state, so a +dismissed but active system session still blocks a duplicate handoff. Calling +`install()` from PermissionNeeded resolves and opens the permission settings again. + The client uses a dedicated anonymous OkHttp client, validating every redirect: HTTPS, no URL user-info, no cookies/Jellyfin token/repository credential. Loopback HTTP is available only through the test transport constructor flag.

V}N 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