go to laast session
This commit is contained in:
@@ -43,3 +43,6 @@ client/dev-dist/
|
||||
|
||||
# Test results
|
||||
e2e/test-results/
|
||||
|
||||
# Ideas/notes
|
||||
ideas.md
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Spiceflow
|
||||
|
||||
The ~~spice~~ *tokens* must flow.
|
||||
|
||||
A mobile-friendly web app for controlling AI coding assistants (Claude Code, OpenCode) remotely.
|
||||
|
||||
```
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
export let autoScroll: boolean = true;
|
||||
export let provider: 'claude' | 'opencode' | 'tmux' = 'claude';
|
||||
export let showBigMode: boolean = false;
|
||||
export let lastSessionId: string | null = null;
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
toggleAutoAccept: boolean;
|
||||
@@ -13,6 +14,7 @@
|
||||
refresh: void;
|
||||
eject: void;
|
||||
bigMode: void;
|
||||
goToLastSession: void;
|
||||
}>();
|
||||
|
||||
function handleToggleAutoScroll() {
|
||||
@@ -54,6 +56,11 @@
|
||||
open = false;
|
||||
}
|
||||
|
||||
function handleGoToLastSession() {
|
||||
dispatch('goToLastSession');
|
||||
open = false;
|
||||
}
|
||||
|
||||
function handleClickOutside(event: MouseEvent) {
|
||||
const target = event.target as HTMLElement;
|
||||
if (!target.closest('.settings-dropdown')) {
|
||||
@@ -140,6 +147,19 @@
|
||||
<span class="text-sm text-zinc-200">Refresh</span>
|
||||
</button>
|
||||
|
||||
<!-- Go to last session -->
|
||||
{#if lastSessionId}
|
||||
<button
|
||||
on:click={handleGoToLastSession}
|
||||
class="w-full flex items-center gap-3 px-3 py-2.5 hover:bg-zinc-700/50 transition-colors text-left"
|
||||
>
|
||||
<svg class="h-4 w-4 text-zinc-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" />
|
||||
</svg>
|
||||
<span class="text-sm text-zinc-200">Last session</span>
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
{#if provider !== 'tmux'}
|
||||
<button
|
||||
on:click={handleCondenseAll}
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
export let sessionId: string;
|
||||
export let autoScroll: boolean = true;
|
||||
export let autoFocus: boolean = true;
|
||||
export let lastSessionId: string | null = null;
|
||||
|
||||
const dispatch = createEventDispatcher<{ aliveChange: boolean }>();
|
||||
const dispatch = createEventDispatcher<{ aliveChange: boolean; goToLastSession: void }>();
|
||||
|
||||
// ANSI to HTML converter for terminal colors
|
||||
const ansiConverter = new AnsiToHtml({
|
||||
@@ -588,6 +589,19 @@
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3" />
|
||||
</svg>
|
||||
</button>
|
||||
{#if lastSessionId}
|
||||
<span class="w-px h-6 bg-zinc-700"></span>
|
||||
<button
|
||||
on:click={() => dispatch('goToLastSession')}
|
||||
class="{btnBase} bg-spice-600/80 hover:bg-spice-600 text-white"
|
||||
aria-label="Go to last session"
|
||||
title="Go to last session"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" />
|
||||
</svg>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Hidden input for keyboard capture (invisible but functional for mobile) -->
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
let autoScroll = true;
|
||||
let tmuxAlive = false;
|
||||
let isMobile = false;
|
||||
let lastSessionId: string | null = null;
|
||||
|
||||
// Load auto-scroll preference from localStorage and detect mobile
|
||||
onMount(() => {
|
||||
@@ -32,6 +33,8 @@
|
||||
if (stored !== null) {
|
||||
autoScroll = stored === 'true';
|
||||
}
|
||||
// Load last session from localStorage
|
||||
lastSessionId = localStorage.getItem('spiceflow-last-session');
|
||||
// Detect mobile (screen width < 640px or height < 450px)
|
||||
const checkMobile = () => {
|
||||
isMobile = window.innerWidth < 640 || window.innerHeight < 450;
|
||||
@@ -42,11 +45,28 @@
|
||||
}
|
||||
});
|
||||
|
||||
// Track session history when navigating to a new session
|
||||
let previousSessionId: string | null = null;
|
||||
$: if (browser && sessionId && sessionId !== previousSessionId) {
|
||||
// Save the previous session as "last session" before switching
|
||||
if (previousSessionId) {
|
||||
localStorage.setItem('spiceflow-last-session', previousSessionId);
|
||||
lastSessionId = previousSessionId;
|
||||
}
|
||||
previousSessionId = sessionId;
|
||||
}
|
||||
|
||||
// Load session when sessionId changes (handles client-side navigation)
|
||||
$: if (sessionId) {
|
||||
activeSession.load(sessionId);
|
||||
}
|
||||
|
||||
function goToLastSession() {
|
||||
if (lastSessionId) {
|
||||
goto(`/session/${lastSessionId}`);
|
||||
}
|
||||
}
|
||||
|
||||
function handleToggleAutoScroll(event: CustomEvent<boolean>) {
|
||||
autoScroll = event.detail;
|
||||
if (browser) {
|
||||
@@ -236,6 +256,7 @@
|
||||
<SessionSettings
|
||||
{autoAcceptEdits}
|
||||
{autoScroll}
|
||||
{lastSessionId}
|
||||
provider={session.provider}
|
||||
showBigMode={isTmuxSession && isMobile}
|
||||
on:toggleAutoAccept={handleToggleAutoAccept}
|
||||
@@ -244,6 +265,7 @@
|
||||
on:refresh={handleRefresh}
|
||||
on:eject={handleEject}
|
||||
on:bigMode={handleBigMode}
|
||||
on:goToLastSession={goToLastSession}
|
||||
/>
|
||||
|
||||
<!-- Refresh button - desktop only -->
|
||||
@@ -326,6 +348,17 @@
|
||||
</svg>
|
||||
Refresh
|
||||
</button>
|
||||
{#if lastSessionId}
|
||||
<button
|
||||
on:click={() => { menuOpen = false; goToLastSession(); }}
|
||||
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" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" />
|
||||
</svg>
|
||||
Last session
|
||||
</button>
|
||||
{/if}
|
||||
{#if !isTmuxSession}
|
||||
<button
|
||||
on:click={() => { menuOpen = false; messageList?.condenseAll(); }}
|
||||
@@ -385,7 +418,7 @@
|
||||
</div>
|
||||
{:else if isTmuxSession}
|
||||
<!-- Terminal view for tmux sessions -->
|
||||
<TerminalView bind:this={terminalView} sessionId={sessionId || ''} {autoScroll} on:aliveChange={handleTmuxAliveChange} />
|
||||
<TerminalView bind:this={terminalView} sessionId={sessionId || ''} {autoScroll} {lastSessionId} on:aliveChange={handleTmuxAliveChange} on:goToLastSession={goToLastSession} />
|
||||
{:else}
|
||||
<MessageList bind:this={messageList} messages={$activeSession.messages} streamingContent={$activeSession.streamingContent} isThinking={$activeSession.isThinking} provider={session?.provider} {autoScroll} />
|
||||
|
||||
|
||||
Reference in New Issue
Block a user