evOo-local/apps/web/src/lib/workspace-pane-pref.ts
cynarAI e28c3acf02
feat: let the pane beside a conversation follow the bot's work (#123)
The live screen opens wide beside the chat while the bot works on it or asks
for a takeover, a file the bot presents as its result opens next to the
conversation, and a question that scrolled away gets a "Needs you" pill back
to it. Shared core rules derive the focus from signals clients already have
(pointer events, takeover requests, a new `present` flag on attach_file,
pending asks), move the pane only on focus edges, never replace a pane the
user opened, and learn per bot whether the screen opens on its own. Pane
widths persist per device; mobile shows a pill that opens the computer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C7VSRHHzyt2KwoCkUkZ2Gc
2026-10-03 22:23:46 +02:00

53 lines
1.5 KiB
TypeScript

import { parseScreenPaneHabit, type ScreenPaneHabit } from "@rakazo/core";
function screenHabitKey(userId: string | null | undefined, botId: string | null | undefined) {
if (!userId || !botId) return null;
return `rakazo:screen-pane:${userId}:${botId}`;
}
export function readScreenPaneHabit(
userId: string | null | undefined,
botId: string | null | undefined,
): ScreenPaneHabit {
const key = screenHabitKey(userId, botId);
if (!key) return 0;
try {
return parseScreenPaneHabit(window.localStorage.getItem(key));
} catch {
return 0;
}
}
export function writeScreenPaneHabit(
userId: string | null | undefined,
botId: string | null | undefined,
habit: ScreenPaneHabit,
): void {
const key = screenHabitKey(userId, botId);
if (!key) return;
try {
if (habit === 0) window.localStorage.removeItem(key);
else window.localStorage.setItem(key, String(habit));
} catch {
// Private mode or a full quota only loses the learned default.
}
}
export function readPaneWidth(storageKey: string, fallback: number, min: number, max: number) {
try {
const stored = Number(window.localStorage.getItem(storageKey));
if (Number.isFinite(stored) && stored > 0) return Math.max(min, Math.min(max, stored));
} catch {
// Fall through to the default width.
}
return fallback;
}
export function writePaneWidth(storageKey: string, width: number): void {
try {
window.localStorage.setItem(storageKey, String(Math.round(width)));
} catch {
// The width still applies for this session.
}
}