From 0a03da7ecbcb56268884881ee2a33995bbccc0de Mon Sep 17 00:00:00 2001 From: WittF Date: Sat, 25 Oct 2025 02:49:43 +0000 Subject: [PATCH] feat(music player): add play once mode to stop after track ends (#2992) --- public/locales/de-DE/application.json | 1 + public/locales/en-US/application.json | 1 + public/locales/es-ES/application.json | 1 + public/locales/fr-FR/application.json | 1 + public/locales/it-IT/application.json | 1 + public/locales/ja-JP/application.json | 1 + public/locales/ko-KR/application.json | 1 + public/locales/pt-BR/application.json | 1 + public/locales/ru-RU/application.json | 1 + public/locales/zh-CN/application.json | 1 + public/locales/zh-TW/application.json | 1 + src/component/Icons/ArrowRepeatOff.tsx | 10 ++++++++++ .../Viewers/MusicPlayer/MusicPlayer.tsx | 17 ++++++++--------- .../Viewers/MusicPlayer/PlayerPopup.tsx | 2 ++ .../Viewers/MusicPlayer/RepeatModePopover.tsx | 10 ++++++++++ 15 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 src/component/Icons/ArrowRepeatOff.tsx diff --git a/public/locales/de-DE/application.json b/public/locales/de-DE/application.json index d83a385..84c4860 100644 --- a/public/locales/de-DE/application.json +++ b/public/locales/de-DE/application.json @@ -400,6 +400,7 @@ "listRepeat": "Liste wiederholen", "singleRepeat": "Einzeln wiederholen", "shuffle": "Zufallswiedergabe", + "playOnce": "Einmal abspielen", "playbackSpeed": "Wiedergabegeschwindigkeit", "searchResult": "Suchergebnis", "preparingBathDownload": "Batch-Download wird vorbereitet...", diff --git a/public/locales/en-US/application.json b/public/locales/en-US/application.json index 99bf246..0224bc6 100644 --- a/public/locales/en-US/application.json +++ b/public/locales/en-US/application.json @@ -365,6 +365,7 @@ "listRepeat": "List Repeat", "singleRepeat": "Single Repeat", "shuffle": "Shuffle", + "playOnce": "Play Once", "playbackSpeed": "Playback Speed", "searchResult": "Search Results", "preparingBathDownload": "Preparing batch download...", diff --git a/public/locales/es-ES/application.json b/public/locales/es-ES/application.json index f42bdfa..a933a45 100644 --- a/public/locales/es-ES/application.json +++ b/public/locales/es-ES/application.json @@ -400,6 +400,7 @@ "listRepeat": "Repetir lista", "singleRepeat": "Repetir uno", "shuffle": "Aleatorio", + "playOnce": "Reproducir una vez", "playbackSpeed": "Velocidad de reproducción", "searchResult": "Resultados de búsqueda", "preparingBathDownload": "Preparando descarga por lotes...", diff --git a/public/locales/fr-FR/application.json b/public/locales/fr-FR/application.json index b2d1091..85e1cb9 100644 --- a/public/locales/fr-FR/application.json +++ b/public/locales/fr-FR/application.json @@ -400,6 +400,7 @@ "listRepeat": "Répétition de liste", "singleRepeat": "Répétition unique", "shuffle": "Aléatoire", + "playOnce": "Lecture unique", "playbackSpeed": "Vitesse de lecture", "searchResult": "Résultats de recherche", "preparingBathDownload": "Préparation du téléchargement par lot...", diff --git a/public/locales/it-IT/application.json b/public/locales/it-IT/application.json index f386020..e44f4c7 100644 --- a/public/locales/it-IT/application.json +++ b/public/locales/it-IT/application.json @@ -400,6 +400,7 @@ "listRepeat": "Ripetizione lista", "singleRepeat": "Ripetizione singola", "shuffle": "Casuale", + "playOnce": "Riproduci una volta", "playbackSpeed": "Velocità riproduzione", "searchResult": "Risultati ricerca", "preparingBathDownload": "Preparazione download in lotti...", diff --git a/public/locales/ja-JP/application.json b/public/locales/ja-JP/application.json index be4cbc6..8acbb63 100644 --- a/public/locales/ja-JP/application.json +++ b/public/locales/ja-JP/application.json @@ -365,6 +365,7 @@ "listRepeat": "リストリピート", "singleRepeat": "シングルリピート", "shuffle": "シャッフル", + "playOnce": "一回再生", "playbackSpeed": "再生速度", "searchResult": "検索結果", "preparingBathDownload": "ダウンロード準備中...", diff --git a/public/locales/ko-KR/application.json b/public/locales/ko-KR/application.json index 02de94d..a029eb5 100644 --- a/public/locales/ko-KR/application.json +++ b/public/locales/ko-KR/application.json @@ -400,6 +400,7 @@ "listRepeat": "목록 반복", "singleRepeat": "한 곡 반복", "shuffle": "무작위 재생", + "playOnce": "한 번 재생", "playbackSpeed": "재생 속도", "searchResult": "검색 결과", "preparingBathDownload": "일괄 다운로드 준비 중...", diff --git a/public/locales/pt-BR/application.json b/public/locales/pt-BR/application.json index 8fbc7c4..d50855a 100644 --- a/public/locales/pt-BR/application.json +++ b/public/locales/pt-BR/application.json @@ -400,6 +400,7 @@ "listRepeat": "Repetir lista", "singleRepeat": "Repetir única", "shuffle": "Aleatório", + "playOnce": "Reproduzir uma vez", "playbackSpeed": "Velocidade de reprodução", "searchResult": "Resultados da busca", "preparingBathDownload": "Preparando download em lote...", diff --git a/public/locales/ru-RU/application.json b/public/locales/ru-RU/application.json index db44376..8c48f2b 100644 --- a/public/locales/ru-RU/application.json +++ b/public/locales/ru-RU/application.json @@ -400,6 +400,7 @@ "listRepeat": "Повтор списка", "singleRepeat": "Повтор трека", "shuffle": "Случайное воспроизведение", + "playOnce": "Воспроизвести один раз", "playbackSpeed": "Скорость воспроизведения", "searchResult": "Результаты поиска", "preparingBathDownload": "Подготовка пакетной загрузки...", diff --git a/public/locales/zh-CN/application.json b/public/locales/zh-CN/application.json index e988324..e3316fb 100644 --- a/public/locales/zh-CN/application.json +++ b/public/locales/zh-CN/application.json @@ -365,6 +365,7 @@ "listRepeat": "列表循环", "singleRepeat": "单曲循环", "shuffle": "随机播放", + "playOnce": "单次播放", "playbackSpeed": "播放速度", "searchResult": "搜索结果", "preparingBathDownload": "正在准备打包下载...", diff --git a/public/locales/zh-TW/application.json b/public/locales/zh-TW/application.json index 9400c03..91713de 100644 --- a/public/locales/zh-TW/application.json +++ b/public/locales/zh-TW/application.json @@ -365,6 +365,7 @@ "listRepeat": "清單循環", "singleRepeat": "單曲循環", "shuffle": "隨機播放", + "playOnce": "單次播放", "playbackSpeed": "播放速度", "searchResult": "搜尋結果", "preparingBathDownload": "正在準備打包下載...", diff --git a/src/component/Icons/ArrowRepeatOff.tsx b/src/component/Icons/ArrowRepeatOff.tsx new file mode 100644 index 0000000..a11efbb --- /dev/null +++ b/src/component/Icons/ArrowRepeatOff.tsx @@ -0,0 +1,10 @@ +import { SvgIcon, SvgIconProps } from "@mui/material"; + +export default function ArrowRepeatOff(props: SvgIconProps) { + return ( + + + + + ); +} diff --git a/src/component/Viewers/MusicPlayer/MusicPlayer.tsx b/src/component/Viewers/MusicPlayer/MusicPlayer.tsx index ecd2582..7a08599 100644 --- a/src/component/Viewers/MusicPlayer/MusicPlayer.tsx +++ b/src/component/Viewers/MusicPlayer/MusicPlayer.tsx @@ -12,6 +12,7 @@ export const LoopMode = { list_repeat: 0, single_repeat: 1, shuffle: 2, + play_once: 3, }; const MusicPlayer = () => { @@ -82,6 +83,7 @@ const MusicPlayer = () => { switch (loopMode) { case LoopMode.list_repeat: + case LoopMode.play_once: if (isNext) { playIndex(((index ?? 0) + 1) % playerState?.files.length); } else { @@ -106,8 +108,10 @@ const MusicPlayer = () => { ); const onPlayEnded = useCallback(() => { - loopProceed(true); - }, []); + if (loopMode !== LoopMode.play_once) { + loopProceed(true); + } + }, [loopMode, loopProceed]); const timeUpdate = useCallback(() => { setCurrent(Math.floor(audio.current?.currentTime || 0)); @@ -152,7 +156,7 @@ const MusicPlayer = () => { }, []); const toggleLoopMode = useCallback(() => { - setLoopMode((loopMode) => (loopMode + 1) % 3); + setLoopMode((loopMode) => (loopMode + 1) % 4); }, []); const setLoopModeHandler = useCallback((mode: number) => { @@ -168,12 +172,7 @@ const MusicPlayer = () => { return ( <> -