feat(shell): hold now-playing marquee at start between scroll passes
Previously the marquee looped continuously, cycling back to the start the moment the text finished. Now it holds at the start for SCROLL_HOLD_MS (10s), scrolls one pass at SCROLL_STEP_MS per char, then holds again.
This commit is contained in:
@@ -239,10 +239,14 @@ export function Shell() {
|
|||||||
|
|
||||||
// ── Now-playing marquee ────────────────────────────────────────────────────
|
// ── Now-playing marquee ────────────────────────────────────────────────────
|
||||||
// The now-playing segment takes the full remaining status-bar width and
|
// The now-playing segment takes the full remaining status-bar width and
|
||||||
// marquee-scrolls on a 300ms timer when its text overflows; when it fits
|
// marquee-scrolls when its text overflows; when it fits (or the bar is too
|
||||||
// (or the bar is too narrow to show anything) it renders statically.
|
// narrow to show anything) it renders statically. Each pass scrolls at
|
||||||
|
// SCROLL_STEP_MS per char, then holds at the start for SCROLL_HOLD_MS
|
||||||
|
// before scrolling again.
|
||||||
const dims = useTerminalDimensions();
|
const dims = useTerminalDimensions();
|
||||||
const GAP = 3;
|
const GAP = 3;
|
||||||
|
const SCROLL_STEP_MS = 150;
|
||||||
|
const SCROLL_HOLD_MS = 10_000;
|
||||||
const [scrollOffset, setScrollOffset] = createSignal(0);
|
const [scrollOffset, setScrollOffset] = createSignal(0);
|
||||||
const leftFixed = () =>
|
const leftFixed = () =>
|
||||||
modeLabel().length +
|
modeLabel().length +
|
||||||
@@ -270,10 +274,29 @@ export function Shell() {
|
|||||||
setScrollOffset(0);
|
setScrollOffset(0);
|
||||||
if (!text || avail <= 0 || text.length <= avail) return;
|
if (!text || avail <= 0 || text.length <= avail) return;
|
||||||
const cycle = text.length + GAP - avail;
|
const cycle = text.length + GAP - avail;
|
||||||
const id = setInterval(() => {
|
// Hold at the start position for SCROLL_HOLD_MS, scroll one pass,
|
||||||
setScrollOffset((o) => (o + 1) % cycle);
|
// then hold again before the next pass.
|
||||||
}, 150);
|
let holdId: ReturnType<typeof setTimeout> | null = null;
|
||||||
onCleanup(() => clearInterval(id));
|
let scrollId: ReturnType<typeof setInterval> | null = null;
|
||||||
|
const startHold = () => {
|
||||||
|
setScrollOffset(0);
|
||||||
|
holdId = setTimeout(() => {
|
||||||
|
scrollId = setInterval(() => {
|
||||||
|
const next = scrollOffset() + 1;
|
||||||
|
if (next >= cycle) {
|
||||||
|
clearInterval(scrollId!);
|
||||||
|
startHold();
|
||||||
|
} else {
|
||||||
|
setScrollOffset(next);
|
||||||
|
}
|
||||||
|
}, SCROLL_STEP_MS);
|
||||||
|
}, SCROLL_HOLD_MS);
|
||||||
|
};
|
||||||
|
startHold();
|
||||||
|
onCleanup(() => {
|
||||||
|
if (holdId) clearTimeout(holdId);
|
||||||
|
if (scrollId) clearInterval(scrollId);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user