From 6c899634c21e339a9e174a4b2ccef4fb8dcaee33 Mon Sep 17 00:00:00 2001 From: lencx Date: Sun, 5 Mar 2023 11:45:52 +0800 Subject: [PATCH] chore: tts --- src-tauri/src/conf.rs | 5 +++++ src-tauri/src/scripts/chat.js | 19 ++++++++++------ src-tauri/src/scripts/cmd.js | 10 +++++++++ src-tauri/src/scripts/export.js | 39 +++++++++++++++++++++++---------- src/view/settings/General.tsx | 16 +++++++++++++- 5 files changed, 69 insertions(+), 20 deletions(-) diff --git a/src-tauri/src/conf.rs b/src-tauri/src/conf.rs index 2faef14f3..ebaff9c25 100644 --- a/src-tauri/src/conf.rs +++ b/src-tauri/src/conf.rs @@ -40,6 +40,7 @@ pub_struct!(AppConf { save_window_state: bool, global_shortcut: Option, default_origin: String, + speech_lang: String, // Main Window isinit: bool, @@ -69,6 +70,10 @@ impl AppConf { save_window_state: false, theme: "light".into(), auto_update: "prompt".into(), + #[cfg(target_os = "macos")] + speech_lang: "com.apple.eloquence.en-US.Rocko".into(), + #[cfg(not(target_os = "macos"))] + speech_lang: "".into(), tray: true, popup_search: false, isinit: true, diff --git a/src-tauri/src/scripts/chat.js b/src-tauri/src/scripts/chat.js index f3f6d1a89..37c3bc2c6 100644 --- a/src-tauri/src/scripts/chat.js +++ b/src-tauri/src/scripts/chat.js @@ -14,7 +14,8 @@ async function init() { ); } -function chatBtns() { +async function chatBtns() { + const chatConf = await invoke('get_app_conf') || {}; const synth = window.speechSynthesis; let currentUtterance = null; let currentIndex = -1; @@ -51,15 +52,19 @@ function chatBtns() { } } const txt = i?.innerText?.trim() || ''; - const lang = 'en-US'; if (!txt) return; const utterance = new SpeechSynthesisUtterance(txt); - utterance.voice = speechSynthesis.getVoices().find(voice => voice.lang === lang); + const voices = speechSynthesis.getVoices(); + let voice = voices.find(voice => voice.voiceURI === chatConf.speech_lang); + if (!voice) { + voice = voices.find(voice => voice.lang === 'en-US'); + } + utterance.voice = voice; currentIndex = idx; - utterance.lang = lang; - utterance.rate = 0.7; - utterance.pitch = 1.1; - utterance.volume = 1; + utterance.lang = voice.lang; + // utterance.rate = 0.7; + // utterance.pitch = 1.1; + // utterance.volume = 1; synth.speak(utterance); amISpeaking = synth.speaking; saybtn.innerHTML = setIcon('speaking'); diff --git a/src-tauri/src/scripts/cmd.js b/src-tauri/src/scripts/cmd.js index 91ab1c682..b87a34599 100644 --- a/src-tauri/src/scripts/cmd.js +++ b/src-tauri/src/scripts/cmd.js @@ -83,6 +83,16 @@ function init() { width: 16px; height: 16px; } + .chatappico.refresh { + width: 22px; + height: 22px; + } + #download-markdown-button, + #download-png-button, + #download-pdf-button, + #refresh-page-button { + border: none; + } @media screen and (max-width: 767px) { #download-png-button, #download-pdf-button, #download-html-button { display: none; diff --git a/src-tauri/src/scripts/export.js b/src-tauri/src/scripts/export.js index 6ef2f7b6e..4760901bf 100644 --- a/src-tauri/src/scripts/export.js +++ b/src-tauri/src/scripts/export.js @@ -80,11 +80,12 @@ async function init() { } function removeButtons() { - const downloadButton = document.getElementById("download-png-button"); + const downloadPngButton = document.getElementById("download-png-button"); const downloadPdfButton = document.getElementById("download-pdf-button"); const downloadMdButton = document.getElementById("download-markdown-button"); - if (downloadButton) { - downloadButton.remove(); + const refreshButton = document.getElementById("refresh-page-button"); + if (downloadPngButton) { + downloadPngButton.remove(); } if (downloadPdfButton) { downloadPdfButton.remove(); @@ -92,14 +93,16 @@ async function init() { if (downloadPdfButton) { downloadMdButton.remove(); } + if (refreshButton) { + refreshButton.remove(); + } } function addActionsButtons(actionsArea, TryAgainButton) { - const downloadButton = TryAgainButton.cloneNode(true); // Export markdown const exportMd = TryAgainButton.cloneNode(true); exportMd.id = "download-markdown-button"; - downloadButton.setAttribute("share-ext", "true"); + exportMd.setAttribute("share-ext", "true"); exportMd.title = "Export Markdown"; exportMd.innerHTML = setIcon('md'); @@ -109,25 +112,36 @@ async function init() { actionsArea.appendChild(exportMd); // Generate PNG - downloadButton.id = "download-png-button"; - downloadButton.setAttribute("share-ext", "true"); - downloadButton.title = "Generate PNG"; - downloadButton.innerHTML = setIcon('png'); - downloadButton.onclick = () => { + const downloadPngButton = TryAgainButton.cloneNode(true); + downloadPngButton.id = "download-png-button"; + downloadPngButton.setAttribute("share-ext", "true"); + downloadPngButton.title = "Generate PNG"; + downloadPngButton.innerHTML = setIcon('png'); + downloadPngButton.onclick = () => { downloadThread(); }; - actionsArea.appendChild(downloadButton); + actionsArea.appendChild(downloadPngButton); // Generate PDF const downloadPdfButton = TryAgainButton.cloneNode(true); downloadPdfButton.id = "download-pdf-button"; - downloadButton.setAttribute("share-ext", "true"); + downloadPdfButton.setAttribute("share-ext", "true"); downloadPdfButton.title = "Download PDF"; downloadPdfButton.innerHTML = setIcon('pdf'); downloadPdfButton.onclick = () => { downloadThread({ as: Format.PDF }); }; actionsArea.appendChild(downloadPdfButton); + + // Refresh + const refreshButton = TryAgainButton.cloneNode(true); + refreshButton.id = "refresh-page-button"; + refreshButton.title = "Refresh the Page"; + refreshButton.innerHTML = setIcon('refresh'); + refreshButton.onclick = () => { + window.location.reload(); + }; + actionsArea.appendChild(refreshButton); } async function exportMarkdown() { @@ -275,6 +289,7 @@ async function init() { png: ``, pdf: ``, md: ``, + refresh: ``, }[type]; } } diff --git a/src/view/settings/General.tsx b/src/view/settings/General.tsx index 9a0d63130..e6e0ae586 100644 --- a/src/view/settings/General.tsx +++ b/src/view/settings/General.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { Form, Radio, Switch, Input, Tooltip } from 'antd'; +import { Form, Radio, Switch, Input, Tooltip, Select, Tag } from 'antd'; import { QuestionCircleOutlined } from '@ant-design/icons'; import { platform } from '@tauri-apps/api/os'; @@ -8,9 +8,11 @@ import { DISABLE_AUTO_COMPLETE } from '@/utils'; export default function General() { const [platformInfo, setPlatform] = useState(''); + const [vlist, setVoices] = useState([]); useInit(async () => { setPlatform(await platform()); + setVoices(speechSynthesis.getVoices()); }); return ( @@ -48,6 +50,18 @@ export default function General() { } name="global_shortcut"> + + + ); }