Timothy J. Baek 7 月之前
父节点
当前提交
2adaf9ba3d

+ 7 - 1
src/lib/components/chat/Chat.svelte

@@ -28,7 +28,8 @@
 		showCallOverlay,
 		currentChatPage,
 		temporaryChatEnabled,
-		mobile
+		mobile,
+		showOverview
 	} from '$lib/stores';
 	import {
 		convertMessagesToHistory,
@@ -292,6 +293,11 @@
 					controlPane.resize(0);
 				}
 			}
+
+			if (!value) {
+				showCallOverlay.set(false);
+				showOverview.set(false);
+			}
 		});
 	});
 

+ 39 - 37
src/lib/components/chat/ChatControls.svelte

@@ -133,48 +133,50 @@
 				}
 			}}
 		>
-			<div class="pr-4 pb-8 flex max-h-full min-h-full" in:slide={{ duration: 200, axis: 'x' }}>
-				<div
-					class="w-full {$showOverview && !$showCallOverlay
-						? ' '
-						: 'px-5 py-4 bg-white dark:shadow-lg dark:bg-gray-850  border border-gray-50 dark:border-gray-800'}  rounded-lg z-50 pointer-events-auto overflow-y-auto scrollbar-hidden"
-				>
-					{#if $showCallOverlay}
-						<div class="w-full h-full flex justify-center">
-							<CallOverlay
-								bind:files
-								{submitPrompt}
-								{stopResponse}
-								{modelId}
-								{chatId}
-								{eventTarget}
+			{#if $showControls}
+				<div class="pr-4 pb-8 flex max-h-full min-h-full">
+					<div
+						class="w-full {$showOverview && !$showCallOverlay
+							? ' '
+							: 'px-5 py-4 bg-white dark:shadow-lg dark:bg-gray-850  border border-gray-50 dark:border-gray-800'}  rounded-lg z-50 pointer-events-auto overflow-y-auto scrollbar-hidden"
+					>
+						{#if $showCallOverlay}
+							<div class="w-full h-full flex justify-center">
+								<CallOverlay
+									bind:files
+									{submitPrompt}
+									{stopResponse}
+									{modelId}
+									{chatId}
+									{eventTarget}
+									on:close={() => {
+										showControls.set(false);
+									}}
+								/>
+							</div>
+						{:else if $showOverview}
+							<Overview
+								{history}
+								on:nodeclick={(e) => {
+									showMessage(e.detail.node.data.message);
+								}}
 								on:close={() => {
 									showControls.set(false);
 								}}
 							/>
-						</div>
-					{:else if $showOverview}
-						<Overview
-							{history}
-							on:nodeclick={(e) => {
-								showMessage(e.detail.node.data.message);
-							}}
-							on:close={() => {
-								showControls.set(false);
-							}}
-						/>
-					{:else}
-						<Controls
-							on:close={() => {
-								showControls.set(false);
-							}}
-							{models}
-							bind:chatFiles
-							bind:params
-						/>
-					{/if}
+						{:else}
+							<Controls
+								on:close={() => {
+									showControls.set(false);
+								}}
+								{models}
+								bind:chatFiles
+								bind:params
+							/>
+						{/if}
+					</div>
 				</div>
-			</div>
+			{/if}
 		</Pane>
 	{/if}
 </SvelteFlowProvider>

+ 62 - 54
src/lib/components/chat/MessageInput/CallOverlay.svelte

@@ -525,6 +525,60 @@
 		console.log(`Audio monitoring and playing stopped for message ID ${id}`);
 	};
 
+	const chatStartHandler = async (e) => {
+		const { id } = e.detail;
+
+		chatStreaming = true;
+
+		if (currentMessageId !== id) {
+			console.log(`Received chat start event for message ID ${id}`);
+
+			currentMessageId = id;
+			if (audioAbortController) {
+				audioAbortController.abort();
+			}
+			audioAbortController = new AbortController();
+
+			assistantSpeaking = true;
+			// Start monitoring and playing audio for the message ID
+			monitorAndPlayAudio(id, audioAbortController.signal);
+		}
+	};
+
+	const chatEventHandler = async (e) => {
+		const { id, content } = e.detail;
+		// "id" here is message id
+		// if "id" is not the same as "currentMessageId" then do not process
+		// "content" here is a sentence from the assistant,
+		// there will be many sentences for the same "id"
+
+		if (currentMessageId === id) {
+			console.log(`Received chat event for message ID ${id}: ${content}`);
+
+			try {
+				if (messages[id] === undefined) {
+					messages[id] = [content];
+				} else {
+					messages[id].push(content);
+				}
+
+				console.log(content);
+
+				fetchAudio(content);
+			} catch (error) {
+				console.error('Failed to fetch or play audio:', error);
+			}
+		}
+	};
+
+	const chatFinishHandler = async (e) => {
+		const { id, content } = e.detail;
+		// "content" here is the entire message from the assistant
+		finishedMessages[id] = true;
+
+		chatStreaming = false;
+	};
+
 	onMount(async () => {
 		const setWakeLock = async () => {
 			try {
@@ -558,60 +612,6 @@
 
 		startRecording();
 
-		const chatStartHandler = async (e) => {
-			const { id } = e.detail;
-
-			chatStreaming = true;
-
-			if (currentMessageId !== id) {
-				console.log(`Received chat start event for message ID ${id}`);
-
-				currentMessageId = id;
-				if (audioAbortController) {
-					audioAbortController.abort();
-				}
-				audioAbortController = new AbortController();
-
-				assistantSpeaking = true;
-				// Start monitoring and playing audio for the message ID
-				monitorAndPlayAudio(id, audioAbortController.signal);
-			}
-		};
-
-		const chatEventHandler = async (e) => {
-			const { id, content } = e.detail;
-			// "id" here is message id
-			// if "id" is not the same as "currentMessageId" then do not process
-			// "content" here is a sentence from the assistant,
-			// there will be many sentences for the same "id"
-
-			if (currentMessageId === id) {
-				console.log(`Received chat event for message ID ${id}: ${content}`);
-
-				try {
-					if (messages[id] === undefined) {
-						messages[id] = [content];
-					} else {
-						messages[id].push(content);
-					}
-
-					console.log(content);
-
-					fetchAudio(content);
-				} catch (error) {
-					console.error('Failed to fetch or play audio:', error);
-				}
-			}
-		};
-
-		const chatFinishHandler = async (e) => {
-			const { id, content } = e.detail;
-			// "content" here is the entire message from the assistant
-			finishedMessages[id] = true;
-
-			chatStreaming = false;
-		};
-
 		eventTarget.addEventListener('chat:start', chatStartHandler);
 		eventTarget.addEventListener('chat', chatEventHandler);
 		eventTarget.addEventListener('chat:finish', chatFinishHandler);
@@ -632,7 +632,15 @@
 	});
 
 	onDestroy(async () => {
+		eventTarget.removeEventListener('chat:start', chatStartHandler);
+		eventTarget.removeEventListener('chat', chatEventHandler);
+		eventTarget.removeEventListener('chat:finish', chatFinishHandler);
+
+		audioAbortController.abort();
+		await tick();
+
 		await stopAllAudio();
+
 		await stopRecordingCallback(false);
 		await stopCamera();
 	});