TTS: add paused seeking

This commit is contained in:
John Factotum
2023-09-28 23:42:33 +08:00
parent 7ebf99b2cd
commit 87605c5235
+20 -7
View File
@@ -427,6 +427,7 @@ export class View extends HTMLElement {
return this.#ssml return this.#ssml
} }
#getSpeechMarkElement(ssml, mark) { #getSpeechMarkElement(ssml, mark) {
if (!mark) return null
return ssml.querySelector(`mark[name="${CSS.escape(mark)}"`) return ssml.querySelector(`mark[name="${CSS.escape(mark)}"`)
} }
#speakFromNode(getNode) { #speakFromNode(getNode) {
@@ -448,17 +449,29 @@ export class View extends HTMLElement {
return this.#speakFromNode(mark ? ssml => return this.#speakFromNode(mark ? ssml =>
this.#getSpeechMarkElement(ssml, mark) : null) this.#getSpeechMarkElement(ssml, mark) : null)
} }
static #seekSpeechNode(ssml, from, dir) {
const walker = ssml.createTreeWalker(ssml.documentElement,
NodeFilter.SHOW_ELEMENT, { acceptNode: node => node.localName === 'p'
? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT })
if (from) walker.currentNode = from
return dir < 1
? (walker.previousNode(), walker.previousNode())
: walker.nextNode()
}
seekSpeech(dir) { seekSpeech(dir) {
return this.#speakFromNode(ssml => { return this.#speakFromNode(ssml => {
const walker = ssml.createTreeWalker(ssml.documentElement, const from = this.#getSpeechMarkElement(ssml, this.#lastSpeechMark)
NodeFilter.SHOW_ELEMENT, { acceptNode: node => node.localName === 'p' return View.#seekSpeechNode(ssml, from, dir)
? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT })
walker.currentNode = this.#getSpeechMarkElement(ssml, this.#lastSpeechMark)
return dir < 1
? (walker.previousNode(), walker.previousNode())
: walker.nextNode()
}) })
} }
seekSpeechPaused(dir) {
const ssml = this.#ssml
const from = this.#getSpeechMarkElement(ssml, this.#lastSpeechMark)
const node = View.#seekSpeechNode(ssml, from, dir)
const mark = node?.querySelector('mark')
const name = mark?.getAttribute('name')
this.hightlightSpeechMark(name || '0')
}
getSpeechMarkBefore(range) { getSpeechMarkBefore(range) {
if (range) for (const [name, range_] of this.#speechRanges.entries()) if (range) for (const [name, range_] of this.#speechRanges.entries())
if (range.compareBoundaryPoints(Range.START_TO_START, range_) <= 0) if (range.compareBoundaryPoints(Range.START_TO_START, range_) <= 0)