fix(tv): only defer option-modal selection when it navigates

The close-first + runAfterInteractions change (needed so the in-player audio
switch's replacePlayer isn't swallowed by the modal route) also runs for every
other tv-option-modal caller — detail-page audio, library filters, settings —
whose onSelect only updates state. Deferring those until after dismissal
re-renders the page after focus returns and yanks TV focus, leaving navigation
stuck. Gate the deferral behind deferApplyUntilDismissed (set only by the
in-player audio caller); everyone else applies before closing, as before.
This commit is contained in:
Gauvain
2026-07-07 00:36:31 +02:00
parent 271ed84811
commit 03ae18e3c0
4 changed files with 29 additions and 5 deletions

View File

@@ -76,13 +76,23 @@ export default function TVOptionModal() {
}, [isReady]);
const handleSelect = (value: any) => {
// Close FIRST, run the callback after this modal route is dismissed: an
// onSelect that navigates (e.g. the transcode audio switch replacing the
// player) would otherwise target the MODAL route and be swallowed.
const onSelect = modalState?.onSelect;
if (modalState?.deferApplyUntilDismissed) {
// onSelect navigates (the transcode audio switch replacing the player);
// a router.replace fired while this modal is the active route would be
// swallowed. Close FIRST, apply after dismissal.
const onSelect = modalState.onSelect;
store.set(tvOptionModalAtom, null);
router.back();
InteractionManager.runAfterInteractions(() => onSelect?.(value));
return;
}
// State-only callers (detail page, library filters, settings): run before
// closing so the re-render happens while the modal is up. Deferring it until
// after dismissal re-renders the page after focus returns and yanks TV
// focus, leaving navigation stuck.
modalState?.onSelect(value);
store.set(tvOptionModalAtom, null);
router.back();
InteractionManager.runAfterInteractions(() => onSelect?.(value));
};
const handleClose = useCallback(() => {