feat: track sprite state per tab

This commit is contained in:
2026-01-20 10:56:53 -08:00
parent 861b44797e
commit 51ecf47508
3 changed files with 47 additions and 11 deletions
+1
View File
@@ -33,6 +33,7 @@ export const claudeStore = {
// Methods // Methods
setConnectionStatus: conversationsStore.setConnectionStatus, setConnectionStatus: conversationsStore.setConnectionStatus,
setConnectionStatusForConversation: conversationsStore.setConnectionStatusForConversation, setConnectionStatusForConversation: conversationsStore.setConnectionStatusForConversation,
setCharacterStateForConversation: conversationsStore.setCharacterStateForConversation,
setSessionId: conversationsStore.setSessionId, setSessionId: conversationsStore.setSessionId,
setSessionIdForConversation: conversationsStore.setSessionIdForConversation, setSessionIdForConversation: conversationsStore.setSessionIdForConversation,
setWorkingDirectory: conversationsStore.setWorkingDirectory, setWorkingDirectory: conversationsStore.setWorkingDirectory,
+22
View File
@@ -1,6 +1,8 @@
import { writable, derived, get } from "svelte/store"; import { writable, derived, get } from "svelte/store";
import type { TerminalLine, ConnectionStatus, PermissionRequest } from "$lib/types/messages"; import type { TerminalLine, ConnectionStatus, PermissionRequest } from "$lib/types/messages";
import type { CharacterState } from "$lib/types/states";
import { cleanupConversationTracking } from "$lib/tauri"; import { cleanupConversationTracking } from "$lib/tauri";
import { characterState } from "$lib/stores/character";
export interface Conversation { export interface Conversation {
id: string; id: string;
@@ -9,6 +11,7 @@ export interface Conversation {
sessionId: string | null; sessionId: string | null;
connectionStatus: ConnectionStatus; connectionStatus: ConnectionStatus;
workingDirectory: string; workingDirectory: string;
characterState: CharacterState;
isProcessing: boolean; isProcessing: boolean;
grantedTools: Set<string>; grantedTools: Set<string>;
createdAt: Date; createdAt: Date;
@@ -41,6 +44,7 @@ function createConversationsStore() {
sessionId: null, sessionId: null,
connectionStatus: "disconnected", connectionStatus: "disconnected",
workingDirectory: "", workingDirectory: "",
characterState: "idle",
isProcessing: false, isProcessing: false,
grantedTools: new Set(), grantedTools: new Set(),
createdAt: new Date(), createdAt: new Date(),
@@ -122,6 +126,19 @@ function createConversationsStore() {
return convs; return convs;
}); });
}, },
setCharacterStateForConversation: (conversationId: string, state: CharacterState) => {
conversations.update((convs) => {
const conv = convs.get(conversationId);
if (conv) {
conv.characterState = state;
// If this is the active conversation, update the global character state
if (conversationId === get(activeConversationId)) {
characterState.setState(state);
}
}
return convs;
});
},
requestPermission: (request: PermissionRequest) => pendingPermission.set(request), requestPermission: (request: PermissionRequest) => pendingPermission.set(request),
clearPermission: () => pendingPermission.set(null), clearPermission: () => pendingPermission.set(null),
setPendingRetryMessage: (message: string | null) => pendingRetryMessage.set(message), setPendingRetryMessage: (message: string | null) => pendingRetryMessage.set(message),
@@ -177,6 +194,11 @@ function createConversationsStore() {
if (currentId !== id) { if (currentId !== id) {
activeConversationId.set(id); activeConversationId.set(id);
// Update the global character state to match the conversation's state
if (targetConv) {
characterState.setState(targetConv.characterState);
}
// Auto-reconnect logic // Auto-reconnect logic
if (targetConv && targetConv.connectionStatus === "disconnected") { if (targetConv && targetConv.connectionStatus === "disconnected") {
// Check if another conversation is connected // Check if another conversation is connected
+24 -11
View File
@@ -142,7 +142,8 @@ export async function initializeTauriListeners() {
// Add system message to the correct conversation // Add system message to the correct conversation
claudeStore.addLineToConversation(targetConversationId, "system", "Connected to Claude Code"); claudeStore.addLineToConversation(targetConversationId, "system", "Connected to Claude Code");
characterState.setState("idle"); // Update character state for this conversation
claudeStore.setCharacterStateForConversation(targetConversationId, "idle");
// Check if this specific conversation has connected before // Check if this specific conversation has connected before
if (!connectedConversations.has(targetConversationId)) { if (!connectedConversations.has(targetConversationId)) {
@@ -164,7 +165,10 @@ export async function initializeTauriListeners() {
claudeStore.addLineToConversation(targetConversationId, "system", "Disconnected from Claude Code"); claudeStore.addLineToConversation(targetConversationId, "system", "Disconnected from Claude Code");
} }
characterState.setState("idle"); // Update character state for this conversation
if (targetConversationId) {
claudeStore.setCharacterStateForConversation(targetConversationId, "idle");
}
} else if (status === "error") { } else if (status === "error") {
const targetConversationId = conversation_id || get(claudeStore.activeConversationId); const targetConversationId = conversation_id || get(claudeStore.activeConversationId);
@@ -181,12 +185,6 @@ export async function initializeTauriListeners() {
const stateUnlisten = await listen<StateChangePayload>("claude:state", (event) => { const stateUnlisten = await listen<StateChangePayload>("claude:state", (event) => {
const { state, conversation_id } = event.payload; const { state, conversation_id } = event.payload;
// Only process events for the active conversation
const activeConversationId = get(claudeStore.activeConversationId);
if (conversation_id && activeConversationId && conversation_id !== activeConversationId) {
return;
}
const stateMap: Record<string, CharacterState> = { const stateMap: Record<string, CharacterState> = {
idle: "idle", idle: "idle",
thinking: "thinking", thinking: "thinking",
@@ -201,10 +199,25 @@ export async function initializeTauriListeners() {
const mappedState = stateMap[state.toLowerCase()] || "idle"; const mappedState = stateMap[state.toLowerCase()] || "idle";
if (mappedState === "success" || mappedState === "error") { // Always update the conversation's state
characterState.setTemporaryState(mappedState, 3000); if (conversation_id) {
claudeStore.setCharacterStateForConversation(conversation_id, mappedState);
} else { } else {
characterState.setState(mappedState); // Fallback to active conversation if no conversation_id
const activeConversationId = get(claudeStore.activeConversationId);
if (activeConversationId) {
claudeStore.setCharacterStateForConversation(activeConversationId, mappedState);
}
}
// Only update global character state for active conversation
const activeConversationId = get(claudeStore.activeConversationId);
if (!conversation_id || conversation_id === activeConversationId) {
if (mappedState === "success" || mappedState === "error") {
characterState.setTemporaryState(mappedState, 3000);
} else {
characterState.setState(mappedState);
}
} }
}); });
unlisteners.push(stateUnlisten); unlisteners.push(stateUnlisten);