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 { IoIosList as TOCIcon } from 'react-icons/io'; import { PiNotePencil as NoteIcon } from 'react-icons/pi'; import { RxSlider as SliderIcon } from 'react-icons/rx'; import { RiFontFamily as FontIcon } from 'react-icons/ri'; import { MdOutlineHeadphones as TTSIcon } from 'react-icons/md'; import { TbBoxMargin } from 'react-icons/tb'; import { RxLineHeight } from 'react-icons/rx'; import { useEnv } from '@/context/EnvContext'; import { useReaderStore } from '@/store/readerStore'; import { useSidebarStore } from '@/store/sidebarStore'; import { useTranslation } from '@/hooks/useTranslation'; import { useResponsiveSize } from '@/hooks/useResponsiveSize'; import { eventDispatcher } from '@/utils/event'; import { saveViewSettings } from '../utils/viewSettingsHelper'; import { PageInfo } from '@/types/book'; import { getStyles } from '@/utils/style'; import Button from '@/components/Button'; import Slider from '@/components/Slider'; interface FooterBarProps { bookKey: string; bookFormat: string; section?: PageInfo; pageinfo?: PageInfo; isHoveredAnim: boolean; } const FooterBar: React.FC = ({ bookKey, bookFormat, section, pageinfo, isHoveredAnim, }) => { const _ = useTranslation(); const { envConfig, appService } = useEnv(); const { hoveredBookKey, setHoveredBookKey, getView, getProgress, getViewSettings } = useReaderStore(); const { isSideBarVisible, setSideBarVisible } = useSidebarStore(); const [actionTab, setActionTab] = React.useState(''); const sliderHeight = useResponsiveSize(28); const tocIconSize = useResponsiveSize(23); const fontIconSize = useResponsiveSize(18); const marginIconSize = useResponsiveSize(20); const view = getView(bookKey); const progress = getProgress(bookKey); const viewSettings = getViewSettings(bookKey); const handleProgressChange = (value: number) => { view?.goToFraction(value / 100.0); }; const handleFontSizeChange = (value: number) => { saveViewSettings(envConfig, bookKey, 'defaultFontSize', value); view?.renderer.setStyles?.(getStyles(viewSettings!)); }; const handleMarginChange = (value: number) => { const marginPx = Math.round((value / 100) * 88); const gapPercent = Math.round((value / 100) * 10); saveViewSettings(envConfig, bookKey, 'marginPx', marginPx); saveViewSettings(envConfig, bookKey, 'gapPercent', gapPercent); view?.renderer.setAttribute('margin', `${marginPx}px`); view?.renderer.setAttribute('gap', `${gapPercent}%`); if (viewSettings?.scrolled) { view?.renderer.setAttribute('flow', 'scrolled'); } }; const handleLineHeightChange = (value: number) => { saveViewSettings(envConfig, bookKey, 'lineHeight', value / 10); view?.renderer.setStyles?.(getStyles(viewSettings!)); }; const handleGoPrev = () => { view?.goLeft(); }; const handleGoNext = () => { view?.goRight(); }; const handleGoBack = () => { view?.history.back(); }; const handleGoForward = () => { view?.history.forward(); }; const handleSpeakText = async () => { if (!view || !progress) return; const { range } = progress; if (eventDispatcher.dispatchSync('tts-is-speaking')) { eventDispatcher.dispatch('tts-stop', { bookKey }); } else { eventDispatcher.dispatch('tts-speak', { bookKey, range }); } }; const handleSetActionTab = (tab: string) => { console.log('handleSetActionTab', tab); setActionTab(actionTab === tab ? '' : tab); if (tab === 'tts') { setHoveredBookKey(''); handleSpeakText(); } else if (tab === 'toc') { setHoveredBookKey(''); if (viewSettings) { viewSettings.sideBarTab = 'toc'; } setSideBarVisible(true); } else if (tab === 'note') { setHoveredBookKey(''); setSideBarVisible(true); if (viewSettings) { viewSettings.sideBarTab = 'annotations'; } } }; const getMarginProgressValue = (marginPx: number, gapPercent: number) => { return (marginPx / 88 + gapPercent / 10) * 50; }; const isVisible = hoveredBookKey === bookKey; const progressInfo = bookFormat === 'PDF' ? section : pageinfo; const progressValid = !!progressInfo; const progressFraction = progressValid ? ((progressInfo!.next ?? progressInfo!.current) + 1) / progressInfo!.total : 0; return ( <>