From 35735cd9315758ae78d59b0514111ca3a3e5e9fc Mon Sep 17 00:00:00 2001 From: Huang Xin Date: Mon, 26 May 2025 22:03:43 +0800 Subject: [PATCH] fix: skip speech when the text is empty at the end of some chapters, closes #1231 (#1243) --- apps/readest-app/src/services/tts/TTSController.ts | 8 +++++++- apps/readest-app/src/types/view.ts | 4 ++-- apps/readest-app/src/utils/style.ts | 4 ++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/apps/readest-app/src/services/tts/TTSController.ts b/apps/readest-app/src/services/tts/TTSController.ts index 689a23ab..2e313fd8 100644 --- a/apps/readest-app/src/services/tts/TTSController.ts +++ b/apps/readest-app/src/services/tts/TTSController.ts @@ -1,5 +1,6 @@ import { FoliateView, TTSGranularity } from '@/types/view'; import { TTSClient, TTSMessageCode, TTSVoice } from './TTSClient'; +import { parseSSMLMarks } from '@/utils/ssml'; import { WebSpeechClient } from './WebSpeechClient'; import { EdgeTTSClient } from './EdgeTTSClient'; import { TTSUtils } from './TTSUtils'; @@ -106,7 +107,7 @@ export class TTSController extends EventTarget { // FIXME: in case we are at the end of the book, need a better way to handle this if (this.#nossmlCnt < 10 && this.state === 'playing') { resolve(); - await this.view.next(1); + await this.view.next(); await this.forward(); } return; @@ -114,6 +115,11 @@ export class TTSController extends EventTarget { this.#nossmlCnt = 0; } + const { plainText, marks } = parseSSMLMarks(ssml); + if (!plainText || marks.length === 0) { + resolve(); + return await this.forward(); + } const iter = await this.ttsClient.speak(ssml, signal); let lastCode: TTSMessageCode = 'boundary'; for await (const { code, mark } of iter) { diff --git a/apps/readest-app/src/types/view.ts b/apps/readest-app/src/types/view.ts index dd6f1486..dfaa67c6 100644 --- a/apps/readest-app/src/types/view.ts +++ b/apps/readest-app/src/types/view.ts @@ -10,8 +10,8 @@ export interface FoliateView extends HTMLElement { init: (options: { lastLocation: string }) => void; goTo: (href: string) => void; goToFraction: (fraction: number) => void; - prev: (distance: number) => void; - next: (distance: number) => void; + prev: (distance?: number) => void; + next: (distance?: number) => void; goLeft: () => void; goRight: () => void; getCFI: (index: number, range: Range) => string; diff --git a/apps/readest-app/src/utils/style.ts b/apps/readest-app/src/utils/style.ts index e32d06b8..aeecc629 100644 --- a/apps/readest-app/src/utils/style.ts +++ b/apps/readest-app/src/utils/style.ts @@ -248,6 +248,10 @@ const getLayoutStyles = ( hanging-punctuation: allow-end last; widows: 2; } + p:has(> img:only-child) { + text-indent: unset !important; + text-align: unset !important; + } p, div { ${vertical ? `margin-left: ${paragraphMargin}em ${overrideLayout ? '!important' : ''};` : ''} ${vertical ? `margin-right: ${paragraphMargin}em ${overrideLayout ? '!important' : ''};` : ''}