@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "Отключи ротацията",
|
||||
"timerActive": "Таймерът е активен",
|
||||
"playbackWillPauseIn": "Възпроизвеждането ще спре след ${duration}",
|
||||
"sleepTimerEndOfVideo": "Край на текущото видео",
|
||||
"sleepTimerStopAtHeader": "Спиране при",
|
||||
"sleepTimerDurationHeader": "Таймер",
|
||||
"playbackWillPauseAtEnd": "Възпроизвеждането ще спре в края на това видео",
|
||||
"stillWatching": "Още ли гледате?",
|
||||
"pausingIn": "Пауза след ${seconds}сек",
|
||||
"continueWatching": "Продължи",
|
||||
|
||||
@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "Lås rotation op",
|
||||
"timerActive": "Timer aktiv",
|
||||
"playbackWillPauseIn": "Afspilning pauses om ${duration}",
|
||||
"sleepTimerEndOfVideo": "Slutningen af aktuel video",
|
||||
"sleepTimerStopAtHeader": "Stop ved",
|
||||
"sleepTimerDurationHeader": "Timer",
|
||||
"playbackWillPauseAtEnd": "Afspilning pauses i slutningen af denne video",
|
||||
"stillWatching": "Ser du stadig?",
|
||||
"pausingIn": "Pauser om ${seconds}s",
|
||||
"continueWatching": "Fortsæt",
|
||||
|
||||
@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "Rotation entsperren",
|
||||
"timerActive": "Schlaftimer aktiv",
|
||||
"playbackWillPauseIn": "Wiedergabe wird in ${duration} pausiert",
|
||||
"sleepTimerEndOfVideo": "Ende des aktuellen Videos",
|
||||
"sleepTimerStopAtHeader": "Beenden bei",
|
||||
"sleepTimerDurationHeader": "Timer",
|
||||
"playbackWillPauseAtEnd": "Wiedergabe wird am Ende dieses Videos pausiert",
|
||||
"stillWatching": "Schaust du noch?",
|
||||
"pausingIn": "Pause in ${seconds}s",
|
||||
"continueWatching": "Weiter",
|
||||
|
||||
@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "Unlock rotation",
|
||||
"timerActive": "Timer Active",
|
||||
"playbackWillPauseIn": "Playback will pause in ${duration}",
|
||||
"sleepTimerEndOfVideo": "End of current video",
|
||||
"sleepTimerStopAtHeader": "Stop at",
|
||||
"sleepTimerDurationHeader": "Timer",
|
||||
"playbackWillPauseAtEnd": "Playback will pause at the end of this video",
|
||||
"stillWatching": "Still watching?",
|
||||
"pausingIn": "Pausing in ${seconds}s",
|
||||
"continueWatching": "Continue",
|
||||
|
||||
@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "Desbloquear rotación",
|
||||
"timerActive": "Temporizador Activo",
|
||||
"playbackWillPauseIn": "La reproducción se pausará en ${duration}",
|
||||
"sleepTimerEndOfVideo": "Fin del video actual",
|
||||
"sleepTimerStopAtHeader": "Detener en",
|
||||
"sleepTimerDurationHeader": "Temporizador",
|
||||
"playbackWillPauseAtEnd": "La reproducción se pausará al final de este video",
|
||||
"stillWatching": "¿Sigues viendo?",
|
||||
"pausingIn": "Pausa en ${seconds}s",
|
||||
"continueWatching": "Continuar",
|
||||
|
||||
@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "Déverrouiller la rotation",
|
||||
"timerActive": "Minuterie active",
|
||||
"playbackWillPauseIn": "La lecture sera mise en pause dans ${duration}",
|
||||
"sleepTimerEndOfVideo": "Fin de la vidéo actuelle",
|
||||
"sleepTimerStopAtHeader": "Arrêter à",
|
||||
"sleepTimerDurationHeader": "Minuterie",
|
||||
"playbackWillPauseAtEnd": "La lecture sera mise en pause à la fin de cette vidéo",
|
||||
"stillWatching": "Toujours en train de regarder ?",
|
||||
"pausingIn": "Pause dans ${seconds}s",
|
||||
"continueWatching": "Continuer",
|
||||
|
||||
@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "Sblocca rotazione",
|
||||
"timerActive": "Timer attivo",
|
||||
"playbackWillPauseIn": "La riproduzione si interromperà tra ${duration}",
|
||||
"sleepTimerEndOfVideo": "Fine del video corrente",
|
||||
"sleepTimerStopAtHeader": "Interrompi a",
|
||||
"sleepTimerDurationHeader": "Timer",
|
||||
"playbackWillPauseAtEnd": "La riproduzione si interromperà alla fine di questo video",
|
||||
"stillWatching": "Stai ancora guardando?",
|
||||
"pausingIn": "Pausa tra ${seconds}s",
|
||||
"continueWatching": "Continua",
|
||||
|
||||
@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "回転のロックを解除",
|
||||
"timerActive": "タイマー動作中",
|
||||
"playbackWillPauseIn": "再生は${duration}後に一時停止します",
|
||||
"sleepTimerEndOfVideo": "現在の動画の最後",
|
||||
"sleepTimerStopAtHeader": "停止のタイミング",
|
||||
"sleepTimerDurationHeader": "タイマー",
|
||||
"playbackWillPauseAtEnd": "再生はこの動画の最後に一時停止します",
|
||||
"stillWatching": "まだ視聴中ですか?",
|
||||
"pausingIn": "${seconds}秒後に一時停止",
|
||||
"continueWatching": "続ける",
|
||||
|
||||
@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "회전 잠금 해제",
|
||||
"timerActive": "타이머 활성화됨",
|
||||
"playbackWillPauseIn": "재생이 ${duration} 후에 일시 중지 됩니다",
|
||||
"sleepTimerEndOfVideo": "현재 비디오의 끝",
|
||||
"sleepTimerStopAtHeader": "정지 시점",
|
||||
"sleepTimerDurationHeader": "타이머",
|
||||
"playbackWillPauseAtEnd": "재생이 이 비디오의 끝에서 일시 중지됩니다",
|
||||
"stillWatching": "아직 시청 중이신가요?",
|
||||
"pausingIn": "${seconds}초 후 일시 정지",
|
||||
"continueWatching": "계속",
|
||||
|
||||
@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "Lås opp rotasjon",
|
||||
"timerActive": "Timer aktiv",
|
||||
"playbackWillPauseIn": "Avspilling vil pause om ${duration}",
|
||||
"sleepTimerEndOfVideo": "Slutten av gjeldende video",
|
||||
"sleepTimerStopAtHeader": "Stopp ved",
|
||||
"sleepTimerDurationHeader": "Timer",
|
||||
"playbackWillPauseAtEnd": "Avspilling vil pause på slutten av denne videoen",
|
||||
"stillWatching": "Ser du fortsatt?",
|
||||
"pausingIn": "Pauser om ${seconds}s",
|
||||
"continueWatching": "Fortsett",
|
||||
|
||||
@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "Ontgrendel rotatie",
|
||||
"timerActive": "Timer actief",
|
||||
"playbackWillPauseIn": "Afspelen wordt gepauzeerd over ${duration}",
|
||||
"sleepTimerEndOfVideo": "Einde van huidige video",
|
||||
"sleepTimerStopAtHeader": "Stoppen bij",
|
||||
"sleepTimerDurationHeader": "Timer",
|
||||
"playbackWillPauseAtEnd": "Afspelen wordt gepauzeerd aan het einde van deze video",
|
||||
"stillWatching": "Kijk je nog?",
|
||||
"pausingIn": "Pauze over ${seconds}s",
|
||||
"continueWatching": "Doorgaan",
|
||||
|
||||
@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "Odblokuj obrót",
|
||||
"timerActive": "Wyłącznik aktywny",
|
||||
"playbackWillPauseIn": "Odtwarzanie zatrzyma się za ${duration}",
|
||||
"sleepTimerEndOfVideo": "Koniec bieżącego wideo",
|
||||
"sleepTimerStopAtHeader": "Zatrzymaj na",
|
||||
"sleepTimerDurationHeader": "Minutnik",
|
||||
"playbackWillPauseAtEnd": "Odtwarzanie zatrzyma się na końcu tego wideo",
|
||||
"stillWatching": "Nadal oglądasz?",
|
||||
"pausingIn": "Pauza za ${seconds}s",
|
||||
"continueWatching": "Kontynuuj",
|
||||
|
||||
@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "Destravar rotação",
|
||||
"timerActive": "Timer Ativo",
|
||||
"playbackWillPauseIn": "A reprodução pausará em ${duration}",
|
||||
"sleepTimerEndOfVideo": "Fim do vídeo atual",
|
||||
"sleepTimerStopAtHeader": "Parar em",
|
||||
"sleepTimerDurationHeader": "Timer",
|
||||
"playbackWillPauseAtEnd": "A reprodução pausará no final deste vídeo",
|
||||
"stillWatching": "Ainda assistindo?",
|
||||
"pausingIn": "Pausando em ${seconds}s",
|
||||
"continueWatching": "Continuar",
|
||||
|
||||
@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "Разблокировать поворот",
|
||||
"timerActive": "Таймер активен",
|
||||
"playbackWillPauseIn": "Воспроизведение будет приостановлено через ${duration}",
|
||||
"sleepTimerEndOfVideo": "Конец текущего видео",
|
||||
"sleepTimerStopAtHeader": "Остановить на",
|
||||
"sleepTimerDurationHeader": "Таймер",
|
||||
"playbackWillPauseAtEnd": "Воспроизведение будет приостановлено в конце этого видео",
|
||||
"stillWatching": "Всё ещё смотрите?",
|
||||
"pausingIn": "Пауза через ${seconds}с",
|
||||
"continueWatching": "Продолжить",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/// To regenerate, run: `dart run slang`
|
||||
///
|
||||
/// Locales: 16
|
||||
/// Strings: 18976 (1186 per locale)
|
||||
/// Strings: 19040 (1190 per locale)
|
||||
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint, unused_import
|
||||
|
||||
@@ -565,6 +565,10 @@ class _TranslationsVideoControlsBg extends TranslationsVideoControlsEn {
|
||||
@override String get unlockRotation => 'Отключи ротацията';
|
||||
@override String get timerActive => 'Таймерът е активен';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'Възпроизвеждането ще спре след ${duration}';
|
||||
@override String get sleepTimerEndOfVideo => 'Край на текущото видео';
|
||||
@override String get sleepTimerStopAtHeader => 'Спиране при';
|
||||
@override String get sleepTimerDurationHeader => 'Таймер';
|
||||
@override String get playbackWillPauseAtEnd => 'Възпроизвеждането ще спре в края на това видео';
|
||||
@override String get stillWatching => 'Още ли гледате?';
|
||||
@override String pausingIn({required Object seconds}) => 'Пауза след ${seconds}сек';
|
||||
@override String get continueWatching => 'Продължи';
|
||||
@@ -2194,6 +2198,10 @@ extension on TranslationsBg {
|
||||
'videoControls.unlockRotation' => 'Отключи ротацията',
|
||||
'videoControls.timerActive' => 'Таймерът е активен',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => 'Възпроизвеждането ще спре след ${duration}',
|
||||
'videoControls.sleepTimerEndOfVideo' => 'Край на текущото видео',
|
||||
'videoControls.sleepTimerStopAtHeader' => 'Спиране при',
|
||||
'videoControls.sleepTimerDurationHeader' => 'Таймер',
|
||||
'videoControls.playbackWillPauseAtEnd' => 'Възпроизвеждането ще спре в края на това видео',
|
||||
'videoControls.stillWatching' => 'Още ли гледате?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => 'Пауза след ${seconds}сек',
|
||||
'videoControls.continueWatching' => 'Продължи',
|
||||
@@ -2323,12 +2331,12 @@ extension on TranslationsBg {
|
||||
'mpvConfig.presetSaved' => 'Пресетът е запазен',
|
||||
'mpvConfig.presetLoaded' => 'Пресетът е зареден',
|
||||
'mpvConfig.presetDeleted' => 'Пресетът е изтрит',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => 'Сигурни ли сте, че искате да изтриете този пресет?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||
'dialog.confirmAction' => 'Потвърждение на действие',
|
||||
'profiles.addPlezyProfile' => 'Добави Plezy профил',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => 'Смяна на профил…',
|
||||
'profiles.deleteThisProfileTitle' => 'Да се изтрие ли този профил?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => 'Премахване на ${displayName}. Връзките не се засягат.',
|
||||
@@ -2837,12 +2845,12 @@ extension on TranslationsBg {
|
||||
'externalPlayer.off' => 'Изключено',
|
||||
'externalPlayer.launchFailed' => 'Неуспешно отваряне на външен плеър',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} не е инсталиран',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => 'Пусни във външен плеър',
|
||||
'metadataEdit.editMetadata' => 'Редактирай...',
|
||||
'metadataEdit.screenTitle' => 'Редактиране на метаданни',
|
||||
'metadataEdit.basicInfo' => 'Основна информация',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => 'Обложка',
|
||||
'metadataEdit.advancedSettings' => 'Разширени настройки',
|
||||
'metadataEdit.title' => 'Заглавие',
|
||||
|
||||
@@ -565,6 +565,10 @@ class _TranslationsVideoControlsDa extends TranslationsVideoControlsEn {
|
||||
@override String get unlockRotation => 'Lås rotation op';
|
||||
@override String get timerActive => 'Timer aktiv';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'Afspilning pauses om ${duration}';
|
||||
@override String get sleepTimerEndOfVideo => 'Slutningen af aktuel video';
|
||||
@override String get sleepTimerStopAtHeader => 'Stop ved';
|
||||
@override String get sleepTimerDurationHeader => 'Timer';
|
||||
@override String get playbackWillPauseAtEnd => 'Afspilning pauses i slutningen af denne video';
|
||||
@override String get stillWatching => 'Ser du stadig?';
|
||||
@override String pausingIn({required Object seconds}) => 'Pauser om ${seconds}s';
|
||||
@override String get continueWatching => 'Fortsæt';
|
||||
@@ -2194,6 +2198,10 @@ extension on TranslationsDa {
|
||||
'videoControls.unlockRotation' => 'Lås rotation op',
|
||||
'videoControls.timerActive' => 'Timer aktiv',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => 'Afspilning pauses om ${duration}',
|
||||
'videoControls.sleepTimerEndOfVideo' => 'Slutningen af aktuel video',
|
||||
'videoControls.sleepTimerStopAtHeader' => 'Stop ved',
|
||||
'videoControls.sleepTimerDurationHeader' => 'Timer',
|
||||
'videoControls.playbackWillPauseAtEnd' => 'Afspilning pauses i slutningen af denne video',
|
||||
'videoControls.stillWatching' => 'Ser du stadig?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => 'Pauser om ${seconds}s',
|
||||
'videoControls.continueWatching' => 'Fortsæt',
|
||||
@@ -2323,12 +2331,12 @@ extension on TranslationsDa {
|
||||
'mpvConfig.presetSaved' => 'Forudindstilling gemt',
|
||||
'mpvConfig.presetLoaded' => 'Forudindstilling indlæst',
|
||||
'mpvConfig.presetDeleted' => 'Forudindstilling slettet',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => 'Er du sikker på, at du vil slette denne forudindstilling?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||
'dialog.confirmAction' => 'Bekræft handling',
|
||||
'profiles.addPlezyProfile' => 'Tilføj Plezy-profil',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => 'Skifter profil…',
|
||||
'profiles.deleteThisProfileTitle' => 'Slet denne profil?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => 'Fjern ${displayName}. Forbindelser påvirkes ikke.',
|
||||
@@ -2837,12 +2845,12 @@ extension on TranslationsDa {
|
||||
'externalPlayer.off' => 'Fra',
|
||||
'externalPlayer.launchFailed' => 'Kunne ikke åbne ekstern afspiller',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} er ikke installeret',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => 'Afspil i ekstern afspiller',
|
||||
'metadataEdit.editMetadata' => 'Redigér...',
|
||||
'metadataEdit.screenTitle' => 'Redigér metadata',
|
||||
'metadataEdit.basicInfo' => 'Grundlæggende info',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => 'Grafik',
|
||||
'metadataEdit.advancedSettings' => 'Avancerede indstillinger',
|
||||
'metadataEdit.title' => 'Titel',
|
||||
|
||||
@@ -565,6 +565,10 @@ class _TranslationsVideoControlsDe extends TranslationsVideoControlsEn {
|
||||
@override String get unlockRotation => 'Rotation entsperren';
|
||||
@override String get timerActive => 'Schlaftimer aktiv';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'Wiedergabe wird in ${duration} pausiert';
|
||||
@override String get sleepTimerEndOfVideo => 'Ende des aktuellen Videos';
|
||||
@override String get sleepTimerStopAtHeader => 'Beenden bei';
|
||||
@override String get sleepTimerDurationHeader => 'Timer';
|
||||
@override String get playbackWillPauseAtEnd => 'Wiedergabe wird am Ende dieses Videos pausiert';
|
||||
@override String get stillWatching => 'Schaust du noch?';
|
||||
@override String pausingIn({required Object seconds}) => 'Pause in ${seconds}s';
|
||||
@override String get continueWatching => 'Weiter';
|
||||
@@ -2194,6 +2198,10 @@ extension on TranslationsDe {
|
||||
'videoControls.unlockRotation' => 'Rotation entsperren',
|
||||
'videoControls.timerActive' => 'Schlaftimer aktiv',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => 'Wiedergabe wird in ${duration} pausiert',
|
||||
'videoControls.sleepTimerEndOfVideo' => 'Ende des aktuellen Videos',
|
||||
'videoControls.sleepTimerStopAtHeader' => 'Beenden bei',
|
||||
'videoControls.sleepTimerDurationHeader' => 'Timer',
|
||||
'videoControls.playbackWillPauseAtEnd' => 'Wiedergabe wird am Ende dieses Videos pausiert',
|
||||
'videoControls.stillWatching' => 'Schaust du noch?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => 'Pause in ${seconds}s',
|
||||
'videoControls.continueWatching' => 'Weiter',
|
||||
@@ -2323,12 +2331,12 @@ extension on TranslationsDe {
|
||||
'mpvConfig.presetSaved' => 'Voreinstellung gespeichert',
|
||||
'mpvConfig.presetLoaded' => 'Voreinstellung geladen',
|
||||
'mpvConfig.presetDeleted' => 'Voreinstellung gelöscht',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => 'Möchten Sie diese Voreinstellung wirklich löschen?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||
'dialog.confirmAction' => 'Aktion bestätigen',
|
||||
'profiles.addPlezyProfile' => 'Plezy-Profil hinzufügen',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => 'Profil wird gewechselt…',
|
||||
'profiles.deleteThisProfileTitle' => 'Dieses Profil löschen?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => '${displayName} entfernen. Verbindungen bleiben unberührt.',
|
||||
@@ -2837,12 +2845,12 @@ extension on TranslationsDe {
|
||||
'externalPlayer.off' => 'Aus',
|
||||
'externalPlayer.launchFailed' => 'Externer Player konnte nicht geöffnet werden',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} ist nicht installiert',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => 'In externem Player abspielen',
|
||||
'metadataEdit.editMetadata' => 'Bearbeiten...',
|
||||
'metadataEdit.screenTitle' => 'Metadaten bearbeiten',
|
||||
'metadataEdit.basicInfo' => 'Grundlegende Infos',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => 'Artwork',
|
||||
'metadataEdit.advancedSettings' => 'Erweiterte Einstellungen',
|
||||
'metadataEdit.title' => 'Titel',
|
||||
|
||||
@@ -1276,6 +1276,18 @@ class TranslationsVideoControlsEn {
|
||||
/// en: 'Playback will pause in ${duration}'
|
||||
String playbackWillPauseIn({required Object duration}) => 'Playback will pause in ${duration}';
|
||||
|
||||
/// en: 'End of current video'
|
||||
String get sleepTimerEndOfVideo => 'End of current video';
|
||||
|
||||
/// en: 'Stop at'
|
||||
String get sleepTimerStopAtHeader => 'Stop at';
|
||||
|
||||
/// en: 'Timer'
|
||||
String get sleepTimerDurationHeader => 'Timer';
|
||||
|
||||
/// en: 'Playback will pause at the end of this video'
|
||||
String get playbackWillPauseAtEnd => 'Playback will pause at the end of this video';
|
||||
|
||||
/// en: 'Still watching?'
|
||||
String get stillWatching => 'Still watching?';
|
||||
|
||||
@@ -4572,6 +4584,10 @@ extension on Translations {
|
||||
'videoControls.unlockRotation' => 'Unlock rotation',
|
||||
'videoControls.timerActive' => 'Timer Active',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => 'Playback will pause in ${duration}',
|
||||
'videoControls.sleepTimerEndOfVideo' => 'End of current video',
|
||||
'videoControls.sleepTimerStopAtHeader' => 'Stop at',
|
||||
'videoControls.sleepTimerDurationHeader' => 'Timer',
|
||||
'videoControls.playbackWillPauseAtEnd' => 'Playback will pause at the end of this video',
|
||||
'videoControls.stillWatching' => 'Still watching?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => 'Pausing in ${seconds}s',
|
||||
'videoControls.continueWatching' => 'Continue',
|
||||
@@ -4701,12 +4717,12 @@ extension on Translations {
|
||||
'mpvConfig.presetSaved' => 'Preset saved',
|
||||
'mpvConfig.presetLoaded' => 'Preset loaded',
|
||||
'mpvConfig.presetDeleted' => 'Preset deleted',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => 'Are you sure you want to delete this preset?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||
'dialog.confirmAction' => 'Confirm Action',
|
||||
'profiles.addPlezyProfile' => 'Add Plezy profile',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => 'Switching profile…',
|
||||
'profiles.deleteThisProfileTitle' => 'Delete this profile?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => 'Remove ${displayName}. Connections aren\'t affected.',
|
||||
@@ -5215,12 +5231,12 @@ extension on Translations {
|
||||
'externalPlayer.off' => 'Off',
|
||||
'externalPlayer.launchFailed' => 'Failed to open external player',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} is not installed',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => 'Play in External Player',
|
||||
'metadataEdit.editMetadata' => 'Edit...',
|
||||
'metadataEdit.screenTitle' => 'Edit Metadata',
|
||||
'metadataEdit.basicInfo' => 'Basic Info',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => 'Artwork',
|
||||
'metadataEdit.advancedSettings' => 'Advanced Settings',
|
||||
'metadataEdit.title' => 'Title',
|
||||
|
||||
@@ -565,6 +565,10 @@ class _TranslationsVideoControlsEs extends TranslationsVideoControlsEn {
|
||||
@override String get unlockRotation => 'Desbloquear rotación';
|
||||
@override String get timerActive => 'Temporizador Activo';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'La reproducción se pausará en ${duration}';
|
||||
@override String get sleepTimerEndOfVideo => 'Fin del video actual';
|
||||
@override String get sleepTimerStopAtHeader => 'Detener en';
|
||||
@override String get sleepTimerDurationHeader => 'Temporizador';
|
||||
@override String get playbackWillPauseAtEnd => 'La reproducción se pausará al final de este video';
|
||||
@override String get stillWatching => '¿Sigues viendo?';
|
||||
@override String pausingIn({required Object seconds}) => 'Pausa en ${seconds}s';
|
||||
@override String get continueWatching => 'Continuar';
|
||||
@@ -2194,6 +2198,10 @@ extension on TranslationsEs {
|
||||
'videoControls.unlockRotation' => 'Desbloquear rotación',
|
||||
'videoControls.timerActive' => 'Temporizador Activo',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => 'La reproducción se pausará en ${duration}',
|
||||
'videoControls.sleepTimerEndOfVideo' => 'Fin del video actual',
|
||||
'videoControls.sleepTimerStopAtHeader' => 'Detener en',
|
||||
'videoControls.sleepTimerDurationHeader' => 'Temporizador',
|
||||
'videoControls.playbackWillPauseAtEnd' => 'La reproducción se pausará al final de este video',
|
||||
'videoControls.stillWatching' => '¿Sigues viendo?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => 'Pausa en ${seconds}s',
|
||||
'videoControls.continueWatching' => 'Continuar',
|
||||
@@ -2323,12 +2331,12 @@ extension on TranslationsEs {
|
||||
'mpvConfig.presetSaved' => 'Ajuste guardado',
|
||||
'mpvConfig.presetLoaded' => 'Ajuste cargado',
|
||||
'mpvConfig.presetDeleted' => 'Ajuste eliminado',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => '¿Estás seguro de que quieres eliminar este ajuste?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||
'dialog.confirmAction' => 'Confirmar Acción',
|
||||
'profiles.addPlezyProfile' => 'Añadir perfil de Plezy',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => 'Cambiando de perfil…',
|
||||
'profiles.deleteThisProfileTitle' => '¿Eliminar este perfil?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => 'Eliminar ${displayName}. Las conexiones no se verán afectadas.',
|
||||
@@ -2837,12 +2845,12 @@ extension on TranslationsEs {
|
||||
'externalPlayer.off' => 'Desactivado',
|
||||
'externalPlayer.launchFailed' => 'No se pudo abrir el reproductor externo',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} no está instalado',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => 'Reproducir en reproductor externo',
|
||||
'metadataEdit.editMetadata' => 'Editar...',
|
||||
'metadataEdit.screenTitle' => 'Editar metadatos',
|
||||
'metadataEdit.basicInfo' => 'Información básica',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => 'Artwork',
|
||||
'metadataEdit.advancedSettings' => 'Ajustes avanzados',
|
||||
'metadataEdit.title' => 'Título',
|
||||
|
||||
@@ -565,6 +565,10 @@ class _TranslationsVideoControlsFr extends TranslationsVideoControlsEn {
|
||||
@override String get unlockRotation => 'Déverrouiller la rotation';
|
||||
@override String get timerActive => 'Minuterie active';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'La lecture sera mise en pause dans ${duration}';
|
||||
@override String get sleepTimerEndOfVideo => 'Fin de la vidéo actuelle';
|
||||
@override String get sleepTimerStopAtHeader => 'Arrêter à';
|
||||
@override String get sleepTimerDurationHeader => 'Minuterie';
|
||||
@override String get playbackWillPauseAtEnd => 'La lecture sera mise en pause à la fin de cette vidéo';
|
||||
@override String get stillWatching => 'Toujours en train de regarder ?';
|
||||
@override String pausingIn({required Object seconds}) => 'Pause dans ${seconds}s';
|
||||
@override String get continueWatching => 'Continuer';
|
||||
@@ -2194,6 +2198,10 @@ extension on TranslationsFr {
|
||||
'videoControls.unlockRotation' => 'Déverrouiller la rotation',
|
||||
'videoControls.timerActive' => 'Minuterie active',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => 'La lecture sera mise en pause dans ${duration}',
|
||||
'videoControls.sleepTimerEndOfVideo' => 'Fin de la vidéo actuelle',
|
||||
'videoControls.sleepTimerStopAtHeader' => 'Arrêter à',
|
||||
'videoControls.sleepTimerDurationHeader' => 'Minuterie',
|
||||
'videoControls.playbackWillPauseAtEnd' => 'La lecture sera mise en pause à la fin de cette vidéo',
|
||||
'videoControls.stillWatching' => 'Toujours en train de regarder ?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => 'Pause dans ${seconds}s',
|
||||
'videoControls.continueWatching' => 'Continuer',
|
||||
@@ -2323,12 +2331,12 @@ extension on TranslationsFr {
|
||||
'mpvConfig.presetSaved' => 'Préréglage enregistré',
|
||||
'mpvConfig.presetLoaded' => 'Préréglage chargé',
|
||||
'mpvConfig.presetDeleted' => 'Préréglage supprimé',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => 'Êtes-vous sûr de vouloir supprimer ce préréglage ?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||
'dialog.confirmAction' => 'Confirmer l\'action',
|
||||
'profiles.addPlezyProfile' => 'Ajouter un profil Plezy',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => 'Changement de profil…',
|
||||
'profiles.deleteThisProfileTitle' => 'Supprimer ce profil ?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => 'Supprimer ${displayName}. Les connexions ne sont pas affectées.',
|
||||
@@ -2837,12 +2845,12 @@ extension on TranslationsFr {
|
||||
'externalPlayer.off' => 'Désactivé',
|
||||
'externalPlayer.launchFailed' => 'Impossible d\'ouvrir le lecteur externe',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} n\'est pas installé',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => 'Lire dans un lecteur externe',
|
||||
'metadataEdit.editMetadata' => 'Modifier...',
|
||||
'metadataEdit.screenTitle' => 'Modifier les métadonnées',
|
||||
'metadataEdit.basicInfo' => 'Informations de base',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => 'Artwork',
|
||||
'metadataEdit.advancedSettings' => 'Paramètres avancés',
|
||||
'metadataEdit.title' => 'Titre',
|
||||
|
||||
@@ -565,6 +565,10 @@ class _TranslationsVideoControlsIt extends TranslationsVideoControlsEn {
|
||||
@override String get unlockRotation => 'Sblocca rotazione';
|
||||
@override String get timerActive => 'Timer attivo';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'La riproduzione si interromperà tra ${duration}';
|
||||
@override String get sleepTimerEndOfVideo => 'Fine del video corrente';
|
||||
@override String get sleepTimerStopAtHeader => 'Interrompi a';
|
||||
@override String get sleepTimerDurationHeader => 'Timer';
|
||||
@override String get playbackWillPauseAtEnd => 'La riproduzione si interromperà alla fine di questo video';
|
||||
@override String get stillWatching => 'Stai ancora guardando?';
|
||||
@override String pausingIn({required Object seconds}) => 'Pausa tra ${seconds}s';
|
||||
@override String get continueWatching => 'Continua';
|
||||
@@ -2194,6 +2198,10 @@ extension on TranslationsIt {
|
||||
'videoControls.unlockRotation' => 'Sblocca rotazione',
|
||||
'videoControls.timerActive' => 'Timer attivo',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => 'La riproduzione si interromperà tra ${duration}',
|
||||
'videoControls.sleepTimerEndOfVideo' => 'Fine del video corrente',
|
||||
'videoControls.sleepTimerStopAtHeader' => 'Interrompi a',
|
||||
'videoControls.sleepTimerDurationHeader' => 'Timer',
|
||||
'videoControls.playbackWillPauseAtEnd' => 'La riproduzione si interromperà alla fine di questo video',
|
||||
'videoControls.stillWatching' => 'Stai ancora guardando?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => 'Pausa tra ${seconds}s',
|
||||
'videoControls.continueWatching' => 'Continua',
|
||||
@@ -2323,12 +2331,12 @@ extension on TranslationsIt {
|
||||
'mpvConfig.presetSaved' => 'Preset salvato',
|
||||
'mpvConfig.presetLoaded' => 'Preset caricato',
|
||||
'mpvConfig.presetDeleted' => 'Preset eliminato',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => 'Sei sicuro di voler eliminare questo preset?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||
'dialog.confirmAction' => 'Conferma azione',
|
||||
'profiles.addPlezyProfile' => 'Aggiungi profilo Plezy',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => 'Cambio profilo…',
|
||||
'profiles.deleteThisProfileTitle' => 'Eliminare questo profilo?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => 'Rimuovi ${displayName}. Le connessioni non sono interessate.',
|
||||
@@ -2837,12 +2845,12 @@ extension on TranslationsIt {
|
||||
'externalPlayer.off' => 'Disattivato',
|
||||
'externalPlayer.launchFailed' => 'Impossibile aprire il lettore esterno',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} non è installato',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => 'Riproduci in lettore esterno',
|
||||
'metadataEdit.editMetadata' => 'Modifica...',
|
||||
'metadataEdit.screenTitle' => 'Modifica metadati',
|
||||
'metadataEdit.basicInfo' => 'Informazioni di base',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => 'Artwork',
|
||||
'metadataEdit.advancedSettings' => 'Impostazioni avanzate',
|
||||
'metadataEdit.title' => 'Titolo',
|
||||
|
||||
@@ -565,6 +565,10 @@ class _TranslationsVideoControlsJa extends TranslationsVideoControlsEn {
|
||||
@override String get unlockRotation => '回転のロックを解除';
|
||||
@override String get timerActive => 'タイマー動作中';
|
||||
@override String playbackWillPauseIn({required Object duration}) => '再生は${duration}後に一時停止します';
|
||||
@override String get sleepTimerEndOfVideo => '現在の動画の最後';
|
||||
@override String get sleepTimerStopAtHeader => '停止のタイミング';
|
||||
@override String get sleepTimerDurationHeader => 'タイマー';
|
||||
@override String get playbackWillPauseAtEnd => '再生はこの動画の最後に一時停止します';
|
||||
@override String get stillWatching => 'まだ視聴中ですか?';
|
||||
@override String pausingIn({required Object seconds}) => '${seconds}秒後に一時停止';
|
||||
@override String get continueWatching => '続ける';
|
||||
@@ -2194,6 +2198,10 @@ extension on TranslationsJa {
|
||||
'videoControls.unlockRotation' => '回転のロックを解除',
|
||||
'videoControls.timerActive' => 'タイマー動作中',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => '再生は${duration}後に一時停止します',
|
||||
'videoControls.sleepTimerEndOfVideo' => '現在の動画の最後',
|
||||
'videoControls.sleepTimerStopAtHeader' => '停止のタイミング',
|
||||
'videoControls.sleepTimerDurationHeader' => 'タイマー',
|
||||
'videoControls.playbackWillPauseAtEnd' => '再生はこの動画の最後に一時停止します',
|
||||
'videoControls.stillWatching' => 'まだ視聴中ですか?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => '${seconds}秒後に一時停止',
|
||||
'videoControls.continueWatching' => '続ける',
|
||||
@@ -2323,12 +2331,12 @@ extension on TranslationsJa {
|
||||
'mpvConfig.presetSaved' => 'プリセットを保存しました',
|
||||
'mpvConfig.presetLoaded' => 'プリセットを読み込みました',
|
||||
'mpvConfig.presetDeleted' => 'プリセットを削除しました',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => 'このプリセットを削除してもよろしいですか?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||
'dialog.confirmAction' => '操作の確認',
|
||||
'profiles.addPlezyProfile' => 'Plezyプロファイルを追加',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => 'プロファイルを切り替え中…',
|
||||
'profiles.deleteThisProfileTitle' => 'このプロファイルを削除しますか?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => '${displayName}を削除します。接続には影響しません。',
|
||||
@@ -2837,12 +2845,12 @@ extension on TranslationsJa {
|
||||
'externalPlayer.off' => 'オフ',
|
||||
'externalPlayer.launchFailed' => '外部プレーヤーの起動に失敗しました',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name}がインストールされていません',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => '外部プレーヤーで再生',
|
||||
'metadataEdit.editMetadata' => '編集...',
|
||||
'metadataEdit.screenTitle' => 'メタデータを編集',
|
||||
'metadataEdit.basicInfo' => '基本情報',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => 'アートワーク',
|
||||
'metadataEdit.advancedSettings' => '詳細設定',
|
||||
'metadataEdit.title' => 'タイトル',
|
||||
|
||||
@@ -565,6 +565,10 @@ class _TranslationsVideoControlsKo extends TranslationsVideoControlsEn {
|
||||
@override String get unlockRotation => '회전 잠금 해제';
|
||||
@override String get timerActive => '타이머 활성화됨';
|
||||
@override String playbackWillPauseIn({required Object duration}) => '재생이 ${duration} 후에 일시 중지 됩니다';
|
||||
@override String get sleepTimerEndOfVideo => '현재 비디오의 끝';
|
||||
@override String get sleepTimerStopAtHeader => '정지 시점';
|
||||
@override String get sleepTimerDurationHeader => '타이머';
|
||||
@override String get playbackWillPauseAtEnd => '재생이 이 비디오의 끝에서 일시 중지됩니다';
|
||||
@override String get stillWatching => '아직 시청 중이신가요?';
|
||||
@override String pausingIn({required Object seconds}) => '${seconds}초 후 일시 정지';
|
||||
@override String get continueWatching => '계속';
|
||||
@@ -2194,6 +2198,10 @@ extension on TranslationsKo {
|
||||
'videoControls.unlockRotation' => '회전 잠금 해제',
|
||||
'videoControls.timerActive' => '타이머 활성화됨',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => '재생이 ${duration} 후에 일시 중지 됩니다',
|
||||
'videoControls.sleepTimerEndOfVideo' => '현재 비디오의 끝',
|
||||
'videoControls.sleepTimerStopAtHeader' => '정지 시점',
|
||||
'videoControls.sleepTimerDurationHeader' => '타이머',
|
||||
'videoControls.playbackWillPauseAtEnd' => '재생이 이 비디오의 끝에서 일시 중지됩니다',
|
||||
'videoControls.stillWatching' => '아직 시청 중이신가요?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => '${seconds}초 후 일시 정지',
|
||||
'videoControls.continueWatching' => '계속',
|
||||
@@ -2323,12 +2331,12 @@ extension on TranslationsKo {
|
||||
'mpvConfig.presetSaved' => '프리셋이 저장 되었습니다',
|
||||
'mpvConfig.presetLoaded' => '프리셋이 로드 되었습니다',
|
||||
'mpvConfig.presetDeleted' => '프리셋이 삭제 되었습니다',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => '이 프리셋을 삭제 하시겠습니까?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||
'dialog.confirmAction' => '확인',
|
||||
'profiles.addPlezyProfile' => 'Plezy 프로필 추가',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => '프로필 전환 중…',
|
||||
'profiles.deleteThisProfileTitle' => '이 프로필을 삭제하시겠습니까?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => '${displayName}을(를) 제거합니다. 연결에는 영향이 없습니다.',
|
||||
@@ -2837,12 +2845,12 @@ extension on TranslationsKo {
|
||||
'externalPlayer.off' => '꺼짐',
|
||||
'externalPlayer.launchFailed' => '외부 플레이어를 열 수 없습니다',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name}이(가) 설치되어 있지 않습니다',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => '외부 플레이어에서 재생',
|
||||
'metadataEdit.editMetadata' => '편집...',
|
||||
'metadataEdit.screenTitle' => '메타데이터 편집',
|
||||
'metadataEdit.basicInfo' => '기본 정보',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => '아트워크',
|
||||
'metadataEdit.advancedSettings' => '고급 설정',
|
||||
'metadataEdit.title' => '제목',
|
||||
|
||||
@@ -565,6 +565,10 @@ class _TranslationsVideoControlsNb extends TranslationsVideoControlsEn {
|
||||
@override String get unlockRotation => 'Lås opp rotasjon';
|
||||
@override String get timerActive => 'Timer aktiv';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'Avspilling vil pause om ${duration}';
|
||||
@override String get sleepTimerEndOfVideo => 'Slutten av gjeldende video';
|
||||
@override String get sleepTimerStopAtHeader => 'Stopp ved';
|
||||
@override String get sleepTimerDurationHeader => 'Timer';
|
||||
@override String get playbackWillPauseAtEnd => 'Avspilling vil pause på slutten av denne videoen';
|
||||
@override String get stillWatching => 'Ser du fortsatt?';
|
||||
@override String pausingIn({required Object seconds}) => 'Pauser om ${seconds}s';
|
||||
@override String get continueWatching => 'Fortsett';
|
||||
@@ -2194,6 +2198,10 @@ extension on TranslationsNb {
|
||||
'videoControls.unlockRotation' => 'Lås opp rotasjon',
|
||||
'videoControls.timerActive' => 'Timer aktiv',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => 'Avspilling vil pause om ${duration}',
|
||||
'videoControls.sleepTimerEndOfVideo' => 'Slutten av gjeldende video',
|
||||
'videoControls.sleepTimerStopAtHeader' => 'Stopp ved',
|
||||
'videoControls.sleepTimerDurationHeader' => 'Timer',
|
||||
'videoControls.playbackWillPauseAtEnd' => 'Avspilling vil pause på slutten av denne videoen',
|
||||
'videoControls.stillWatching' => 'Ser du fortsatt?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => 'Pauser om ${seconds}s',
|
||||
'videoControls.continueWatching' => 'Fortsett',
|
||||
@@ -2323,12 +2331,12 @@ extension on TranslationsNb {
|
||||
'mpvConfig.presetSaved' => 'Forhåndsinnstilling lagret',
|
||||
'mpvConfig.presetLoaded' => 'Forhåndsinnstilling lastet inn',
|
||||
'mpvConfig.presetDeleted' => 'Forhåndsinnstilling slettet',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => 'Er du sikker på at du vil slette denne forhåndsinnstillingen?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# kommentar',
|
||||
'dialog.confirmAction' => 'Bekreft handling',
|
||||
'profiles.addPlezyProfile' => 'Legg til Plezy-profil',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => 'Bytter profil…',
|
||||
'profiles.deleteThisProfileTitle' => 'Slett denne profilen?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => 'Fjern ${displayName}. Tilkoblinger påvirkes ikke.',
|
||||
@@ -2837,12 +2845,12 @@ extension on TranslationsNb {
|
||||
'externalPlayer.off' => 'Av',
|
||||
'externalPlayer.launchFailed' => 'Kunne ikke åpne ekstern spiller',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} er ikke installert',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => 'Spill av i ekstern spiller',
|
||||
'metadataEdit.editMetadata' => 'Rediger...',
|
||||
'metadataEdit.screenTitle' => 'Rediger metadata',
|
||||
'metadataEdit.basicInfo' => 'Grunnleggende info',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => 'Kunstverk',
|
||||
'metadataEdit.advancedSettings' => 'Avanserte innstillinger',
|
||||
'metadataEdit.title' => 'Tittel',
|
||||
|
||||
@@ -565,6 +565,10 @@ class _TranslationsVideoControlsNl extends TranslationsVideoControlsEn {
|
||||
@override String get unlockRotation => 'Ontgrendel rotatie';
|
||||
@override String get timerActive => 'Timer actief';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'Afspelen wordt gepauzeerd over ${duration}';
|
||||
@override String get sleepTimerEndOfVideo => 'Einde van huidige video';
|
||||
@override String get sleepTimerStopAtHeader => 'Stoppen bij';
|
||||
@override String get sleepTimerDurationHeader => 'Timer';
|
||||
@override String get playbackWillPauseAtEnd => 'Afspelen wordt gepauzeerd aan het einde van deze video';
|
||||
@override String get stillWatching => 'Kijk je nog?';
|
||||
@override String pausingIn({required Object seconds}) => 'Pauze over ${seconds}s';
|
||||
@override String get continueWatching => 'Doorgaan';
|
||||
@@ -2194,6 +2198,10 @@ extension on TranslationsNl {
|
||||
'videoControls.unlockRotation' => 'Ontgrendel rotatie',
|
||||
'videoControls.timerActive' => 'Timer actief',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => 'Afspelen wordt gepauzeerd over ${duration}',
|
||||
'videoControls.sleepTimerEndOfVideo' => 'Einde van huidige video',
|
||||
'videoControls.sleepTimerStopAtHeader' => 'Stoppen bij',
|
||||
'videoControls.sleepTimerDurationHeader' => 'Timer',
|
||||
'videoControls.playbackWillPauseAtEnd' => 'Afspelen wordt gepauzeerd aan het einde van deze video',
|
||||
'videoControls.stillWatching' => 'Kijk je nog?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => 'Pauze over ${seconds}s',
|
||||
'videoControls.continueWatching' => 'Doorgaan',
|
||||
@@ -2323,12 +2331,12 @@ extension on TranslationsNl {
|
||||
'mpvConfig.presetSaved' => 'Voorinstelling opgeslagen',
|
||||
'mpvConfig.presetLoaded' => 'Voorinstelling geladen',
|
||||
'mpvConfig.presetDeleted' => 'Voorinstelling verwijderd',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => 'Weet je zeker dat je deze voorinstelling wilt verwijderen?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||
'dialog.confirmAction' => 'Bevestig actie',
|
||||
'profiles.addPlezyProfile' => 'Plezy-profiel toevoegen',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => 'Profiel wisselen…',
|
||||
'profiles.deleteThisProfileTitle' => 'Dit profiel verwijderen?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => 'Verwijder ${displayName}. Verbindingen blijven ongewijzigd.',
|
||||
@@ -2837,12 +2845,12 @@ extension on TranslationsNl {
|
||||
'externalPlayer.off' => 'Uit',
|
||||
'externalPlayer.launchFailed' => 'Kan externe speler niet openen',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} is niet geïnstalleerd',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => 'Afspelen in externe speler',
|
||||
'metadataEdit.editMetadata' => 'Bewerken...',
|
||||
'metadataEdit.screenTitle' => 'Metadata bewerken',
|
||||
'metadataEdit.basicInfo' => 'Basisinformatie',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => 'Artwork',
|
||||
'metadataEdit.advancedSettings' => 'Geavanceerde instellingen',
|
||||
'metadataEdit.title' => 'Titel',
|
||||
|
||||
@@ -565,6 +565,10 @@ class _TranslationsVideoControlsPl extends TranslationsVideoControlsEn {
|
||||
@override String get unlockRotation => 'Odblokuj obrót';
|
||||
@override String get timerActive => 'Wyłącznik aktywny';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'Odtwarzanie zatrzyma się za ${duration}';
|
||||
@override String get sleepTimerEndOfVideo => 'Koniec bieżącego wideo';
|
||||
@override String get sleepTimerStopAtHeader => 'Zatrzymaj na';
|
||||
@override String get sleepTimerDurationHeader => 'Minutnik';
|
||||
@override String get playbackWillPauseAtEnd => 'Odtwarzanie zatrzyma się na końcu tego wideo';
|
||||
@override String get stillWatching => 'Nadal oglądasz?';
|
||||
@override String pausingIn({required Object seconds}) => 'Pauza za ${seconds}s';
|
||||
@override String get continueWatching => 'Kontynuuj';
|
||||
@@ -2194,6 +2198,10 @@ extension on TranslationsPl {
|
||||
'videoControls.unlockRotation' => 'Odblokuj obrót',
|
||||
'videoControls.timerActive' => 'Wyłącznik aktywny',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => 'Odtwarzanie zatrzyma się za ${duration}',
|
||||
'videoControls.sleepTimerEndOfVideo' => 'Koniec bieżącego wideo',
|
||||
'videoControls.sleepTimerStopAtHeader' => 'Zatrzymaj na',
|
||||
'videoControls.sleepTimerDurationHeader' => 'Minutnik',
|
||||
'videoControls.playbackWillPauseAtEnd' => 'Odtwarzanie zatrzyma się na końcu tego wideo',
|
||||
'videoControls.stillWatching' => 'Nadal oglądasz?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => 'Pauza za ${seconds}s',
|
||||
'videoControls.continueWatching' => 'Kontynuuj',
|
||||
@@ -2323,12 +2331,12 @@ extension on TranslationsPl {
|
||||
'mpvConfig.presetSaved' => 'Preset zapisany',
|
||||
'mpvConfig.presetLoaded' => 'Preset załadowany',
|
||||
'mpvConfig.presetDeleted' => 'Preset usunięty',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => 'Czy na pewno chcesz usunąć ten preset?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||
'dialog.confirmAction' => 'Potwierdź działanie',
|
||||
'profiles.addPlezyProfile' => 'Dodaj profil Plezy',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => 'Przełączanie profilu…',
|
||||
'profiles.deleteThisProfileTitle' => 'Usunąć ten profil?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => 'Usuń ${displayName}. Połączenia nie zostaną zmienione.',
|
||||
@@ -2837,12 +2845,12 @@ extension on TranslationsPl {
|
||||
'externalPlayer.off' => 'Wyłączony',
|
||||
'externalPlayer.launchFailed' => 'Nie udało się otworzyć zewnętrznego odtwarzacza',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} nie jest zainstalowany',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => 'Odtwórz w zewnętrznym odtwarzaczu',
|
||||
'metadataEdit.editMetadata' => 'Edytuj...',
|
||||
'metadataEdit.screenTitle' => 'Edytuj metadane',
|
||||
'metadataEdit.basicInfo' => 'Podstawowe informacje',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => 'Grafika',
|
||||
'metadataEdit.advancedSettings' => 'Ustawienia zaawansowane',
|
||||
'metadataEdit.title' => 'Tytuł',
|
||||
|
||||
@@ -565,6 +565,10 @@ class _TranslationsVideoControlsPt extends TranslationsVideoControlsEn {
|
||||
@override String get unlockRotation => 'Destravar rotação';
|
||||
@override String get timerActive => 'Timer Ativo';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'A reprodução pausará em ${duration}';
|
||||
@override String get sleepTimerEndOfVideo => 'Fim do vídeo atual';
|
||||
@override String get sleepTimerStopAtHeader => 'Parar em';
|
||||
@override String get sleepTimerDurationHeader => 'Timer';
|
||||
@override String get playbackWillPauseAtEnd => 'A reprodução pausará no final deste vídeo';
|
||||
@override String get stillWatching => 'Ainda assistindo?';
|
||||
@override String pausingIn({required Object seconds}) => 'Pausando em ${seconds}s';
|
||||
@override String get continueWatching => 'Continuar';
|
||||
@@ -2194,6 +2198,10 @@ extension on TranslationsPt {
|
||||
'videoControls.unlockRotation' => 'Destravar rotação',
|
||||
'videoControls.timerActive' => 'Timer Ativo',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => 'A reprodução pausará em ${duration}',
|
||||
'videoControls.sleepTimerEndOfVideo' => 'Fim do vídeo atual',
|
||||
'videoControls.sleepTimerStopAtHeader' => 'Parar em',
|
||||
'videoControls.sleepTimerDurationHeader' => 'Timer',
|
||||
'videoControls.playbackWillPauseAtEnd' => 'A reprodução pausará no final deste vídeo',
|
||||
'videoControls.stillWatching' => 'Ainda assistindo?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => 'Pausando em ${seconds}s',
|
||||
'videoControls.continueWatching' => 'Continuar',
|
||||
@@ -2323,12 +2331,12 @@ extension on TranslationsPt {
|
||||
'mpvConfig.presetSaved' => 'Predefinição salva',
|
||||
'mpvConfig.presetLoaded' => 'Predefinição carregada',
|
||||
'mpvConfig.presetDeleted' => 'Predefinição excluída',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => 'Tem certeza que deseja excluir esta predefinição?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||
'dialog.confirmAction' => 'Confirmar Ação',
|
||||
'profiles.addPlezyProfile' => 'Adicionar perfil Plezy',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => 'Mudando perfil…',
|
||||
'profiles.deleteThisProfileTitle' => 'Excluir este perfil?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => 'Remover ${displayName}. As conexões não serão afetadas.',
|
||||
@@ -2837,12 +2845,12 @@ extension on TranslationsPt {
|
||||
'externalPlayer.off' => 'Desativado',
|
||||
'externalPlayer.launchFailed' => 'Falha ao abrir player externo',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} não está instalado',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => 'Reproduzir no Player Externo',
|
||||
'metadataEdit.editMetadata' => 'Editar...',
|
||||
'metadataEdit.screenTitle' => 'Editar Metadados',
|
||||
'metadataEdit.basicInfo' => 'Informações Básicas',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => 'Arte',
|
||||
'metadataEdit.advancedSettings' => 'Configurações Avançadas',
|
||||
'metadataEdit.title' => 'Título',
|
||||
|
||||
@@ -565,6 +565,10 @@ class _TranslationsVideoControlsRu extends TranslationsVideoControlsEn {
|
||||
@override String get unlockRotation => 'Разблокировать поворот';
|
||||
@override String get timerActive => 'Таймер активен';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'Воспроизведение будет приостановлено через ${duration}';
|
||||
@override String get sleepTimerEndOfVideo => 'Конец текущего видео';
|
||||
@override String get sleepTimerStopAtHeader => 'Остановить на';
|
||||
@override String get sleepTimerDurationHeader => 'Таймер';
|
||||
@override String get playbackWillPauseAtEnd => 'Воспроизведение будет приостановлено в конце этого видео';
|
||||
@override String get stillWatching => 'Всё ещё смотрите?';
|
||||
@override String pausingIn({required Object seconds}) => 'Пауза через ${seconds}с';
|
||||
@override String get continueWatching => 'Продолжить';
|
||||
@@ -2194,6 +2198,10 @@ extension on TranslationsRu {
|
||||
'videoControls.unlockRotation' => 'Разблокировать поворот',
|
||||
'videoControls.timerActive' => 'Таймер активен',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => 'Воспроизведение будет приостановлено через ${duration}',
|
||||
'videoControls.sleepTimerEndOfVideo' => 'Конец текущего видео',
|
||||
'videoControls.sleepTimerStopAtHeader' => 'Остановить на',
|
||||
'videoControls.sleepTimerDurationHeader' => 'Таймер',
|
||||
'videoControls.playbackWillPauseAtEnd' => 'Воспроизведение будет приостановлено в конце этого видео',
|
||||
'videoControls.stillWatching' => 'Всё ещё смотрите?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => 'Пауза через ${seconds}с',
|
||||
'videoControls.continueWatching' => 'Продолжить',
|
||||
@@ -2323,12 +2331,12 @@ extension on TranslationsRu {
|
||||
'mpvConfig.presetSaved' => 'Пресет сохранён',
|
||||
'mpvConfig.presetLoaded' => 'Пресет загружен',
|
||||
'mpvConfig.presetDeleted' => 'Пресет удалён',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => 'Вы уверены, что хотите удалить этот пресет?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||
'dialog.confirmAction' => 'Подтвердить действие',
|
||||
'profiles.addPlezyProfile' => 'Добавить профиль Plezy',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => 'Переключение профиля…',
|
||||
'profiles.deleteThisProfileTitle' => 'Удалить этот профиль?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => 'Удалить ${displayName}. Подключения не изменятся.',
|
||||
@@ -2837,12 +2845,12 @@ extension on TranslationsRu {
|
||||
'externalPlayer.off' => 'Выкл.',
|
||||
'externalPlayer.launchFailed' => 'Не удалось открыть внешний плеер',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} не установлен',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => 'Воспроизвести во внешнем плеере',
|
||||
'metadataEdit.editMetadata' => 'Редактировать...',
|
||||
'metadataEdit.screenTitle' => 'Редактировать метаданные',
|
||||
'metadataEdit.basicInfo' => 'Основная информация',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => 'Обложка',
|
||||
'metadataEdit.advancedSettings' => 'Дополнительные настройки',
|
||||
'metadataEdit.title' => 'Название',
|
||||
|
||||
@@ -565,6 +565,10 @@ class _TranslationsVideoControlsSv extends TranslationsVideoControlsEn {
|
||||
@override String get unlockRotation => 'Lås upp rotation';
|
||||
@override String get timerActive => 'Timer aktiv';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'Uppspelningen pausas om ${duration}';
|
||||
@override String get sleepTimerEndOfVideo => 'Slutet av aktuell video';
|
||||
@override String get sleepTimerStopAtHeader => 'Stoppa vid';
|
||||
@override String get sleepTimerDurationHeader => 'Timer';
|
||||
@override String get playbackWillPauseAtEnd => 'Uppspelningen pausas i slutet av denna video';
|
||||
@override String get stillWatching => 'Tittar du fortfarande?';
|
||||
@override String pausingIn({required Object seconds}) => 'Pausar om ${seconds}s';
|
||||
@override String get continueWatching => 'Fortsätt';
|
||||
@@ -2194,6 +2198,10 @@ extension on TranslationsSv {
|
||||
'videoControls.unlockRotation' => 'Lås upp rotation',
|
||||
'videoControls.timerActive' => 'Timer aktiv',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => 'Uppspelningen pausas om ${duration}',
|
||||
'videoControls.sleepTimerEndOfVideo' => 'Slutet av aktuell video',
|
||||
'videoControls.sleepTimerStopAtHeader' => 'Stoppa vid',
|
||||
'videoControls.sleepTimerDurationHeader' => 'Timer',
|
||||
'videoControls.playbackWillPauseAtEnd' => 'Uppspelningen pausas i slutet av denna video',
|
||||
'videoControls.stillWatching' => 'Tittar du fortfarande?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => 'Pausar om ${seconds}s',
|
||||
'videoControls.continueWatching' => 'Fortsätt',
|
||||
@@ -2323,12 +2331,12 @@ extension on TranslationsSv {
|
||||
'mpvConfig.presetSaved' => 'Förval sparat',
|
||||
'mpvConfig.presetLoaded' => 'Förval laddat',
|
||||
'mpvConfig.presetDeleted' => 'Förval borttaget',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => 'Är du säker på att du vill ta bort detta förval?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||
'dialog.confirmAction' => 'Bekräfta åtgärd',
|
||||
'profiles.addPlezyProfile' => 'Lägg till Plezy-profil',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => 'Byter profil…',
|
||||
'profiles.deleteThisProfileTitle' => 'Ta bort denna profil?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => 'Ta bort ${displayName}. Anslutningar påverkas inte.',
|
||||
@@ -2837,12 +2845,12 @@ extension on TranslationsSv {
|
||||
'externalPlayer.off' => 'Av',
|
||||
'externalPlayer.launchFailed' => 'Kunde inte öppna extern spelare',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} är inte installerad',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => 'Spela i extern spelare',
|
||||
'metadataEdit.editMetadata' => 'Redigera...',
|
||||
'metadataEdit.screenTitle' => 'Redigera metadata',
|
||||
'metadataEdit.basicInfo' => 'Grundläggande info',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => 'Artwork',
|
||||
'metadataEdit.advancedSettings' => 'Avancerade inställningar',
|
||||
'metadataEdit.title' => 'Titel',
|
||||
|
||||
@@ -565,6 +565,10 @@ class _TranslationsVideoControlsZh extends TranslationsVideoControlsEn {
|
||||
@override String get unlockRotation => '解锁旋转';
|
||||
@override String get timerActive => '定时器已激活';
|
||||
@override String playbackWillPauseIn({required Object duration}) => '播放将在 ${duration} 后暂停';
|
||||
@override String get sleepTimerEndOfVideo => '当前视频结束时';
|
||||
@override String get sleepTimerStopAtHeader => '停止于';
|
||||
@override String get sleepTimerDurationHeader => '定时器';
|
||||
@override String get playbackWillPauseAtEnd => '播放将在此视频结束时暂停';
|
||||
@override String get stillWatching => '还在看吗?';
|
||||
@override String pausingIn({required Object seconds}) => '${seconds}秒后暂停';
|
||||
@override String get continueWatching => '继续';
|
||||
@@ -2194,6 +2198,10 @@ extension on TranslationsZh {
|
||||
'videoControls.unlockRotation' => '解锁旋转',
|
||||
'videoControls.timerActive' => '定时器已激活',
|
||||
'videoControls.playbackWillPauseIn' => ({required Object duration}) => '播放将在 ${duration} 后暂停',
|
||||
'videoControls.sleepTimerEndOfVideo' => '当前视频结束时',
|
||||
'videoControls.sleepTimerStopAtHeader' => '停止于',
|
||||
'videoControls.sleepTimerDurationHeader' => '定时器',
|
||||
'videoControls.playbackWillPauseAtEnd' => '播放将在此视频结束时暂停',
|
||||
'videoControls.stillWatching' => '还在看吗?',
|
||||
'videoControls.pausingIn' => ({required Object seconds}) => '${seconds}秒后暂停',
|
||||
'videoControls.continueWatching' => '继续',
|
||||
@@ -2323,12 +2331,12 @@ extension on TranslationsZh {
|
||||
'mpvConfig.presetSaved' => '预设已保存',
|
||||
'mpvConfig.presetLoaded' => '预设已加载',
|
||||
'mpvConfig.presetDeleted' => '预设已删除',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'mpvConfig.confirmDeletePreset' => '确定要删除此预设吗?',
|
||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||
'dialog.confirmAction' => '确认操作',
|
||||
'profiles.addPlezyProfile' => '添加 Plezy 配置文件',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'profiles.switchingProfile' => '切换配置文件中…',
|
||||
'profiles.deleteThisProfileTitle' => '删除此配置文件?',
|
||||
'profiles.deleteThisProfileMessage' => ({required Object displayName}) => '移除 ${displayName}。连接不会受影响。',
|
||||
@@ -2837,12 +2845,12 @@ extension on TranslationsZh {
|
||||
'externalPlayer.off' => '关闭',
|
||||
'externalPlayer.launchFailed' => '无法打开外部播放器',
|
||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} 未安装',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'externalPlayer.playInExternalPlayer' => '在外部播放器中播放',
|
||||
'metadataEdit.editMetadata' => '编辑...',
|
||||
'metadataEdit.screenTitle' => '编辑元数据',
|
||||
'metadataEdit.basicInfo' => '基本信息',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'metadataEdit.artwork' => '封面图片',
|
||||
'metadataEdit.advancedSettings' => '高级设置',
|
||||
'metadataEdit.title' => '标题',
|
||||
|
||||
@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "Lås upp rotation",
|
||||
"timerActive": "Timer aktiv",
|
||||
"playbackWillPauseIn": "Uppspelningen pausas om ${duration}",
|
||||
"sleepTimerEndOfVideo": "Slutet av aktuell video",
|
||||
"sleepTimerStopAtHeader": "Stoppa vid",
|
||||
"sleepTimerDurationHeader": "Timer",
|
||||
"playbackWillPauseAtEnd": "Uppspelningen pausas i slutet av denna video",
|
||||
"stillWatching": "Tittar du fortfarande?",
|
||||
"pausingIn": "Pausar om ${seconds}s",
|
||||
"continueWatching": "Fortsätt",
|
||||
|
||||
@@ -407,6 +407,10 @@
|
||||
"unlockRotation": "解锁旋转",
|
||||
"timerActive": "定时器已激活",
|
||||
"playbackWillPauseIn": "播放将在 ${duration} 后暂停",
|
||||
"sleepTimerEndOfVideo": "当前视频结束时",
|
||||
"sleepTimerStopAtHeader": "停止于",
|
||||
"sleepTimerDurationHeader": "定时器",
|
||||
"playbackWillPauseAtEnd": "播放将在此视频结束时暂停",
|
||||
"stillWatching": "还在看吗?",
|
||||
"pausingIn": "${seconds}秒后暂停",
|
||||
"continueWatching": "继续",
|
||||
|
||||
@@ -25,6 +25,15 @@ extension _VideoPlayerPlaybackPromptMethods on VideoPlayerScreenState {
|
||||
unawaited(_videoPIPManager?.updateAutoPipState(isPlaying: false));
|
||||
}
|
||||
|
||||
// End-of-video sleep timer takes precedence over autoplay / next-episode
|
||||
// dialogs: the user explicitly asked to stop after this item.
|
||||
final sleepTimerService = SleepTimerService();
|
||||
if (sleepTimerService.isEndOfVideoMode && !_completionTriggered) {
|
||||
_completionTriggered = true;
|
||||
sleepTimerService.notifyVideoCompleted();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_nextEpisode != null && !_showPlayNextDialog && !_showStillWatchingPrompt && !_completionTriggered) {
|
||||
_completionTriggered = true;
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ class SleepTimerService extends ChangeNotifier {
|
||||
Duration? _originalDuration;
|
||||
VoidCallback? _onTimerComplete;
|
||||
bool _needsRestart = false;
|
||||
bool _restartAsEndOfVideo = false;
|
||||
bool _endOfVideoArmed = false;
|
||||
final StreamController<void> _completedController = StreamController<void>.broadcast();
|
||||
final StreamController<void> _promptController = StreamController<void>.broadcast();
|
||||
|
||||
@@ -24,7 +26,11 @@ class SleepTimerService extends ChangeNotifier {
|
||||
/// Emits when the timer fires and wants to show a "still watching?" prompt
|
||||
Stream<void> get onPrompt => _promptController.stream;
|
||||
|
||||
bool get isActive => _timer != null && _timer!.isActive;
|
||||
bool get isActive => (_timer != null && _timer!.isActive) || _endOfVideoArmed;
|
||||
|
||||
/// Whether the sleep timer is armed to fire at the end of the current video
|
||||
/// rather than after a fixed duration.
|
||||
bool get isEndOfVideoMode => _endOfVideoArmed;
|
||||
|
||||
/// The time when the timer will complete
|
||||
DateTime? get endTime => _endTime;
|
||||
@@ -67,9 +73,34 @@ class SleepTimerService extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Arm the sleep timer to fire when the currently playing video reaches its end.
|
||||
/// Unlike [startTimer], no periodic timer runs — playback completion is reported
|
||||
/// externally via [notifyVideoCompleted].
|
||||
void armEndOfVideo(VoidCallback onComplete) {
|
||||
cancelTimer();
|
||||
|
||||
_endOfVideoArmed = true;
|
||||
_onTimerComplete = onComplete;
|
||||
|
||||
appLogger.d('Sleep timer armed: end of current video');
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Notify the service that the currently playing video has completed.
|
||||
/// If armed via [armEndOfVideo], fires the completion callback and resets the mode.
|
||||
/// Safe to call unconditionally — does nothing when end-of-video mode is not armed.
|
||||
void notifyVideoCompleted() {
|
||||
if (!_endOfVideoArmed) return;
|
||||
|
||||
appLogger.d('Sleep timer (end of video) triggered');
|
||||
_endOfVideoArmed = false;
|
||||
_executeCallback();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Cancel the active timer (user-initiated, clears everything)
|
||||
void cancelTimer() {
|
||||
if (_timer != null || _originalDuration != null) {
|
||||
if (_timer != null || _originalDuration != null || _endOfVideoArmed) {
|
||||
appLogger.d('Sleep timer cancelled');
|
||||
_timer?.cancel();
|
||||
_timer = null;
|
||||
@@ -77,6 +108,8 @@ class SleepTimerService extends ChangeNotifier {
|
||||
_duration = null;
|
||||
_originalDuration = null;
|
||||
_onTimerComplete = null;
|
||||
_endOfVideoArmed = false;
|
||||
_restartAsEndOfVideo = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
@@ -99,14 +132,20 @@ class SleepTimerService extends ChangeNotifier {
|
||||
void markNeedsRestart() {
|
||||
if (isActive || _originalDuration != null) {
|
||||
_needsRestart = true;
|
||||
_restartAsEndOfVideo = _endOfVideoArmed;
|
||||
}
|
||||
}
|
||||
|
||||
/// Restart the timer if it was marked for restart (new playback session).
|
||||
/// [onComplete] provides the new callback for the fresh session.
|
||||
void restartIfNeeded(VoidCallback onComplete) {
|
||||
if (_needsRestart && _originalDuration != null) {
|
||||
_needsRestart = false;
|
||||
if (!_needsRestart) return;
|
||||
_needsRestart = false;
|
||||
|
||||
if (_restartAsEndOfVideo) {
|
||||
_restartAsEndOfVideo = false;
|
||||
armEndOfVideo(onComplete);
|
||||
} else if (_originalDuration != null) {
|
||||
startTimer(_originalDuration!, onComplete);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,16 +6,27 @@ import '../../../services/sleep_timer_service.dart';
|
||||
import '../../../i18n/strings.g.dart';
|
||||
import '../../../utils/formatters.dart';
|
||||
|
||||
/// Widget displaying active sleep timer status with extend/cancel actions
|
||||
/// Widget displaying active sleep timer status with extend/cancel actions.
|
||||
///
|
||||
/// Supports two modes:
|
||||
/// * Timed (default) — [remainingTime] is non-null; shows countdown and the
|
||||
/// "+15 min" extend button.
|
||||
/// * End-of-video — [remainingTime] is null; shows a static message and only
|
||||
/// the cancel button (extending makes no sense here).
|
||||
class SleepTimerActiveStatus extends StatelessWidget {
|
||||
final SleepTimerService sleepTimer;
|
||||
final Duration remainingTime;
|
||||
final Duration? remainingTime;
|
||||
final VoidCallback? onCancel;
|
||||
|
||||
const SleepTimerActiveStatus({super.key, required this.sleepTimer, required this.remainingTime, this.onCancel});
|
||||
const SleepTimerActiveStatus({super.key, required this.sleepTimer, this.remainingTime, this.onCancel});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isEndOfVideo = remainingTime == null;
|
||||
final subtitle = isEndOfVideo
|
||||
? t.videoControls.playbackWillPauseAtEnd
|
||||
: t.videoControls.playbackWillPauseIn(duration: formatDurationWithSeconds(remainingTime!));
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
color: Colors.amber.withValues(alpha: 0.1),
|
||||
@@ -27,30 +38,33 @@ class SleepTimerActiveStatus extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
t.videoControls.playbackWillPauseIn(duration: formatDurationWithSeconds(remainingTime)),
|
||||
subtitle,
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant, fontSize: 14),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
FocusableButton(
|
||||
onPressed: () {
|
||||
sleepTimer.extendTimer(const Duration(minutes: 15));
|
||||
},
|
||||
child: OutlinedButton.icon(
|
||||
icon: const AppIcon(Symbols.add_rounded, fill: 1),
|
||||
label: Text(t.videoControls.addTime(amount: "15", unit: " min")),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: Theme.of(context).colorScheme.onSurface,
|
||||
side: BorderSide(color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
if (!isEndOfVideo) ...[
|
||||
FocusableButton(
|
||||
onPressed: () {
|
||||
sleepTimer.extendTimer(const Duration(minutes: 15));
|
||||
},
|
||||
child: OutlinedButton.icon(
|
||||
icon: const AppIcon(Symbols.add_rounded, fill: 1),
|
||||
label: Text(t.videoControls.addTime(amount: "15", unit: " min")),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: Theme.of(context).colorScheme.onSurface,
|
||||
side: BorderSide(color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
onPressed: () {
|
||||
sleepTimer.extendTimer(const Duration(minutes: 15));
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
const SizedBox(width: 12),
|
||||
],
|
||||
FocusableButton(
|
||||
onPressed: () {
|
||||
sleepTimer.cancelTimer();
|
||||
|
||||
@@ -1,11 +1,28 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
|
||||
import '../../../i18n/strings.g.dart';
|
||||
import '../../../mpv/mpv.dart';
|
||||
import '../../../services/sleep_timer_service.dart';
|
||||
import '../../../utils/formatters.dart';
|
||||
import '../../../utils/snackbar_helper.dart';
|
||||
import '../../../widgets/app_icon.dart';
|
||||
import '../../../widgets/focusable_list_tile.dart';
|
||||
import '../../../widgets/overlay_sheet.dart';
|
||||
import '../sheets/sheet_column_header.dart';
|
||||
import 'sleep_timer_active_status.dart';
|
||||
import 'sleep_timer_duration_list.dart';
|
||||
|
||||
/// Shared UI for sleep timer selection and active status.
|
||||
///
|
||||
/// Layout mirrors the audio/subtitle [TrackSheet]: two side-by-side columns
|
||||
/// inside a [Row], each in its own [FocusTraversalGroup] so D-pad navigation
|
||||
/// stays inside the column the user is acting on.
|
||||
///
|
||||
/// * Left column ("Stop at") — event-based stop options. Today this is just
|
||||
/// "End of current video"; the column is intentionally open-ended for
|
||||
/// future event triggers (end of next episode, end of chapter, …).
|
||||
/// * Right column ("Timer") — fixed-duration options (5/10/15/30/45/60/90/120
|
||||
/// minutes, plus an optional default duration injected from settings).
|
||||
class SleepTimerContent extends StatelessWidget {
|
||||
final Player player;
|
||||
final SleepTimerService sleepTimer;
|
||||
@@ -26,15 +43,37 @@ class SleepTimerContent extends StatelessWidget {
|
||||
listenable: sleepTimer,
|
||||
builder: (context, _) {
|
||||
final remainingTime = sleepTimer.remainingTime;
|
||||
// Active status renders either with a countdown (duration timer) or
|
||||
// without (end-of-video mode). Both share the same widget.
|
||||
final showActiveStatus = sleepTimer.isActive && (remainingTime != null || sleepTimer.isEndOfVideoMode);
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
if (sleepTimer.isActive && remainingTime != null) ...[
|
||||
if (showActiveStatus) ...[
|
||||
SleepTimerActiveStatus(sleepTimer: sleepTimer, remainingTime: remainingTime, onCancel: onCancel),
|
||||
Divider(color: Theme.of(context).dividerColor, height: 1),
|
||||
],
|
||||
Expanded(
|
||||
child: SleepTimerDurationList(player: player, sleepTimer: sleepTimer, defaultDuration: defaultDuration),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: FocusTraversalGroup(
|
||||
child: _SleepTimerEventColumn(player: player, sleepTimer: sleepTimer),
|
||||
),
|
||||
),
|
||||
VerticalDivider(width: 1, color: Theme.of(context).dividerColor),
|
||||
Expanded(
|
||||
child: FocusTraversalGroup(
|
||||
child: _SleepTimerDurationColumn(
|
||||
player: player,
|
||||
sleepTimer: sleepTimer,
|
||||
defaultDuration: defaultDuration,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -42,3 +81,103 @@ class SleepTimerContent extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SleepTimerEventColumn extends StatelessWidget {
|
||||
final Player player;
|
||||
final SleepTimerService sleepTimer;
|
||||
|
||||
const _SleepTimerEventColumn({required this.player, required this.sleepTimer});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final label = t.videoControls.sleepTimerEndOfVideo;
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
SheetColumnHeader(label: t.videoControls.sleepTimerStopAtHeader),
|
||||
Expanded(
|
||||
child: ListView(
|
||||
children: [
|
||||
FocusableListTile(
|
||||
leading: AppIcon(
|
||||
Symbols.hourglass_bottom_rounded,
|
||||
fill: 1,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
title: Text(label),
|
||||
selected: sleepTimer.isEndOfVideoMode,
|
||||
onTap: () {
|
||||
sleepTimer.armEndOfVideo(() {
|
||||
// Pause playback when the current video ends
|
||||
player.pause();
|
||||
});
|
||||
OverlaySheetController.closeAdaptive(context);
|
||||
|
||||
showSuccessSnackBar(context, t.messages.sleepTimerSet(label: label));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SleepTimerDurationColumn extends StatelessWidget {
|
||||
final Player player;
|
||||
final SleepTimerService sleepTimer;
|
||||
final int? defaultDuration;
|
||||
|
||||
const _SleepTimerDurationColumn({required this.player, required this.sleepTimer, this.defaultDuration});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final durations = [5, 10, 15, 30, 45, 60, 90, 120];
|
||||
// Add default duration if provided and not already in list
|
||||
if (defaultDuration != null && !durations.contains(defaultDuration)) {
|
||||
durations.add(defaultDuration!);
|
||||
durations.sort();
|
||||
}
|
||||
|
||||
// Highlight the currently running duration timer (end-of-video mode is
|
||||
// handled by the event column and intentionally does not light up here).
|
||||
final activeMinutes = sleepTimer.isActive && !sleepTimer.isEndOfVideoMode
|
||||
? sleepTimer.originalDuration?.inMinutes
|
||||
: null;
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
SheetColumnHeader(label: t.videoControls.sleepTimerDurationHeader),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: durations.length,
|
||||
itemBuilder: (context, index) {
|
||||
final minutes = durations[index];
|
||||
final label = formatDurationTextual(
|
||||
minutes * 60 * 1000, // Convert minutes to milliseconds
|
||||
abbreviated: false, // Use full format for better readability
|
||||
);
|
||||
|
||||
return FocusableListTile(
|
||||
leading: AppIcon(Symbols.timer_rounded, fill: 1, color: Theme.of(context).colorScheme.onSurfaceVariant),
|
||||
title: Text(label),
|
||||
selected: minutes == activeMinutes,
|
||||
onTap: () {
|
||||
sleepTimer.startTimer(Duration(minutes: minutes), () {
|
||||
// Pause playback when timer completes
|
||||
player.pause();
|
||||
});
|
||||
OverlaySheetController.closeAdaptive(context);
|
||||
|
||||
// Show confirmation snackbar
|
||||
showSuccessSnackBar(context, t.messages.sleepTimerSet(label: label));
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:plezy/widgets/app_icon.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
|
||||
import '../../../mpv/mpv.dart';
|
||||
import '../../../services/sleep_timer_service.dart';
|
||||
import '../../../utils/formatters.dart';
|
||||
import '../../../utils/snackbar_helper.dart';
|
||||
import '../../../widgets/overlay_sheet.dart';
|
||||
import '../../../i18n/strings.g.dart';
|
||||
|
||||
class SleepTimerDurationList extends StatelessWidget {
|
||||
final Player player;
|
||||
final SleepTimerService sleepTimer;
|
||||
final int? defaultDuration;
|
||||
|
||||
const SleepTimerDurationList({super.key, required this.player, required this.sleepTimer, this.defaultDuration});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final durations = [5, 10, 15, 30, 45, 60, 90, 120];
|
||||
// Add default duration if provided and not already in list
|
||||
if (defaultDuration != null && !durations.contains(defaultDuration)) {
|
||||
durations.add(defaultDuration!);
|
||||
durations.sort();
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
itemCount: durations.length,
|
||||
itemBuilder: (context, index) {
|
||||
final minutes = durations[index];
|
||||
final label = formatDurationTextual(
|
||||
minutes * 60 * 1000, // Convert minutes to milliseconds
|
||||
abbreviated: false, // Use full format for better readability
|
||||
);
|
||||
|
||||
return ListTile(
|
||||
leading: AppIcon(Symbols.timer_rounded, fill: 1, color: Theme.of(context).colorScheme.onSurfaceVariant),
|
||||
title: Text(label),
|
||||
onTap: () {
|
||||
sleepTimer.startTimer(Duration(minutes: minutes), () {
|
||||
// Pause playback when timer completes
|
||||
player.pause();
|
||||
});
|
||||
OverlaySheetController.closeAdaptive(context);
|
||||
|
||||
// Show confirmation snackbar
|
||||
showSuccessSnackBar(context, t.messages.sleepTimerSet(label: label));
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -287,6 +287,120 @@ void main() {
|
||||
});
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// armEndOfVideo / notifyVideoCompleted
|
||||
// ============================================================
|
||||
|
||||
group('armEndOfVideo', () {
|
||||
test('sets isActive and isEndOfVideoMode without starting a periodic timer', () {
|
||||
timer.armEndOfVideo(() {});
|
||||
try {
|
||||
expect(timer.isActive, isTrue);
|
||||
expect(timer.isEndOfVideoMode, isTrue);
|
||||
// No fixed duration / endTime in this mode — countdown UIs must
|
||||
// detect end-of-video mode instead of falling through.
|
||||
expect(timer.endTime, isNull);
|
||||
expect(timer.duration, isNull);
|
||||
expect(timer.originalDuration, isNull);
|
||||
expect(timer.remainingTime, isNull);
|
||||
} finally {
|
||||
timer.cancelTimer();
|
||||
}
|
||||
});
|
||||
|
||||
test('replaces any running duration-based timer', () {
|
||||
var firstFired = false;
|
||||
timer.startTimer(const Duration(minutes: 30), () => firstFired = true);
|
||||
expect(timer.isEndOfVideoMode, isFalse);
|
||||
|
||||
timer.armEndOfVideo(() {});
|
||||
expect(timer.isEndOfVideoMode, isTrue);
|
||||
// The previous duration is gone — armEndOfVideo calls cancelTimer first.
|
||||
expect(timer.originalDuration, isNull);
|
||||
expect(firstFired, isFalse);
|
||||
|
||||
timer.cancelTimer();
|
||||
});
|
||||
|
||||
test('cancelTimer clears end-of-video mode', () {
|
||||
timer.armEndOfVideo(() {});
|
||||
timer.cancelTimer();
|
||||
expect(timer.isActive, isFalse);
|
||||
expect(timer.isEndOfVideoMode, isFalse);
|
||||
});
|
||||
|
||||
test('arming notifies listeners', () {
|
||||
var notifications = 0;
|
||||
void listener() => notifications++;
|
||||
timer.addListener(listener);
|
||||
|
||||
timer.armEndOfVideo(() {});
|
||||
// cancelTimer (called inside armEndOfVideo when idle) is gated on existing
|
||||
// state, so a fresh service only emits the single arm notification.
|
||||
expect(notifications, greaterThanOrEqualTo(1));
|
||||
|
||||
timer.removeListener(listener);
|
||||
timer.cancelTimer();
|
||||
});
|
||||
});
|
||||
|
||||
group('notifyVideoCompleted', () {
|
||||
test('fires the stored callback and emits onCompleted', () async {
|
||||
var fired = 0;
|
||||
var completedFired = 0;
|
||||
final sub = timer.onCompleted.listen((_) => completedFired++);
|
||||
|
||||
timer.armEndOfVideo(() => fired++);
|
||||
timer.notifyVideoCompleted();
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
|
||||
expect(fired, 1);
|
||||
expect(completedFired, 1);
|
||||
// Mode is consumed after firing.
|
||||
expect(timer.isEndOfVideoMode, isFalse);
|
||||
expect(timer.isActive, isFalse);
|
||||
|
||||
await sub.cancel();
|
||||
});
|
||||
|
||||
test('does nothing when end-of-video mode is not armed', () async {
|
||||
var completedFired = 0;
|
||||
final sub = timer.onCompleted.listen((_) => completedFired++);
|
||||
|
||||
timer.notifyVideoCompleted();
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
expect(completedFired, 0);
|
||||
|
||||
// Also safe when a duration timer is running — should not interfere.
|
||||
timer.startTimer(const Duration(minutes: 30), () {});
|
||||
timer.notifyVideoCompleted();
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
expect(completedFired, 0);
|
||||
expect(timer.isActive, isTrue);
|
||||
|
||||
await sub.cancel();
|
||||
timer.cancelTimer();
|
||||
});
|
||||
});
|
||||
|
||||
group('end-of-video + restartIfNeeded', () {
|
||||
test('preserves the end-of-video mode across a playback session swap', () {
|
||||
timer.armEndOfVideo(() {});
|
||||
timer.markNeedsRestart();
|
||||
|
||||
var newCallbackHooked = false;
|
||||
timer.restartIfNeeded(() => newCallbackHooked = true);
|
||||
|
||||
expect(timer.isActive, isTrue);
|
||||
expect(timer.isEndOfVideoMode, isTrue);
|
||||
// restartIfNeeded re-arms — the consumer callback should be wired up
|
||||
// but not yet invoked.
|
||||
expect(newCallbackHooked, isFalse);
|
||||
|
||||
timer.cancelTimer();
|
||||
});
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// What's NOT covered (and why)
|
||||
// ============================================================
|
||||
|
||||
Reference in New Issue
Block a user