Skip to content

Big refactor: provider integration, E2E coverage, profiling and v0.9.1 - #11

Open
sachk wants to merge 98 commits into
masterfrom
big-refactor
Open

sachk wants to merge 98 commits into
masterfrom
big-refactor

Conversation

@sachk

@sachk sachk commented Oct 17, 2026

Copy link
Copy Markdown
Collaborator

Scope

  • Consolidate the big-refactor integration history into topic commits while preserving the original content. The original DAG remains available at preservation/big-refactor-pre-squash-20261017.
  • Extend the real-application journey across filter/reset remote focus recovery, nested retained details, repeat at actual EOF, and sleep-after-current precedence.
  • Add repeatable isolated native profiling with explicit software-renderer measurement limits, strict baseline compatibility, private artifacts and bounded cleanup.
  • Clean up webOS packaging and diagnostic scripts: install-only verification by default, explicit launch, bounded transport, exact registration checks, no installed-tree benchmark mutations.
  • Build and audit unsigned iOS device IPAs with internal simulator artifacts and honest signing/provisioning boundaries.
  • Bundle published compatible provider releases: Jellyfin 0.2.14, Emby 0.1.9, Plex 0.1.10, Stremio 0.1.3, Open Movies 1.1.2.
  • Prepare Spool 0.9.1 from this branch; this PR does not merge the branch automatically.

Verification

  • Provider contract runners: Qt JIT and interpreter modes, all five providers; package build/validation and published feed digest/size verification.
  • Emby finite HTTP transfer smoke: original byte identity, actual encoded MP4, duration/height and cleanup.
  • Local webOS CLI/transport boundary suite, shell/Python syntax, package audit/metadata contracts, profiling report contracts, version synchronization and Actions syntax.
  • Actual app journey and native full-suite results are tracked by the linked Actions checks.
  • No TV was connected to, installed, launched or tested. Unsigned IPAs are not installable as downloaded; native simulator success is not physical-device playback certification.

sachk added 30 commits October 17, 2026 23:56
- build: pin the published provider UX cohort
- fix(build): validate immutable Nix store roots
- fix(ui): preserve directional gestures, reorder state and native drop data
- fix(ui): reconcile row sections from the published payload

Original commits:
bf0c8be
01f3fed
38fa648
3e839c3
- feat(ios): integrate native review build with current mobile owners

Original commits:
4804eb8
- fix(sdk): bound provider archives before extraction
- fix(sdk): reject malformed manifest field types

Original commits:
3db6857
c53f595
- fix(storage): preserve file credentials on failed replacement
- fix(cache): own database inputs across initialization

Original commits:
1d4ae77
f25c81e
- fix(player): join event callbacks before asynchronous core destruction
- fix(player): fence reentrant starts and retain core controls
- fix(player): bind delayed playback reports to their original source

Original commits:
da1dfd1
83c01ce
b5038ae
- fix(queue): notify traversal changes and shuffle for real

Original commits:
b7edc67
- fix(home): preserve warm rows and retire obsolete content requests

Original commits:
b7acf99
- fix(remote): preserve the playback clock across pause and seek

Original commits:
cd9ad7f
- fix(discovery): keep servers without IDs distinct

Original commits:
467304c
- fix(navigation): preserve item identity across retained pages

Original commits:
4fd251d
- fix(qml): finish picker placement and respect menu boundaries

Original commits:
ab00c67
- fix(android): launch intents without visibility-sensitive preflight

Original commits:
bc1f3e4
- fix(state): publish manual item changes after confirmed writes

Original commits:
ef69d35
- fix(app): fence every playback intent with one retirement path

Original commits:
d585f3f
- perf(player): wait on the mpv event loop explicitly
- perf(player): move queue ranges as one model operation

Original commits:
1333306
0a6c91e
- perf(remote): reuse queue metadata lookups as hashed joins

Original commits:
a9e793a
- perf(diagnostics): sample only while an overlay observes

Original commits:
a56c69d
- perf(player): publish the playback UI clock at a bounded cadence
- perf(player): avoid color diagnostic queries after every seek

Original commits:
b91a834
e914272
- perf(diagnostics): stop route sampling on cancellation

Original commits:
ab7ddaa
- perf(qml): bind media cards to row-specific model roles
- perf(qml): search library titles in a single traversal
- perf(qml): keep home rows stable while loading changes
- perf(home): retain descriptors when only row content changes
- perf(qml): refresh settings rows only for availability changes

