Merge Wholphin v1.1.0 while preserving Wolfskin features #27
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fm/wolfskin-upstream-1-1-0"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Outcome
Merge upstream Wholphin v1.1.0 into Wolfskin while preserving every fork delta. This is a real two-parent merge, not a rebase or squash.
6bb382a12655216cdf5a590f5ddb24ad0293dfae; upstream tag:2bb662fd603143753493d13e2b91ac6d18bdb8f5.670e95f2fa6f7d94c70d36cfbfb2e9d713697c92.git describe --tags --long --match='v*'isv1.1.0-29-g670e95f2; version naming remains upstream-tag-plus-distance, with Wolfskinpmarkers reserved for an authorized release. No version override, new tag, release, asset upload, or TV installation.applicationIdstaysorg.justinvisser.wolfskin.tv.Conflict log
ui/detail/discover/DiscoverSeriesDetails.kt: rating parameteravailability: SeerrAvailabilitywith Wolfskinrating: SourceRatings?. Wolfskin wins the rating type so RT/IMDb/TMDB badges remain; upstream wins the added availability input so corrected request status/permissions work.ui/setup/seerr/AddSeerrServer.kt: API-key URLseerrUrlPrefill(initialUrl): upstream/plugin URL wins when nonblank, otherwise Wolfskin's editablehttps://seerr.justinvisser.orgdefault wins. Initial focus uses the effective URL, so a prefilled URL moves to the key field.All other overlapping edits merged automatically. No side-wide
ours/theirscheckout. In particular, SourceRatings service/model/row, updater and its Forgejo fixtures, theme/artwork, profile focus, Docker wrapper/lock, Makefile and existing Wolfskin tests are retained. The Conductarr integration currently uses Seerr with per-profile Jellyfin identities and matching PWA ratings; no new Conductarr API or Discover implementation is added.Wolfskin-path preservation check
The baseline is 116 paths changed by Wolfskin relative to v1.0.9. All 116 still differ from upstream v1.1.0 after this merge; none vanished into an upstream replacement. 83 paths are byte-identical to Wolfskin main, including all fork-added source/resources/tests, updater, artwork,
HomePage.kt,UiConstants.kt,QuickDetails.kt,Rating.kt,SourceRatingsRow.kt, and Docker/Makefile code. The 33 changed baseline paths are 32 upstream overlaps plusdocker/README.mdintegration documentation.Reproduce with the original base rather than a later moving main:
Wolfskin-only added files retained (28; 27 unchanged, build README extended)
Full 116-path Wolfskin baseline
Requested main...HEAD --stat restricted to Wolfskin baseline paths
Full before/after patches, stats, immutable-path inventory and logs are preserved outside the checkout under
/root/.treehouse/firstmate-7bab20/2/firstmate/data/wolfskin-upstream-1-1-0/.Build, tests and artifact evidence
GREEN: one
make apkand onemake test, as requested; no repeated Gradle validation runs.make apk→bash docker/gradle.sh release clean assembleDefaultReleaseBUILD SUCCESSFUL in 6m 42s; 70 tasks executed; release-vital lint tasks included; signed universal + armeabi-v7a + arm64-v8a + x86_64 APKs.make test→bash docker/gradle.sh debug testDefaultDebugUnitTestBUILD SUCCESSFUL in 3m 58s; 66 suites, 550 tests, 0 failures, 0 errors, 0 skipped. Existing assertions retained. Includes Wolfskin ratings/episode scores/row UI, Seerr defaults, active-profile focus, Forgejo updater; upstream folder inheritance, session restoration and Dolby conversion tests.UNSET, new track-choice insert, foreign-key check and integrity check passed. No live database touched.apksigner verify --verbose --print-certsandaapt2 dump badgingfor all 4 APKs in the pinned Docker imageorg.justinvisser.wolfskin.tv, labelWolfskin, same signing SHA-2565cd708ffa94cc22fa41648377a305af3afe0f6da394c57e67024df43c1fcb5a0.libmpv.so,libffmpegJNI.so,libdav1dJNI.soand newlibdovi_android.so. APK SHA-256173920183c27f3ffb8c8bd46271753f0d9042192903205536fbd9b6e3b7b6ccd.git diff --check main...HEADgradlew.batare reported as trailing whitespace. Wrapper is byte-identical to v1.1.0 (blob03754c4c3d9206f5c9ef69e41990dfe26a05251e); do not normalize the upstream Windows wrapper in this merge.Artifact-version limitation: validation started while the merge was uncommitted. Source code is the merged tree, but Git-derived APK metadata is still
1.0.9-28-g6bb382a1, code64. These are local proof artifacts, not release-ready APKs. The committed head describes asv1.1.0-29-g670e95f2; any future authorized release must build its committed/tagged head with the existing versioning process. After the successful smoke/build, onlydocker/README.mddocumentation was added before committing; no compiled source changed. Working tree is clean.Exact extra smoke commands:
No failing application test was reproduced: this is a release integration, not a standalone bug fix. The first temporary smoke harness attempt failed on an absent optional JSON
indiceskey; correcting the harness to accept a schema without indexes produced the passing run, with no project change or weakened assertion.Toolchain / CI
Upstream Kotlin 2.4.21, Gradle 9.8.2, AGP 9.5.0, ExoplayerHdrUtils 0.4.1, serialization/dependency bumps imported unchanged. The existing digest-pinned SDK37/JDK21 Docker image and
docker/gradle.shwork without code changes; Wholphin native extensions remain 0.2.4. Hostflockserialization,--no-daemonand four-worker limit unchanged. There are no tracked dependency lockfiles or verification-metadata files to update, and no existing wrapper distribution checksum field; this does not add a new verification policy. Gradle 10 deprecation/configuration-time resolution, OpenAPIlongmapping and Kotlin warnings remain visible, not suppressed. Generated OpenAPI and Room schema files were not edited beyond unchanged upstream files imported by the merge.Forgejo repository API confirms
has_actions=false; upstream GitHub workflow dependency updates are imported but stay dormant, and no Forgejo workflow is enabled. This Android repository has nomake checktarget or Go packages: the copied Conductarr race-test/issue-closing gates are not applicable, and no fictitious Conductarr issue is closed. No Chromium/browser suite, live Arr/provider/queue operation, release asset change, or TV action.TV layout impact — hand-tuned layout work (wolfskin#10)
HomeRowPresets.kt,ItemGrid.ktorHomePage.kt. Wolfskin's hand-tuned home spacing, watched marks, row/detail ratings and active-profile focus remain; no layout conflict.CollectionFolderGrid.kt/CollectionFolderList.ktnow render throughCollectionFolderViewScope.PlaylistDetails.ktuses the sameCollectionFolderViewContentas libraries, aligning header/view options/grid/list/dense layout and focus/position behavior. This is a visible playlist/library change, not a claim that physical alignment was verified.CollectionFolderViewModel.getAncestorDisplayInfo: a folder without its own view options looks up the first ancestor with saved settings; saved child view/sort wins, inherited sort is used only when saved-display-info is enabled, filters are not inherited, and a display-info-ID override bypasses ancestor lookup. This can change untouched subfolders' view/sort without changing saved preferences.HomeDataService; main home/row focus code is unchanged. Home settings add a Source row (shifting settings-list focus indices), source selection and explicit save/discard on exit. Unset source order is local → server profile → companion plugin → defaults; selecting/resetting to plugin settings can visibly change rows. Existing local rows remain first in unset-source lookup.Seerr / Discover and future Conductarr-backed Discover
/wholphin/public,/wholphin/homesettings,/wholphin/seerrsettings; it can supply home rows/custom endpoints and Discover URL/credentials.UserSwitchListenertries plugin Seerr login before saved per-profile login. Successful plugin login can use an API key or local account, and plugin-managed connections cannot be removed from the TV UI. If no plugin settings are returned or plugin login returns false, saved per-profile login is tried; an exception while fetching plugin settings can abort that coroutine before fallback.Jellyfin 12, session restoration and app database
WholphinApplication.newMinimumServerVersion = ServerVersion(12, 0, 0).SwitchServerViewModel,SwitchUserViewModelandPreferencesViewModelclassify 12+ as SUPPORTED; the future-unsupported warning is for older supported servers. Jellyfin SDK stays 1.7.1. No new rejection or future-unsupported warning for Justin's v12 server; no live-server verification performed.MostRecentServerSharedPreferences(server URL/ID and user ID/token), revalidates the stored user throughgetCurrentUser, respects protected profiles, and routes startup errors back to the server list. Hot auto-login can reuse an unprotected current user.AppUpgradeHandlermigrates oldcurrentServerId/currentUserIdonly when the current app version is ≤1.0.8-0-g0, not the previous version. A 1.1.0 upgrade therefore does not seed the new recent-server provider from legacy preferences. Cold launch may require selecting the existing server/profile again; the Room records remain. Imported unchanged rather than expanding this merge into an upstream bug fix.SeriesTrackChoiceandusers.c_homeSettingsSource(defaultUNSET). Downgrading while retaining that database is not supported; no downgrade/destructive fallback is registered. Firstmate explicitly authorized unchanged upstream migrations after checking the fork has no Wolfskin Room entities, DAOs or schema changes (only non-RoomBaseItem,DiscoverItem,SourceRatingsdiffer). UpstreamAppUpgradeHandlerconverts legacy language choices when the new table is empty. No TV installation or live migration here.Playback / Xiaomi MiTV-AFMU0 risk notes
Target box: Android 14, armeabi-v7a, S905X5M. JVM/build/ELF evidence does not prove its decoder behavior.
libdovi_android.sois present, but physical Dolby Vision activation, frame cost and passthrough remain unverified. JNI loading failure leaves original frames while the extractor may already advertise profile 8: exercise this only in the approved device window, not by enabling it here.TrustAllControllersCallback: accepts default player commands from all controllers, broader than play/pause alone. Useful for remote/Cast controls, with a larger local-controller command surface. Fire OS voice permission is Fire-flavor only, not the default Xiaomi build.Device verification limit
not smoke-tested on the TV. A smoke test needs Justin's ADB window and explicit installation approval. Walk:
Publishing a Wolfskin release or installing/updating on the TV remains outside this PR's authorization.
## Description Wholphin builds item image URLs without Jellyfin's `tag` query parameter. `ImageUrlService` already receives the item's `imageTags` and `backdropTags`, and the low-level `getItemImageUrl` supports `tag`, but no branch passed it. Today only chapter and now-playing images set it. Before: `/Items/{id}/Images/Primary?quality=96&fillHeight=229` After: `/Items/{id}/Images/Primary?quality=96&fillHeight=229&tag={ImageTags.Primary}` This is how the official Jellyfin clients request images. jellyfin-web and the official Jellyfin Android TV app both copy `ImageTags[...]` (and the parent/series tags) into the image URL. I also added `ImageUrlServiceTest`, which covers each branch. ### Related issues I tested each one on the emulator against a stock Jellyfin 12.1 server (no plugins), comparing `main` with this branch: - **#366 (Image cache expiration): fixed by this PR.** - **#1249 (blank tile for a newly added movie) and #1338 (episode cover never refreshes): already fixed on `main` since v1.0.3, not by this PR.** - **#360 (Option to hide spoilers): partly.** ## AI or LLM usage This change was made with AI assistance (Claude Code). It was used for: - the code changes in `ImageUrlService` and the call sites listed above - the new `ImageUrlServiceTest` - the emulator testing and benchmarks - drafting this description The testing is what's described above: unit tests, an Android TV emulator against Jellyfin 12.1 servers (with Jellyfin Enhanced and stock), request logs from a proxy, and a check of every tag against the server's metadata. I've reviewed the change and can explain it. I'm also a maintainer on Jellyfin Enhanced, which is how I ran into this. I'm happy to share examples of my own coding work if that helps with reviewing this.v1.0.9(#2072) 5f2f9a8106Cross-family code review (Claude Sonnet): APPROVE, no blocking findings. Reviewed head
670e95f2fa6f7d94c70d36cfbfb2e9d713697c92(parents Wolfskin main6bb382a1+ upstream v1.1.02bb662fd). This is a comment and commit status only; I did not approve-merge or edit the PR.Checks:
git merge-tree --write-tree 6bb382a1 v1.1.0: conflicts are exactly the two named files, and HEAD differs from Git's own merge only in those two resolutions plus the newdocker/README.md. So the other 30 overlapping files are the plain 3-way result, with the Wolfskin delta kept and the upstream delta taken.DiscoverSeriesDetails.kt(upstreamavailability: SeerrAvailability+ Wolfskinrating: SourceRatings?) is consistent with its ViewModel and callers.AddSeerrServer.ktusesseerrUrlPrefill(initialUrl)in both flows (plugin URL wins when nonblank, else the Wolfskin default). Sampled rating, theme, NavDrawer, preferences, MainActivity, proto and Seerr discover: Wolfskin deltas intact.AppDatabase,DatabaseModule, all DAOs/entities, andTestDbMigrationsare identical to v1.1.0. Wolfskin has no Room entity, DAO or schema delta (v1.0.9..main empty). Migration is 35->40->41, one-way.app/build.gradle.ktschange isimplementation(libs.exoplayerhdrutils).applicationIdis stillorg.justinvisser.wolfskin.tv. No version override, tag, signing change or.forgejo;.githubequals upstream and stays dormant. LICENSE intact.test-summary.json(66 suites / 550 tests / 0 failures),make apklog, and the 35->40->41 migration smoke match the PR body. The stale1.0.9-28-g6bb382a1APK version is disclosed. Gradle not rerun. Minor:make-test.logis a truncated capture; the test result rests on the JSON summary.UserSwitchListener.kt); the Jellyfin 12 minimum isServerVersion(12,0,0), and v1.1.0 release notes say it is the last 10.10/10.11 release; theAppUpgradeHandlergap (current, notprevious, compared to1.0.8-0-g0) is real. None needs a code change now.Non-blocking: the upstream
gradlew.batCRLF makesgit diff --checknonzero (correctly untouched). The TV device walk stays outstanding and gates any future install, not this merge. Consider a Wolfskin issue for the session-restoration gap before the TV install.Full report:
/root/.treehouse/firstmate-7bab20/2/firstmate/data/review-wolfskin-27/report.md