Files
paseo/packages/app/src/utils/web-focus.ts
T
Mohamed Boudra d4435bd016 perf(app): keep warm workspace switching responsive (#3447)
* perf(app): reduce warm workspace switch work

Retained workspaces avoided mounts but pane activity still rerendered the full composer, message input, and agent-control presentation. Keep the activity contract intact while moving focus-sensitive behavior behind small context consumers, and add a Playwright benchmark that measures rapid retained workspace switching on one browser clock.

* perf(app): accelerate retained workspace switching

Avoid repeated retained-stream layout reconciliation and unrelated workspace structure recomputation. Use the lightweight route transition while the host is already focused, while preserving targeted root POP_TO for returns from app-wide routes where it prevents duplicate hidden decks.

* perf(app): defer composer focus during workspace switches

* perf(app): retain recently used workspaces longer

Keep up to ten workspace screens warm so normal multi-workspace navigation does not repeatedly rebuild recently used timelines. Inactive screens expire after ten minutes, while the active screen remains protected and capacity eviction stays least-recently-used.

* fix(app): reconcile retained timeline geometry

* fix(app): refresh retained reading position
2026-08-16 12:40:28 +02:00

55 lines
917 B
TypeScript

interface FocusWithRetriesOptions {
focus: () => void;
isFocused: () => boolean;
deferInitialAttempt?: boolean;
timeoutMs?: number;
onSuccess?: () => void;
onTimeout?: () => void;
}
export function focusWithRetries({
focus,
isFocused,
deferInitialAttempt = false,
timeoutMs = 1500,
onSuccess,
onTimeout,
}: FocusWithRetriesOptions): () => void {
let cancelled = false;
const deadlineMs = Date.now() + timeoutMs;
const tick = () => {
if (cancelled) return;
try {
focus();
} catch {
// ignore
}
if (isFocused()) {
onSuccess?.();
return;
}
if (Date.now() >= deadlineMs) {
onTimeout?.();
return;
}
requestAnimationFrame(() => {
requestAnimationFrame(tick);
});
};
if (deferInitialAttempt) {
requestAnimationFrame(tick);
} else {
tick();
}
return () => {
cancelled = true;
};
}