Ver Fonte

feat: tts automatic playback

Timothy J. Baek há 1 ano atrás
pai
commit
5eff0e5f61

+ 1 - 0
src/lib/components/chat/Messages/ResponseMessage.svelte

@@ -458,6 +458,7 @@
 										</button>
 
 										<button
+											id="speak-button-{message.id}"
 											class="{isLastMessage
 												? 'visible'
 												: 'invisible group-hover:visible'} p-1 rounded dark:hover:text-white transition"

+ 4 - 28
src/lib/components/chat/Settings/Interface.svelte

@@ -10,7 +10,6 @@
 
 	// Addons
 	let titleAutoGenerate = true;
-	let speechAutoSend = false;
 	let responseAutoCopy = false;
 	let titleAutoGenerateModel = '';
 
@@ -23,12 +22,6 @@
 		saveSettings({ showUsername: showUsername });
 	};
 
-
-	const toggleSpeechAutoSend = async () => {
-		speechAutoSend = !speechAutoSend;
-		saveSettings({ speechAutoSend: speechAutoSend });
-	};
-
 	const toggleTitleAutoGenerate = async () => {
 		titleAutoGenerate = !titleAutoGenerate;
 		saveSettings({ titleAutoGenerate: titleAutoGenerate });
@@ -107,26 +100,6 @@
 				</div>
 			</div>
 
-			<div>
-				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs font-medium">Voice Input Auto-Send</div>
-
-					<button
-						class="p-1 px-3 text-xs flex rounded transition"
-						on:click={() => {
-							toggleSpeechAutoSend();
-						}}
-						type="button"
-					>
-						{#if speechAutoSend === true}
-							<span class="ml-2 self-center">On</span>
-						{:else}
-							<span class="ml-2 self-center">Off</span>
-						{/if}
-					</button>
-				</div>
-			</div>
-
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
 					<div class=" self-center text-xs font-medium">Response AutoCopy to Clipboard</div>
@@ -146,9 +119,12 @@
 					</button>
 				</div>
 			</div>
+
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
-					<div class=" self-center text-xs font-medium">Display the username instead of "You" in the Chat</div>
+					<div class=" self-center text-xs font-medium">
+						Display the username instead of "You" in the Chat
+					</div>
 
 					<button
 						class="p-1 px-3 text-xs flex rounded transition"

+ 72 - 18
src/lib/components/chat/Settings/Voice.svelte

@@ -5,6 +5,10 @@
 	export let saveSettings: Function;
 
 	// Voice
+
+	let speechAutoSend = false;
+	let responseAutoPlayback = false;
+
 	let engines = ['', 'openai'];
 	let engine = '';
 
@@ -33,6 +37,16 @@
 		}, 100);
 	};
 
+	const toggleResponseAutoPlayback = async () => {
+		responseAutoPlayback = !responseAutoPlayback;
+		saveSettings({ responseAutoPlayback: responseAutoPlayback });
+	};
+
+	const toggleSpeechAutoSend = async () => {
+		speechAutoSend = !speechAutoSend;
+		saveSettings({ speechAutoSend: speechAutoSend });
+	};
+
 	onMount(async () => {
 		let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
 
@@ -60,26 +74,66 @@
 	}}
 >
 	<div class=" space-y-3">
-		<div class=" py-0.5 flex w-full justify-between">
-			<div class=" self-center text-sm font-medium">Speech Engine</div>
-			<div class="flex items-center relative">
-				<select
-					class="w-fit pr-8 rounded py-2 px-2 text-xs bg-transparent outline-none text-right"
-					bind:value={engine}
-					placeholder="Select a mode"
-					on:change={(e) => {
-						if (e.target.value === 'openai') {
-							getOpenAIVoices();
-							speaker = 'alloy';
-						} else {
-							getWebAPIVoices();
-							speaker = '';
-						}
+		<div>
+			<div class=" mb-1 text-sm font-medium">TTS Settings</div>
+
+			<div class=" py-0.5 flex w-full justify-between">
+				<div class=" self-center text-xs font-medium">Speech Engine</div>
+				<div class="flex items-center relative">
+					<select
+						class="w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
+						bind:value={engine}
+						placeholder="Select a mode"
+						on:change={(e) => {
+							if (e.target.value === 'openai') {
+								getOpenAIVoices();
+								speaker = 'alloy';
+							} else {
+								getWebAPIVoices();
+								speaker = '';
+							}
+						}}
+					>
+						<option value="">Default (Web API)</option>
+						<option value="openai">Open AI</option>
+					</select>
+				</div>
+			</div>
+
+			<div class=" py-0.5 flex w-full justify-between">
+				<div class=" self-center text-xs font-medium">Voice Input Auto-Send</div>
+
+				<button
+					class="p-1 px-3 text-xs flex rounded transition"
+					on:click={() => {
+						toggleSpeechAutoSend();
+					}}
+					type="button"
+				>
+					{#if speechAutoSend === true}
+						<span class="ml-2 self-center">On</span>
+					{:else}
+						<span class="ml-2 self-center">Off</span>
+					{/if}
+				</button>
+			</div>
+
+			<div class=" py-0.5 flex w-full justify-between">
+				<div class=" self-center text-xs font-medium">TTS Automatic Playback</div>
+
+				<button
+					class="p-1 px-3 text-xs flex rounded transition"
+					on:click={() => {
+						toggleResponseAutoPlayback();
 					}}
+					type="button"
 				>
-					<option value="">Default (Web API)</option>
-					<option value="openai">Open AI</option>
-				</select>
+					{#if responseAutoPlayback === true}
+						<span class="ml-2 self-center">On</span>
+					{:else}
+						<span class="ml-2 self-center">Off</span>
+					{/if}
+				</button>
 			</div>
 		</div>
 

+ 8 - 0
src/routes/(app)/+page.svelte

@@ -448,6 +448,10 @@
 									if ($settings.responseAutoCopy) {
 										copyToClipboard(responseMessage.content);
 									}
+
+									if ($settings.responseAutoPlayback) {
+										document.getElementById(`speak-button-${responseMessage.id}`)?.click();
+									}
 								}
 							}
 						}
@@ -633,6 +637,10 @@
 					copyToClipboard(responseMessage.content);
 				}
 
+				if ($settings.responseAutoPlayback) {
+					document.getElementById(`speak-button-${responseMessage.id}`)?.click();
+				}
+
 				if (autoScroll) {
 					window.scrollTo({ top: document.body.scrollHeight });
 				}

+ 8 - 0
src/routes/(app)/c/[id]/+page.svelte

@@ -462,6 +462,10 @@
 									if ($settings.responseAutoCopy) {
 										copyToClipboard(responseMessage.content);
 									}
+
+									if ($settings.responseAutoPlayback) {
+										document.getElementById(`speak-button-${responseMessage.id}`)?.click();
+									}
 								}
 							}
 						}
@@ -647,6 +651,10 @@
 					copyToClipboard(responseMessage.content);
 				}
 
+				if ($settings.responseAutoPlayback) {
+					document.getElementById(`speak-button-${responseMessage.id}`)?.click();
+				}
+
 				if (autoScroll) {
 					window.scrollTo({ top: document.body.scrollHeight });
 				}