Browse Source

refac: styling

Timothy J. Baek 7 tháng trước cách đây
mục cha
commit
ff2fff857a

+ 2 - 59
src/lib/components/chat/MessageInput/CallOverlay.svelte

@@ -358,7 +358,7 @@
 								?.at(0) ?? undefined;
 
 						currentUtterance = new SpeechSynthesisUtterance(content);
-						currentUtterance.rate = speechRate;
+						currentUtterance.rate = $settings.audio?.tts?.speedRate ?? 1;
 
 						if (voice) {
 							currentUtterance.voice = voice;
@@ -385,7 +385,7 @@
 				if (audioElement) {
 					audioElement.src = audio.src;
 					audioElement.muted = true;
-					audioElement.playbackRate = speechRate;
+					audioElement.playbackRate = $settings.audio?.tts?.speedRate ?? 1;
 
 					audioElement
 						.play()
@@ -430,28 +430,6 @@
 
 	let audioAbortController = new AbortController();
 
-	// Audio speed control
-	let speechRate = 1;
-	let showSpeedMenu = false;
-
-	const speedOptions = [2, 1.75, 1.5, 1.25, 1, 0.75, 0.5];
-
-	const setSpeedRate = (rate: number) => {
-		speechRate = rate;
-		showSpeedMenu = false;
-		updateAudioSpeed();
-	};
-
-	const updateAudioSpeed = () => {
-		if (currentUtterance) {
-			currentUtterance.rate = speechRate;
-		}
-		const audioElement = document.getElementById('audioElement') as HTMLAudioElement;
-		if (audioElement) {
-			audioElement.playbackRate = speechRate;
-		}
-	};
-
 	// Audio cache map where key is the content and value is the Audio object.
 	const audioCache = new Map();
 	const emojiCache = new Map();
@@ -940,41 +918,6 @@
 				</button>
 			</div>
 
-			<div class="relative">
-				<Dropdown bind:show={showSpeedMenu}>
-					<button class="p-2 rounded-full bg-gray-50 dark:bg-gray-900">
-						<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
-							<polygon points="8,5 8,19 19,12" fill="currentColor"/>
-							<path d="M12 2A10 10 0 0 0 12 22" fill="none" stroke="currentColor" stroke-width="2" stroke-dasharray="2,2"/>
-							<path d="M12 2A10 10 0 0 1 12 22" fill="none" stroke="currentColor" stroke-width="2"/>
-						</svg>
-					</button>
-
-					<div slot="content">
-						<DropdownMenu.Content
-							class="w-full max-w-[180px] rounded-lg px-1 py-1.5 border border-gray-300/30 dark:border-gray-700/50 z-[9999] bg-white dark:bg-gray-900 dark:text-white shadow-sm"
-							sideOffset={6}
-							side="top"
-							align="start"
-							transition={flyAndScale}
-						>
-							{#each speedOptions as speed}
-								<DropdownMenu.Item
-									class="flex gap-2 items-center px-3 py-2 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md {speechRate === speed ? 'bg-gray-200 dark:bg-gray-600' : ''}"
-									on:click={() => setSpeedRate(speed)}
-								>
-									<div class="flex items-center">
-										<div class="line-clamp-1">
-											{speed}x
-										</div>
-									</div>
-								</DropdownMenu.Item>
-							{/each}
-						</DropdownMenu.Content>
-					</div>
-				</Dropdown>
-			</div>
-
 			<div>
 				<button
 					class=" p-3 rounded-full bg-gray-50 dark:bg-gray-900"

+ 5 - 2
src/lib/components/chat/Messages/ResponseMessage.svelte

@@ -204,6 +204,8 @@
 					const blob = await res.blob();
 					const blobUrl = URL.createObjectURL(blob);
 					const audio = new Audio(blobUrl);
+					audio.playbackRate = $settings.audio?.tts?.speedRate ?? 1;
+
 					audioParts[idx] = audio;
 					loadingSpeech = false;
 					lastPlayedAudioPromise = lastPlayedAudioPromise.then(() => playAudio(idx));
@@ -226,6 +228,7 @@
 					console.log(voice);
 
 					const speak = new SpeechSynthesisUtterance(message.content);
+					speak.rate = $settings.audio?.tts?.speedRate ?? 1;
 
 					console.log(speak);
 
@@ -410,7 +413,7 @@
 										const isEnterPressed = e.key === 'Enter';
 
 										if (isCmdOrCtrlPressed && isEnterPressed) {
-											document.getElementById('save-edit-message-button')?.click();
+											document.getElementById('confirm-edit-message-button')?.click();
 										}
 									}}
 								/>
@@ -418,7 +421,7 @@
 								<div class=" mt-2 mb-1 flex justify-between text-sm font-medium">
 									<div>
 										<button
-											id="close-edit-message-button"
+											id="save-new-message-button"
 											class=" px-4 py-2 bg-gray-50 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 border dark:border-gray-700 text-gray-700 dark:text-gray-200 transition rounded-3xl"
 											on:click={() => {
 												saveNewMessageHandler();

+ 21 - 0
src/lib/components/chat/Settings/Audio.svelte

@@ -23,6 +23,10 @@
 	let voices = [];
 	let voice = '';
 
+	// Audio speed control
+	let speechRate = 1;
+	const speedOptions = [2, 1.75, 1.5, 1.25, 1, 0.75, 0.5];
+
 	const getVoices = async () => {
 		if ($config.audio.tts.engine === '') {
 			const getVoicesLoop = setInterval(async () => {
@@ -56,6 +60,7 @@
 	};
 
 	onMount(async () => {
+		speechRate = $settings.audio?.tts?.speedRate ?? 1;
 		conversationMode = $settings.conversationMode ?? false;
 		speechAutoSend = $settings.speechAutoSend ?? false;
 		responseAutoPlayback = $settings.responseAutoPlayback ?? false;
@@ -83,6 +88,7 @@
 					engine: STTEngine !== '' ? STTEngine : undefined
 				},
 				tts: {
+					speedRate: speechRate,
 					voice: voice !== '' ? voice : undefined,
 					defaultVoice: $config?.audio?.tts?.voice ?? '',
 					nonLocalVoices: $config.audio.tts.engine === '' ? nonLocalVoices : undefined
@@ -153,6 +159,21 @@
 					{/if}
 				</button>
 			</div>
+
+			<div class=" py-0.5 flex w-full justify-between">
+				<div class=" self-center text-xs font-medium">{$i18n.t('Speed Rate')}</div>
+
+				<div class="flex items-center relative">
+					<select
+						class="dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
+						bind:value={speechRate}
+					>
+						{#each speedOptions as option}
+							<option value={option} selected={speechRate === option}>{option}x</option>
+						{/each}
+					</select>
+				</div>
+			</div>
 		</div>
 
 		<hr class=" dark:border-gray-850" />