Original commits:
2fb12f4
2bcca5c
81494ec
b44195f
09b9e3e
- feat(details): expose server trailers and extras on detail pages

Original commits:
e28e7ef
- feat(settings): add preferred audio language

Original commits:
1afe13c
- feat(player): add local repeat controls and report queue state
- feat(player): add a sleep timer with cancellable playback stop

Original commits:
74e027b
44334aa
- fix(ui): honor routed Back and contain modal pointer input
- fix(ui): route certificate dialog cancellation through Back

Original commits:
69052b8
ba72096
- fix(ui): make media information remotely scrollable
- fix(ui): reserve space for setting selectors
- fix(ui): expose accessible button actions and bounded content

Original commits:
4566f10
626305e
ba93a09
- fix(ui): give diagnostics confirmation ownership of its routes

Original commits:
c52124a
- fix(ui): make playback Back and segment actions consistent
- fix(ui): reflect the player mute state without changing it
- fix(ui): constrain the playback group menu to the viewport

Original commits:
a4274a5
988a2f8
0df128b
- fix(ui): keep detail actions and links usable on narrow screens

Original commits:
b8d3693
- fix(ui): offer persistent retry for a failed search

Original commits:
0bc907e
- fix(ui): keep updater input modal and honor routed Back

Original commits:
af37064
sachk added 7 commits October 22, 2026 03:52
spool.plex 0.1.12, spool.jellyfin 0.2.15 and spool.emby 0.1.10 are now
published; the pins are their release assets. The Jellyfin and Emby
archives unpack to exactly what was bundled before, compressed by CI's
zstd; Plex 0.1.12 also connects a lone server without asking.
Speed tests now return their per-concurrency samples, but Qt hands a
QVariantList to script as a sequence wrapper, so a provider returning the
result unchanged sent back an object keyed "0", "1", "2" and the
samples the network profiles learn from were lost. The result is built
from plain script arrays and objects, as LAN probe results already are.
…core

A prepared idle mpv core reports its own pause state as soon as it is
observed, and that report arrived while setup waited for the video
surface, overwriting a requested paused start (or a pause pressed during
setup) just before the file loaded. Pause reports are taken only once a
file has loaded; before that mpv's pause is only ever what was set.
Sparse large-library browsing with an alphabet index and type-to-seek,
throughput-aware artwork downloads, one-step accounts with sensible
defaults and Plex servers from an existing sign-in, a sideloadable iOS
build with a SideStore/AltStore source, and the published Plex 0.1.12,
Jellyfin 0.2.15 and Emby 0.1.10 providers.
On every direction key the library page checks that the selected card is
visibly on screen and, if not, takes the press as a gesture to recover
focus and consumes that key until it is released. During a hold the grid
moves the selection between frames, so the next card is often not laid
out when the next repeat arrives; the page read that as a lost selection
and swallowed the rest of the hold, which the release watchdog then
ended. This is what stopped holds dead in large libraries. A hold the
grid is driving now skips the check; pointer scrolling still recovers.
The render benchmark names the provider runtime from a hash's key order,
so two runs of one build could disagree and the profiler refused to
aggregate them as different environments.
The real page, browse controller and artwork pipeline over a server that
answers each block after 60 ms: a four second held key must keep moving,
the view must fill when it stops, and typing must settle. Timings --
GUI-thread stalls during the hold, rows and posters after release, seek
time, block and artwork requests -- are reported as LIBRARY_PROFILE for
comparison between builds rather than gated. It found the swallowed hold.
sachk added 12 commits October 22, 2026 20:41
The supervisor's crash selectors abort and fault on purpose, and each one
was filed as a desktop crash report. Mark them non-dumpable on Linux; the
supervisor still observes the real signal.
mpv's curl backend now honours --network-timeout as a stall limit. Its
60 s default outlasts any demuxer cache, so a server that stops sending
without closing froze playback for a minute before the transfer was
retried.
Rebase the fork onto upstream master (488fec0789, 252 commits). Upstream
now ships a D3D11 render API; the fork's gpu-next D3D11 path implements
that API instead of its own, so render through mpv_d3d11_fbo and allow the
legacy renderer as a D3D11 fallback like OpenGL. Upstream's stream_curl
fixes are ported onto the parallel range transport.

