fix(ui): focus, paging and state that a key or a finger can reach
- A key landing on a side panel's tab steps into the card it peeks open, not onto the hidden tab. - The Channels cards keep their status / pager row at the list's end while the band is folded. - A menu row's note shows on an enabled row too: the download state under 'Download…', not a title. - A removal chip hands the focus to its neighbour before it goes, for every caller (the feed's and Plex's active filters); the hidden-filter cue's own copy is gone. - Back to a spot within a page's end spacer lands at the page's end, not its top. - A running push / revert is tracked per list: another list's push is no longer refused unseen.
This commit is contained in:
@@ -28,6 +28,12 @@ function rememberScroll(key: string, top: number): void {
|
||||
// Put the scroller back to `top`. The feed is virtualized, so on a remount the list needs a frame
|
||||
// or two to render enough rows to reach its full height; an immediate `scrollTop` would otherwise
|
||||
// clamp short. Re-apply over a few frames until it sticks (or the content is simply shorter now).
|
||||
// A spot the page can no longer reach — the last stretch of a page scrolled to its very end, whose
|
||||
// Back-to-top spacer only shows once scrolled — goes as far as the page does: it used to be left at
|
||||
// the top (round 2, F8). Only a spacer's worth short, and only once the height has held still, is
|
||||
// that answer early; a list still loading is further short than that, and gets the full wait.
|
||||
const SETTLED_FRAMES = 10;
|
||||
const SPACER_REM = 6;
|
||||
function restoreScroll(el: HTMLElement, top: number): () => void {
|
||||
if (top <= 0) {
|
||||
el.scrollTop = 0;
|
||||
@@ -35,11 +41,22 @@ function restoreScroll(el: HTMLElement, top: number): () => void {
|
||||
}
|
||||
let raf = 0;
|
||||
let frames = 0;
|
||||
let still = 0;
|
||||
let lastMax = -1;
|
||||
let cancelled = false;
|
||||
const tick = () => {
|
||||
if (cancelled) return;
|
||||
if (el.scrollHeight - el.clientHeight >= top) el.scrollTop = top;
|
||||
if (el.scrollTop >= top - 1 || frames++ > 90) return; // reached, or gave up after ~1.5s
|
||||
const max = el.scrollHeight - el.clientHeight;
|
||||
if (max >= top) el.scrollTop = top;
|
||||
if (el.scrollTop >= top - 1) return; // reached
|
||||
still = max === lastMax ? still + 1 : 0;
|
||||
lastMax = max;
|
||||
const rem = parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
|
||||
const nearEnd = max > 0 && top - max <= SPACER_REM * rem;
|
||||
if ((nearEnd && still >= SETTLED_FRAMES) || frames++ > 90) {
|
||||
el.scrollTop = max; // as near as the page reaches now
|
||||
return;
|
||||
}
|
||||
raf = requestAnimationFrame(tick);
|
||||
};
|
||||
raf = requestAnimationFrame(tick);
|
||||
|
||||
Reference in New Issue
Block a user