diff --git a/apps/readest-app/src/app/reader/components/FooterBar.tsx b/apps/readest-app/src/app/reader/components/FooterBar.tsx index 5052487b..ad809153 100644 --- a/apps/readest-app/src/app/reader/components/FooterBar.tsx +++ b/apps/readest-app/src/app/reader/components/FooterBar.tsx @@ -2,10 +2,14 @@ import React from 'react'; import clsx from 'clsx'; import { RiArrowLeftWideLine, RiArrowRightWideLine } from 'react-icons/ri'; import { RiArrowGoBackLine, RiArrowGoForwardLine } from 'react-icons/ri'; +import { FaHeadphones } from 'react-icons/fa6'; import { useReaderStore } from '@/store/readerStore'; import { useSidebarStore } from '@/store/sidebarStore'; +import { useBookDataStore } from '@/store/bookDataStore'; import { useTranslation } from '@/hooks/useTranslation'; +import { getBookLangCode } from '@/utils/book'; +import { eventDispatcher } from '@/utils/event'; import Button from '@/components/Button'; interface FooterBarProps { @@ -16,9 +20,12 @@ interface FooterBarProps { const FooterBar: React.FC = ({ bookKey, pageinfo, isHoveredAnim }) => { const _ = useTranslation(); - const { hoveredBookKey, setHoveredBookKey, getView } = useReaderStore(); + const { hoveredBookKey, setHoveredBookKey, getView, getProgress } = useReaderStore(); + const { getBookData } = useBookDataStore(); const { isSideBarVisible } = useSidebarStore(); const view = getView(bookKey); + const bookData = getBookData(bookKey); + const progress = getProgress(bookKey); const handleProgressChange = (event: React.ChangeEvent) => { const newProgress = parseInt((event.target as HTMLInputElement).value, 10); @@ -41,6 +48,16 @@ const FooterBar: React.FC = ({ bookKey, pageinfo, isHoveredAnim view?.history.forward(); }; + const handleSpeakText = async () => { + if (!view || !progress) return; + const lang = getBookLangCode(bookData?.bookDoc!.metadata.language); + const granularity = ['zh', 'ja', 'ko'].includes(lang) ? 'sentence' : 'word'; + await view.initTTS(granularity); + const { range } = progress; + const ssml = view.tts.from(range); + eventDispatcher.dispatch('speak', { bookKey, ssml }); + }; + const pageinfoValid = pageinfo && pageinfo.total > 0 && pageinfo.current >= 0; const progressFraction = pageinfoValid ? pageinfo.current / pageinfo.total : 0; return ( @@ -83,6 +100,7 @@ const FooterBar: React.FC = ({ bookKey, pageinfo, isHoveredAnim value={pageinfoValid ? progressFraction * 100 : 0} onChange={(e) => handleProgressChange(e)} /> +