Also picks up two playback fixes from a webOS 24 stall where video never
came back while the clock ran on:

- A Starfish pipeline that starves for input is an underrun, not a
  failure, and a pipeline that does fail is rebuilt by seeking to the
  frozen frame instead of leaving playback running without picture.
- A transfer that receives nothing for --network-timeout is retried.
On a slow server, jumping to a letter waited behind up to three 100-row
blocks still loading for where the view had been, each allowed fifteen
seconds. A jump into a seekable listing now has a cancellable scope of
its own, and blocks more than two away from the viewport give up their
slot. A view that has just jumped waits 150 ms for its next move, so
stepping through letters loads only where it stops.

Speculative poster fetches likewise follow the viewport instead of
queueing behind where it was.
Two sets of letters, an A-Z rail beside a scroll bar with its own letter
callout, become one bar. The thumb's callout names where the view is.
In a name-sorted list each letter owns a stretch of the track as long as
its share of the titles but never too short to aim at, so the thumb and
the index agree: pointing names the letter there, a tap jumps to its
first title, a drag scrubs. From the remote, Right off the last column
focuses the bar; Up and Down step letters with their neighbours shown
in the callout, and Left, OK or Back return to the grid. The bar is
sized for a finger, a magic remote or a mouse.
Which providers Home shows stays in Settings > Accounts; Show all still appears while some are hidden.
An account's address is the provider's configured serverAddress when it
names one, such as "Local · 192.168.1.5", rather than the host of a long
routing name. The PIN screens can offer a provider-labelled switch to
remember the PIN, which the answer carries as `remember`.
/proc files report a size of zero, so reading /proc/meminfo until
QFile::atEnd() read nothing and every TV logged memTotal=0. A 2 GB set
keeps the low-memory budget it was tuned on, since the TV leaves an app
about 400 MB.

Each release compiles QML into a directory of its own; the ones left by
earlier releases are removed in the background after launch.
The night mode chain mixes pan, dialoguenhance and compand, which work in
different sample formats. libavfilter converts between them with an
aresample it inserts itself, and the curated build left that filter out,
so on the TV the whole chain failed to configure and was dropped.
A source at its operation limit failed a block on screen, which then
stayed blank until the view moved, and the letter index, which left the
letters estimated for the session. Blocks still on screen and the index
are asked for again, up to three times, a second further apart each time.
spool.plex 0.2.0 connects at the fastest of a server's addresses,
prefers the owner's own over plex.direct and the relay, names addresses
readably and can remember a Plex Home PIN. It needs this host's
remember-PIN switch on the PIN screens.
The library scroll bar becomes its letter index, large-library jumps stop
waiting behind rows already passed and failed rows are fetched again,
Plex connects at its fastest address with readable names and can remember
a Home PIN, Home drops its providers button, night mode works on webOS,
playback recovers from stalled Starfish pipelines and quiet connections,
and old compiled QML caches are cleaned up. Bundles Plex 0.2.0.
sachk added 5 commits October 23, 2026 17:10
OK activated on press, so the on-screen keyboard came up while the key
was still down and took its release for its own Enter. The PIN screen
then submitted an empty PIN and closed before anything was typed; Plex
accepted it for the linked account's own profile, so it unlocked
without one. Text rows now activate on release, and PIN screens ignore
an empty submit.
Restore failures were silent, so a launch that opened no accounts left
nothing in the device log. Log the module and outcome only, never the
provider's error text.
RangedDownload fetches one file over parallel HTTP range requests, each
on its own connection, handing a finished lane half of the busiest
one's remainder and falling back to one GET when ranges are ignored.
The updater uses two lanes, hashes the whole package off the GUI
thread, and installs as soon as it verifies instead of asking again.
Plex no longer asks for the PIN of the account a device linked with,
which plex.tv itself never requires.
TV text fields open their keyboard on OK's release, so a PIN screen no
longer closes itself with an empty entry; Plex stops asking for the
linked account's own PIN; updates download over two connections and
install once verified; failed account restores are logged. Bundles
Plex 0.2.1.

This branch was successfully deployed

2 active (outdated) deployments
release — e4f77770 Deployed Oct 22, 2026 by sachk
github-pages — e4f77770 Deployed Oct 22, 2026 by sachk
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants