forked from akai/readest
translator: lazy load translation observer (#1282)
This commit is contained in:
@@ -9,11 +9,11 @@ import { getLocale } from '@/utils/misc';
|
||||
|
||||
export function useTextTranslation(bookKey: string, view: FoliateView | HTMLElement | null) {
|
||||
const { getViewSettings } = useReaderStore();
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
const viewSettings = getViewSettings(bookKey);
|
||||
|
||||
const enabled = useRef(viewSettings.translationEnabled);
|
||||
const [provider, setProvider] = useState(viewSettings.translationProvider);
|
||||
const [targetLang, setTargetLang] = useState(viewSettings.translateTargetLang);
|
||||
const enabled = useRef(viewSettings?.translationEnabled);
|
||||
const [provider, setProvider] = useState(viewSettings?.translationProvider);
|
||||
const [targetLang, setTargetLang] = useState(viewSettings?.translateTargetLang);
|
||||
|
||||
const { translate } = useTranslator({
|
||||
provider,
|
||||
@@ -42,6 +42,16 @@ export function useTextTranslation(bookKey: string, view: FoliateView | HTMLElem
|
||||
translateRef.current = translate;
|
||||
}, [translate]);
|
||||
|
||||
const observeTextNodes = () => {
|
||||
if (!view || !enabled.current) return;
|
||||
const observer = createTranslationObserver();
|
||||
observerRef.current = observer;
|
||||
const nodes = walkTextNodes(view);
|
||||
console.log('Observing text nodes for translation:', nodes.length);
|
||||
allTextNodes.current = nodes;
|
||||
nodes.forEach((el) => observer.observe(el));
|
||||
};
|
||||
|
||||
const updateTranslation = () => {
|
||||
translatedElements.current.forEach((element) => {
|
||||
const translationTargets = element.querySelectorAll('.translation-target');
|
||||
@@ -49,7 +59,7 @@ export function useTextTranslation(bookKey: string, view: FoliateView | HTMLElem
|
||||
});
|
||||
|
||||
translatedElements.current = [];
|
||||
if (viewSettings.translationEnabled && view) {
|
||||
if (viewSettings?.translationEnabled && view) {
|
||||
recreateTranslationObserver();
|
||||
}
|
||||
};
|
||||
@@ -168,7 +178,7 @@ export function useTextTranslation(bookKey: string, view: FoliateView | HTMLElem
|
||||
if (enabledChanged) {
|
||||
toggleTranslationVisibility(viewSettings.translationEnabled);
|
||||
if (enabled.current) {
|
||||
recreateTranslationObserver();
|
||||
observeTextNodes();
|
||||
}
|
||||
} else if (providerChanged || targetLangChanged) {
|
||||
updateTranslation();
|
||||
@@ -177,15 +187,7 @@ export function useTextTranslation(bookKey: string, view: FoliateView | HTMLElem
|
||||
}, [bookKey, viewSettings, provider, targetLang]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!view) return;
|
||||
|
||||
const observeTextNodes = () => {
|
||||
const observer = createTranslationObserver();
|
||||
observerRef.current = observer;
|
||||
const nodes = walkTextNodes(view);
|
||||
allTextNodes.current = nodes;
|
||||
nodes.forEach((el) => observer.observe(el));
|
||||
};
|
||||
if (!view || !enabled.current) return;
|
||||
|
||||
if ('renderer' in view) {
|
||||
view.addEventListener('load', observeTextNodes);
|
||||
|
||||
@@ -401,7 +401,7 @@ export abstract class BaseAppService implements AppService {
|
||||
}
|
||||
} catch (error) {
|
||||
// don't throw error here since some books may not have cover images at all
|
||||
console.log('Failed to download cover file:', error);
|
||||
console.log(`Failed to download cover file for book: '${book.title}'`, error);
|
||||
}
|
||||
|
||||
if (needDownBook) {
|
||||
|
||||
@@ -86,6 +86,7 @@ export class TTSController extends EventTarget {
|
||||
.replace(/[–—]/g, ',')
|
||||
.replace('<break/>', ' ')
|
||||
.replace(/\.{3,}/g, ' ')
|
||||
.replace(/……/g, ' ')
|
||||
.replace(/·/g, ' ');
|
||||
|
||||
return ssml;
|
||||
|
||||
@@ -59,7 +59,7 @@ export const updateToc = (bookDoc: BookDoc, items: TOCItem[], sections: SectionI
|
||||
map[section.id] = section;
|
||||
return map;
|
||||
}, {});
|
||||
updateTocData(bookDoc, items, sectionsMap);
|
||||
updateTocData(bookDoc, items, sections, sectionsMap);
|
||||
items.sort((a, b) => {
|
||||
if (a.location && b.location) {
|
||||
return a.location.current - b.location.current;
|
||||
@@ -71,25 +71,26 @@ export const updateToc = (bookDoc: BookDoc, items: TOCItem[], sections: SectionI
|
||||
const updateTocData = (
|
||||
bookDoc: BookDoc,
|
||||
items: TOCItem[],
|
||||
sections: { [id: string]: SectionItem },
|
||||
sections: SectionItem[],
|
||||
sectionsMap: { [id: string]: SectionItem },
|
||||
index = 0,
|
||||
): number => {
|
||||
items.forEach((item) => {
|
||||
item.id ??= index++;
|
||||
if (item.href) {
|
||||
const id = bookDoc.splitTOCHref(item.href)[0]!;
|
||||
const section = sections[id];
|
||||
const section = sectionsMap[id];
|
||||
if (section) {
|
||||
item.cfi = section.cfi;
|
||||
// Add location only when toc item is at the same level as the section
|
||||
// otherwise the location will not be accurate
|
||||
if (id === item.href) {
|
||||
if (id === item.href || items.length <= sections.length) {
|
||||
item.location = section.location;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (item.subitems) {
|
||||
index = updateTocData(bookDoc, item.subitems, sections, index);
|
||||
index = updateTocData(bookDoc, item.subitems, sections, sectionsMap, index);
|
||||
}
|
||||
});
|
||||
return index;
|
||||
|
||||
Reference in New Issue
Block a user