Add terminal big mode, keyboard shortcuts menu, and UX refinements

- Reduce mobile terminal widths by 2 chars (portrait 42x24, landscape 86x24)
- Add "Big mode" for mobile: desktop sizing (120x36) at 70% zoom
- Click zoom percentage to reset to 100%
- Add keyboard shortcuts submenu in session settings
- Update PRD with all terminal features and documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-21 00:20:40 -05:00
parent 5171059692
commit a2e10688bf
7 changed files with 473 additions and 36 deletions
+46 -2
View File
@@ -23,14 +23,22 @@
let menuOpen = false;
let autoScroll = true;
let tmuxAlive = false;
let isMobile = false;
// Load auto-scroll preference from localStorage
// Load auto-scroll preference from localStorage and detect mobile
onMount(() => {
if (browser) {
const stored = localStorage.getItem('spiceflow-auto-scroll');
if (stored !== null) {
autoScroll = stored === 'true';
}
// Detect mobile (screen width < 640px or height < 450px)
const checkMobile = () => {
isMobile = window.innerWidth < 640 || window.innerHeight < 450;
};
checkMobile();
window.addEventListener('resize', checkMobile);
return () => window.removeEventListener('resize', checkMobile);
}
});
@@ -149,6 +157,10 @@
}
}
function handleBigMode() {
terminalView?.setBigMode(true);
}
const statusColors: Record<string, string> = {
idle: 'bg-zinc-600',
processing: 'bg-green-500 animate-pulse',
@@ -163,13 +175,20 @@
$: statusIndicator = isTmuxSession
? (tmuxAlive ? 'bg-green-500' : 'bg-zinc-600')
: (statusColors[session?.status || 'idle'] || statusColors.idle);
function handleKeydown(event: KeyboardEvent) {
if (event.ctrlKey && event.shiftKey && event.key === 'R') {
event.preventDefault();
handleRefresh();
}
}
</script>
<svelte:head>
<title>{session?.title || `Session ${shortId}`} - Spiceflow</title>
</svelte:head>
<svelte:window on:click={() => (menuOpen = false)} />
<svelte:window on:click={() => (menuOpen = false)} on:keydown={handleKeydown} />
<!-- Header - Full (portrait) -->
<header class="flex-shrink-0 border-b border-zinc-800 px-4 py-3 landscape-mobile:hidden">
@@ -218,13 +237,27 @@
{autoAcceptEdits}
{autoScroll}
provider={session.provider}
showBigMode={isTmuxSession && isMobile}
on:toggleAutoAccept={handleToggleAutoAccept}
on:toggleAutoScroll={handleToggleAutoScroll}
on:condenseAll={() => messageList?.condenseAll()}
on:refresh={handleRefresh}
on:eject={handleEject}
on:bigMode={handleBigMode}
/>
<!-- Refresh button - desktop only -->
<button
on:click={handleRefresh}
class="hidden sm:block p-1.5 hover:bg-zinc-700 rounded transition-colors"
aria-label="Refresh"
title="Refresh"
>
<svg class="h-5 w-5 text-zinc-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
</button>
<span class="text-xs font-medium uppercase {providerColors[session.provider] || 'text-zinc-400'}">
{session.provider === 'tmux' ? 'terminal' : session.provider}
</span>
@@ -273,6 +306,17 @@
/>
<span>Auto-scroll</span>
</label>
{#if isTmuxSession && isMobile}
<button
on:click={() => { menuOpen = false; handleBigMode(); }}
class="w-full px-3 py-2 text-left text-sm hover:bg-zinc-700 flex items-center gap-2 transition-colors"
>
<svg class="h-4 w-4 text-cyan-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4" />
</svg>
Big mode
</button>
{/if}
<button
on:click={() => { menuOpen = false; handleRefresh(); }}
class="w-full px-3 py-2 text-left text-sm hover:bg-zinc-700 flex items-center gap-2 transition-colors"