Add chapter skip and 10s seek controls to audio players
Build and Push Docker Image / build-and-push (push) Successful in 5m42s

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5 committed 2026-09-23 11:49:32 -04:00
1 parent 5287b471d0
commit b9f9b97cba
3 files changed
+59

No files matched your search

+18
View File
@@ -80,6 +80,22 @@ export function useAudio(readerBookAbbrev, readerChapter) {
}
};
const handleSeekAudio = (deltaSeconds) => {
if (!audioRef.current) return;
const el = audioRef.current;
const duration = Number.isFinite(el.duration) ? el.duration : Infinity;
el.currentTime = Math.min(Math.max(el.currentTime + deltaSeconds, 0), duration);
};
const handleSkipBookChapter = () => {
const nextChapter = audioStateRef.current.chapter + 1;
if (nextChapter > audioStateRef.current.total) return;
audioModeRef.current = 'book';
playAudioChapter(audioBookRef.current, nextChapter, audioNarratorRef.current).catch(() =>
setAudioState({ status: 'error', chapter: 0, total: 0 }),
);
};
const handlePlayReaderAudio = async () => {
audioModeRef.current = 'reader';
try {
@@ -131,6 +147,8 @@ export function useAudio(readerBookAbbrev, readerChapter) {
handlePlayBookAudio,
handleStopBookAudio,
handleToggleBookAudioPause,
handleSkipBookChapter,
handleSeekAudio,
readerAudioState,
handlePlayReaderAudio,
handleToggleReaderAudioPause,
+27
View File
@@ -31,6 +31,8 @@ export default function HomePage() {
handlePlayBookAudio,
handleStopBookAudio,
handleToggleBookAudioPause,
handleSkipBookChapter,
handleSeekAudio,
} = useApp();
const [homeSearch, setHomeSearch] = useState('');
const [homeSort, setHomeSort] = useState(() => {
@@ -266,6 +268,22 @@ export default function HomePage() {
</select>
{audioState.status === 'playing' || audioState.status === 'paused' ? (
<>
<button
type="button"
onClick={() => handleSeekAudio(-10)}
title="Rewind 10 seconds"
className="rounded-xl border border-slate-300 bg-white px-3 py-1.5 text-sm font-medium text-slate-700 shadow-sm hover:bg-slate-50"
>
-10s
</button>
<button
type="button"
onClick={() => handleSeekAudio(10)}
title="Fast-forward 10 seconds"
className="rounded-xl border border-slate-300 bg-white px-3 py-1.5 text-sm font-medium text-slate-700 shadow-sm hover:bg-slate-50"
>
+10s
</button>
<button
type="button"
onClick={handleToggleBookAudioPause}
@@ -273,6 +291,15 @@ export default function HomePage() {
>
{audioState.status === 'paused' ? 'Resume' : 'Pause'}
</button>
<button
type="button"
onClick={handleSkipBookChapter}
disabled={audioState.chapter >= audioState.total}
title="Skip to next chapter"
className="rounded-xl border border-slate-300 bg-white px-3 py-1.5 text-sm font-medium text-slate-700 shadow-sm hover:bg-slate-50 disabled:opacity-60"
>
Next chapter
</button>
<button
type="button"
onClick={handleStopBookAudio}
+14
View File
@@ -47,6 +47,7 @@ export default function ReaderPage() {
handlePlayReaderAudio,
handleToggleReaderAudioPause,
handleStopBookAudio,
handleSeekAudio,
setReaderCrossRefs,
readerInkByPage,
updateReaderPageInk,
@@ -520,10 +521,23 @@ export default function ReaderPage() {
</select>
{readerAudioState.status === 'playing' || readerAudioState.status === 'paused' ? (
<>
<button type="button" onClick={() => handleSeekAudio(-10)} title="Rewind 10 seconds"
className="rounded-xl border border-slate-300 bg-white px-3 py-1.5 text-sm font-medium text-slate-700 shadow-sm hover:bg-slate-50">
-10s
</button>
<button type="button" onClick={() => handleSeekAudio(10)} title="Fast-forward 10 seconds"
className="rounded-xl border border-slate-300 bg-white px-3 py-1.5 text-sm font-medium text-slate-700 shadow-sm hover:bg-slate-50">
+10s
</button>
<button type="button" onClick={handleToggleReaderAudioPause}
className="rounded-xl bg-sky-600 px-3 py-1.5 text-sm font-medium text-white shadow-sm hover:bg-sky-500">
{readerAudioState.status === 'paused' ? 'Resume' : 'Pause'}
</button>
<button type="button" onClick={readerGoToNextChapter} disabled={readerChapter >= readerTotalChapters}
title="Skip to next chapter"
className="rounded-xl border border-slate-300 bg-white px-3 py-1.5 text-sm font-medium text-slate-700 shadow-sm hover:bg-slate-50 disabled:opacity-60">
Next chapter
</button>
<button type="button" onClick={handleStopBookAudio}
className="rounded-xl border border-slate-300 bg-white px-3 py-1.5 text-sm font-medium text-slate-700 shadow-sm hover:bg-slate-50">
Stop