feat(tts): support going previous/next by sentence in bottom TTS bar, closes #1816 (#1967)

This commit is contained in:
Huang Xin
2025-09-05 16:34:30 +08:00
committed by GitHub
parent 64007b1188
commit 5724d2eeec
29 changed files with 230 additions and 43 deletions
@@ -1,17 +1,25 @@
import clsx from 'clsx';
import React from 'react';
import { MdPlayArrow, MdOutlinePause, MdFastRewind, MdFastForward } from 'react-icons/md';
import {
MdPlayArrow,
MdOutlinePause,
MdFastRewind,
MdFastForward,
MdSkipPrevious,
MdSkipNext,
} from 'react-icons/md';
import { Insets } from '@/types/misc';
import { useEnv } from '@/context/EnvContext';
import { useReaderStore } from '@/store/readerStore';
import { useResponsiveSize } from '@/hooks/useResponsiveSize';
import { useTranslation } from '@/hooks/useTranslation';
type TTSBarProps = {
bookKey: string;
isPlaying: boolean;
onTogglePlay: () => void;
onBackward: () => void;
onForward: () => void;
onBackward: (byMark: boolean) => void;
onForward: (byMark: boolean) => void;
gridInsets: Insets;
};
@@ -23,6 +31,7 @@ const TTSBar = ({
onForward,
gridInsets,
}: TTSBarProps) => {
const _ = useTranslation();
const { appService } = useEnv();
const { hoveredBookKey, setHoveredBookKey } = useReaderStore();
const iconSize32 = useResponsiveSize(30);
@@ -44,20 +53,42 @@ const TTSBar = ({
>
<div className='text-base-content flex h-[52px] items-center space-x-2 px-2'>
<button
onClick={onBackward}
onClick={onBackward.bind(null, false)}
className='rounded-full p-1 transition-transform duration-200 hover:scale-105'
title={_('Previous Paragraph')}
aria-label={_('Previous Paragraph')}
>
<MdFastRewind size={iconSize32} />
</button>
<button
onClick={onBackward.bind(null, true)}
className='rounded-full p-1 transition-transform duration-200 hover:scale-105'
title={_('Previous Sentence')}
aria-label={_('Previous Sentence')}
>
<MdSkipPrevious size={iconSize32} />
</button>
<button
onClick={onTogglePlay}
className='rounded-full p-1 transition-transform duration-200 hover:scale-105'
title={isPlaying ? _('Pause') : _('Play')}
aria-label={isPlaying ? _('Pause') : _('Play')}
>
{isPlaying ? <MdOutlinePause size={iconSize48} /> : <MdPlayArrow size={iconSize48} />}
</button>
<button
onClick={onForward}
onClick={onForward.bind(null, true)}
className='rounded-full p-1 transition-transform duration-200 hover:scale-105'
title={_('Next Sentence')}
aria-label={_('Next Sentence')}
>
<MdSkipNext size={iconSize32} />
</button>
<button
onClick={onForward.bind(null, false)}
className='rounded-full p-1 transition-transform duration-200 hover:scale-105'
title={_('Next Paragraph')}
aria-label={_('Next Paragraph')}
>
<MdFastForward size={iconSize32} />
</button>
@@ -260,17 +260,17 @@ const TTSControl: React.FC<TTSControlProps> = ({ bookKey, gridInsets }) => {
}
}, [isPlaying, isPaused]);
const handleBackward = useCallback(async () => {
const handleBackward = useCallback(async (byMark = false) => {
const ttsController = ttsControllerRef.current;
if (ttsController) {
await ttsController.backward();
await ttsController.backward(byMark);
}
}, []);
const handleForward = useCallback(async () => {
const handleForward = useCallback(async (byMark = false) => {
const ttsController = ttsControllerRef.current;
if (ttsController) {
await ttsController.forward();
await ttsController.forward(byMark);
}
}, []);
@@ -237,12 +237,16 @@ const TTSPanel = ({
<button
onClick={onBackward}
className='rounded-full p-1 transition-transform duration-200 hover:scale-105'
title={_('Previous Paragraph')}
aria-label={_('Previous Paragraph')}
>
<MdFastRewind size={iconSize32} />
</button>
<button
onClick={onTogglePlay}
className='rounded-full p-1 transition-transform duration-200 hover:scale-105'
title={isPlaying ? _('Pause') : _('Play')}
aria-label={isPlaying ? _('Pause') : _('Play')}
>
{isPlaying ? (
<MdPauseCircle size={iconSize48} className='fill-primary' />
@@ -253,6 +257,8 @@ const TTSPanel = ({
<button
onClick={onForward}
className='rounded-full p-1 transition-transform duration-200 hover:scale-105'
title={_('Next Paragraph')}
aria-label={_('Next Paragraph')}
>
<MdFastForward size={iconSize32} />
</button>