diff --git a/apps/main/src/tipc/reader.ts b/apps/main/src/tipc/reader.ts index 06b04b4760..aa98d7d5d6 100644 --- a/apps/main/src/tipc/reader.ts +++ b/apps/main/src/tipc/reader.ts @@ -29,14 +29,32 @@ export const readerRoute = { .input<{ id: string text: string + voice: string }>() - .action(async ({ input }) => { - const { id, text } = input - + .action(async ({ input, context: { sender } }) => { + const { id, text, voice } = input if (!text) { return null } + const window = BrowserWindow.fromWebContents(sender) + if (!window) return + + // It's ok to set voice every time, because it will be cached by msedge-tts + await tts + .setMetadata(voice, OUTPUT_FORMAT.WEBM_24KHZ_16BIT_MONO_OPUS) + .catch((error: unknown) => { + console.error("Failed to set voice", error) + if (error instanceof Error) { + return callWindowExpose(window).toast.error(error.message, { + duration: 1000, + }) + } + return callWindowExpose(window).toast.error("Failed to set voice", { + duration: 1000, + }) + }) + const filePath = path.join(app.getPath("userData"), `${id}.webm`) if (fs.existsSync(filePath)) { return filePath @@ -62,25 +80,6 @@ export const readerRoute = { } }), - setVoice: t.procedure.input().action(async ({ input, context: { sender } }) => { - const window = BrowserWindow.fromWebContents(sender) - if (!window) return - - await tts - .setMetadata(input, OUTPUT_FORMAT.WEBM_24KHZ_16BIT_MONO_OPUS) - .catch((error: unknown) => { - console.error("Failed to set voice", error) - if (error instanceof Error) { - return callWindowExpose(window).toast.error(error.message, { - duration: 1000, - }) - } - return callWindowExpose(window).toast.error("Failed to set voice", { - duration: 1000, - }) - }) - }), - detectCodeStringLanguage: t.procedure .input<{ codeString: string }>() .action(async ({ input }) => { diff --git a/apps/mobile/src/hooks/useIsRouteOnlyOne.ts b/apps/mobile/src/hooks/useIsRouteOnlyOne.ts index 4f50c82524..a6d496e6ea 100644 --- a/apps/mobile/src/hooks/useIsRouteOnlyOne.ts +++ b/apps/mobile/src/hooks/useIsRouteOnlyOne.ts @@ -4,7 +4,7 @@ export const useIsRouteOnlyOne = () => { const navigation = useNavigation() const state = navigation.getState() - const routeOnlyOne = state.routes.length === 1 + const routeOnlyOne = state?.routes.length === 1 return routeOnlyOne } diff --git a/apps/renderer/src/modules/entry-content/actions/electron-actions.tsx b/apps/renderer/src/modules/entry-content/actions/electron-actions.tsx index f3bc98f6aa..ea90ed5e02 100644 --- a/apps/renderer/src/modules/entry-content/actions/electron-actions.tsx +++ b/apps/renderer/src/modules/entry-content/actions/electron-actions.tsx @@ -14,6 +14,7 @@ import { ReadabilityStatus, useEntryInReadabilityStatus, } from "~/atoms/readability" +import { useGeneralSettingKey } from "~/atoms/settings/general" import { shortcuts } from "~/constants/shortcuts" import { useEntryReadabilityToggle } from "~/hooks/biz/useEntryActions" import { tipcClient } from "~/lib/client" @@ -50,6 +51,7 @@ export const ElectronAdditionActions = IN_ELECTRON }) const [ttsLoading, setTtsLoading] = useState(false) + const voice = useGeneralSettingKey("voice") if (!populatedEntry) return null @@ -70,7 +72,8 @@ export const ElectronAdditionActions = IN_ELECTRON } else { const filePath = await tipcClient?.tts({ id: populatedEntry.entries.id, - text: (await parseHtml(populatedEntry.entries.content)).toText(), + text: parseHtml(populatedEntry.entries.content).toText(), + voice, }) if (filePath) { AudioPlayer.mount({ diff --git a/apps/renderer/src/providers/setting-sync.tsx b/apps/renderer/src/providers/setting-sync.tsx index 86bcd54a64..e7a24035cd 100644 --- a/apps/renderer/src/providers/setting-sync.tsx +++ b/apps/renderer/src/providers/setting-sync.tsx @@ -75,12 +75,7 @@ const useLanguageSync = () => { }, [language]) } const useGeneralSettingSync = () => { - const voice = useGeneralSettingKey("voice") - useEffect(() => { - if (voice) { - tipcClient?.setVoice(voice) - } - }, [voice]) + useGeneralSettingKey("voice") } export const SettingSync = () => {