github vatax3/NuvioTVOS v1.0.9
1.0.9 — the player gives the remote back

latest releases: v1.0.44, v1.0.43, v1.0.42...
one month ago

Six reported problems, four of them in the player.

The skip card was holding the remote hostage

It appeared with the interval, took focus unconditionally, and kept it for the whole opening — with no handler for a direction. Left and right were dead for ninety seconds, at the exact moment somebody reaches for the fast-forward.

It now forwards them, through the transport's own acceleration table. Up or down hands the remote back and brings the controls up where the card was. It carries upstream's ten-second auto-hide, whose countdown stops while the transport is showing — so time spent reading the controls never counts against it, and on the MPV engine a pause does not quietly spend it. It no longer draws over an open track panel, and no longer takes focus out of a control row somebody is already using.

One deliberate divergence from SkipIntroVisibilityRules.kt, recorded in the source: Android keeps the card drawn beside the control row, in a scaffold that reserves room for both. Ours is a floating overlay over a transport that owns its own layout, so drawn together it lands across the title of what is playing — visible in a screenshot the moment Down was pressed. It stands down instead. Nothing is lost: everything it could do is on the row underneath it, more precisely.

Hold a direction to seek

Tapping already stepped ten seconds, and tapping quickly accelerated to sixty. Holding did nothing past the first press: tvOS has no equivalent of Android's KeyEvent.repeatCount, so the acceleration this player was written around was unreachable by the one gesture everybody tries first. A press recognizer reads the button still being down, below the focus graph, so it works whether the transport is up or the picture is bare.

The hero follows the cursor onto a collection

Moving onto a collection rail left the hero describing whichever title the cursor had been on last — worse than showing nothing, because it captioned something the cursor was no longer on. A folder is not a media item and nothing reported the move. Upstream builds a hero from the folder itself; that is ported field for field, with null for everything a folder cannot have and the same backdrop fallback chain.

Trailers actually play now

youtube://<id> puts the id in the URL's host, where the app has no watch request to act on — so it opened and fell through to its own home screen. It travels as a full watch link now. canOpenURL answers for the scheme and never looks at the rest, so there was never a failure to detect or a fallback to try; the form has to be right the first time, which is why it is covered by tests. Ids arriving as links (youtu.be/…, /embed/…, a full watch URL) are unwrapped — the same malformed value used to break the artwork too.

"You are watching" stays down while you are choosing something

Pausing and then opening the subtitle chooser raised the card over the list of languages a few seconds later. The rule had only ever asked whether playback was stopped.

Skip, Play next and Stay here wear the app's focus, not the platform's

tvOS 26 lays its own opaque plate over a Button after the view tree is built, so .buttonStyle(.plain) does not prevent it — the large white slab that was reported. Same answer as the stream row: a focusable shape with the button trait, owning every pixel of its own focus state.


Verified on the simulator: the hero following folder cards and returning to full metadata on a catalogue card; both player cards focused in the app's own treatment with no plate; Down handing off to the transport with Pause focused.

Not verified on device: the held-direction seek. It needs a stream this simulator will decode and a physically held button, and neither is available here.

164 unit tests, 8 UI tests.

The IPA is unsigned — sideload it with your own signing.

Don't miss a new NuvioTVOS release

NewReleases is sending notifications on new releases.