mirror of
https://git.mirrors.martin98.com/https://github.com/open-webui/open-webui
synced 2025-08-18 01:25:57 +08:00
refac: styling
This commit is contained in:
parent
dd4cf102cc
commit
ff2fff857a
@ -358,7 +358,7 @@
|
|||||||
?.at(0) ?? undefined;
|
?.at(0) ?? undefined;
|
||||||
|
|
||||||
currentUtterance = new SpeechSynthesisUtterance(content);
|
currentUtterance = new SpeechSynthesisUtterance(content);
|
||||||
currentUtterance.rate = speechRate;
|
currentUtterance.rate = $settings.audio?.tts?.speedRate ?? 1;
|
||||||
|
|
||||||
if (voice) {
|
if (voice) {
|
||||||
currentUtterance.voice = voice;
|
currentUtterance.voice = voice;
|
||||||
@ -385,7 +385,7 @@
|
|||||||
if (audioElement) {
|
if (audioElement) {
|
||||||
audioElement.src = audio.src;
|
audioElement.src = audio.src;
|
||||||
audioElement.muted = true;
|
audioElement.muted = true;
|
||||||
audioElement.playbackRate = speechRate;
|
audioElement.playbackRate = $settings.audio?.tts?.speedRate ?? 1;
|
||||||
|
|
||||||
audioElement
|
audioElement
|
||||||
.play()
|
.play()
|
||||||
@ -430,28 +430,6 @@
|
|||||||
|
|
||||||
let audioAbortController = new AbortController();
|
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.
|
// Audio cache map where key is the content and value is the Audio object.
|
||||||
const audioCache = new Map();
|
const audioCache = new Map();
|
||||||
const emojiCache = new Map();
|
const emojiCache = new Map();
|
||||||
@ -940,41 +918,6 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</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>
|
<div>
|
||||||
<button
|
<button
|
||||||
class=" p-3 rounded-full bg-gray-50 dark:bg-gray-900"
|
class=" p-3 rounded-full bg-gray-50 dark:bg-gray-900"
|
||||||
|
@ -204,6 +204,8 @@
|
|||||||
const blob = await res.blob();
|
const blob = await res.blob();
|
||||||
const blobUrl = URL.createObjectURL(blob);
|
const blobUrl = URL.createObjectURL(blob);
|
||||||
const audio = new Audio(blobUrl);
|
const audio = new Audio(blobUrl);
|
||||||
|
audio.playbackRate = $settings.audio?.tts?.speedRate ?? 1;
|
||||||
|
|
||||||
audioParts[idx] = audio;
|
audioParts[idx] = audio;
|
||||||
loadingSpeech = false;
|
loadingSpeech = false;
|
||||||
lastPlayedAudioPromise = lastPlayedAudioPromise.then(() => playAudio(idx));
|
lastPlayedAudioPromise = lastPlayedAudioPromise.then(() => playAudio(idx));
|
||||||
@ -226,6 +228,7 @@
|
|||||||
console.log(voice);
|
console.log(voice);
|
||||||
|
|
||||||
const speak = new SpeechSynthesisUtterance(message.content);
|
const speak = new SpeechSynthesisUtterance(message.content);
|
||||||
|
speak.rate = $settings.audio?.tts?.speedRate ?? 1;
|
||||||
|
|
||||||
console.log(speak);
|
console.log(speak);
|
||||||
|
|
||||||
@ -410,7 +413,7 @@
|
|||||||
const isEnterPressed = e.key === 'Enter';
|
const isEnterPressed = e.key === 'Enter';
|
||||||
|
|
||||||
if (isCmdOrCtrlPressed && isEnterPressed) {
|
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 class=" mt-2 mb-1 flex justify-between text-sm font-medium">
|
||||||
<div>
|
<div>
|
||||||
<button
|
<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"
|
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={() => {
|
on:click={() => {
|
||||||
saveNewMessageHandler();
|
saveNewMessageHandler();
|
||||||
|
@ -23,6 +23,10 @@
|
|||||||
let voices = [];
|
let voices = [];
|
||||||
let voice = '';
|
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 () => {
|
const getVoices = async () => {
|
||||||
if ($config.audio.tts.engine === '') {
|
if ($config.audio.tts.engine === '') {
|
||||||
const getVoicesLoop = setInterval(async () => {
|
const getVoicesLoop = setInterval(async () => {
|
||||||
@ -56,6 +60,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
speechRate = $settings.audio?.tts?.speedRate ?? 1;
|
||||||
conversationMode = $settings.conversationMode ?? false;
|
conversationMode = $settings.conversationMode ?? false;
|
||||||
speechAutoSend = $settings.speechAutoSend ?? false;
|
speechAutoSend = $settings.speechAutoSend ?? false;
|
||||||
responseAutoPlayback = $settings.responseAutoPlayback ?? false;
|
responseAutoPlayback = $settings.responseAutoPlayback ?? false;
|
||||||
@ -83,6 +88,7 @@
|
|||||||
engine: STTEngine !== '' ? STTEngine : undefined
|
engine: STTEngine !== '' ? STTEngine : undefined
|
||||||
},
|
},
|
||||||
tts: {
|
tts: {
|
||||||
|
speedRate: speechRate,
|
||||||
voice: voice !== '' ? voice : undefined,
|
voice: voice !== '' ? voice : undefined,
|
||||||
defaultVoice: $config?.audio?.tts?.voice ?? '',
|
defaultVoice: $config?.audio?.tts?.voice ?? '',
|
||||||
nonLocalVoices: $config.audio.tts.engine === '' ? nonLocalVoices : undefined
|
nonLocalVoices: $config.audio.tts.engine === '' ? nonLocalVoices : undefined
|
||||||
@ -153,6 +159,21 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
|
|
||||||
<hr class=" dark:border-gray-850" />
|
<hr class=" dark:border-gray-850" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user