Merge branch 'accessibility'
This commit is contained in:
+434
-2
@@ -4,9 +4,9 @@
|
||||
/// To regenerate, run: `dart run slang`
|
||||
///
|
||||
/// Locales: 6
|
||||
/// Strings: 2448 (408 per locale)
|
||||
/// Strings: 2634 (439 per locale)
|
||||
///
|
||||
/// Built on 2025-11-16 at 22:35 UTC
|
||||
/// Built on 2025-11-18 at 05:02 UTC
|
||||
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
@@ -163,6 +163,7 @@ class Translations implements BaseTranslations<AppLocale, Translations> {
|
||||
late final _StringsPinEntryEn pinEntry = _StringsPinEntryEn._(_root);
|
||||
late final _StringsFileInfoEn fileInfo = _StringsFileInfoEn._(_root);
|
||||
late final _StringsMediaMenuEn mediaMenu = _StringsMediaMenuEn._(_root);
|
||||
late final _StringsAccessibilityEn accessibility = _StringsAccessibilityEn._(_root);
|
||||
late final _StringsTooltipsEn tooltips = _StringsTooltipsEn._(_root);
|
||||
late final _StringsVideoControlsEn videoControls = _StringsVideoControlsEn._(_root);
|
||||
late final _StringsUserStatusEn userStatus = _StringsUserStatusEn._(_root);
|
||||
@@ -445,6 +446,23 @@ class _StringsMediaMenuEn {
|
||||
String get fileInfo => 'File Info';
|
||||
}
|
||||
|
||||
// Path: accessibility
|
||||
class _StringsAccessibilityEn {
|
||||
_StringsAccessibilityEn._(this._root);
|
||||
|
||||
final Translations _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
String mediaCardMovie({required Object title}) => '${title}, movie';
|
||||
String mediaCardShow({required Object title}) => '${title}, TV show';
|
||||
String mediaCardEpisode({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}';
|
||||
String mediaCardSeason({required Object title, required Object seasonInfo}) => '${title}, ${seasonInfo}';
|
||||
String get mediaCardWatched => 'watched';
|
||||
String mediaCardPartiallyWatched({required Object percent}) => '${percent} percent watched';
|
||||
String get mediaCardUnwatched => 'unwatched';
|
||||
String get tapToPlay => 'Tap to play';
|
||||
}
|
||||
|
||||
// Path: tooltips
|
||||
class _StringsTooltipsEn {
|
||||
_StringsTooltipsEn._(this._root);
|
||||
@@ -481,6 +499,29 @@ class _StringsVideoControlsEn {
|
||||
String get timerActive => 'Timer Active';
|
||||
String playbackWillPauseIn({required Object duration}) => 'Playback will pause in ${duration}';
|
||||
String get sleepTimerCompleted => 'Sleep timer completed - playback paused';
|
||||
String get playButton => 'Play';
|
||||
String get pauseButton => 'Pause';
|
||||
String seekBackwardButton({required Object seconds}) => 'Seek backward ${seconds} seconds';
|
||||
String seekForwardButton({required Object seconds}) => 'Seek forward ${seconds} seconds';
|
||||
String get previousButton => 'Previous episode';
|
||||
String get nextButton => 'Next episode';
|
||||
String get previousChapterButton => 'Previous chapter';
|
||||
String get nextChapterButton => 'Next chapter';
|
||||
String get volumeButton => 'Volume';
|
||||
String get muteButton => 'Mute';
|
||||
String get unmuteButton => 'Unmute';
|
||||
String get settingsButton => 'Video settings';
|
||||
String get audioTrackButton => 'Audio tracks';
|
||||
String get subtitlesButton => 'Subtitles';
|
||||
String get chaptersButton => 'Chapters';
|
||||
String get versionsButton => 'Video versions';
|
||||
String get aspectRatioButton => 'Aspect ratio';
|
||||
String get fullscreenButton => 'Enter fullscreen';
|
||||
String get exitFullscreenButton => 'Exit fullscreen';
|
||||
String get rotationLockButton => 'Rotation lock';
|
||||
String get timelineSlider => 'Video timeline';
|
||||
String get volumeSlider => 'Volume level';
|
||||
String get backButton => 'Back';
|
||||
}
|
||||
|
||||
// Path: userStatus
|
||||
@@ -907,6 +948,7 @@ class _StringsDe implements Translations {
|
||||
@override late final _StringsPinEntryDe pinEntry = _StringsPinEntryDe._(_root);
|
||||
@override late final _StringsFileInfoDe fileInfo = _StringsFileInfoDe._(_root);
|
||||
@override late final _StringsMediaMenuDe mediaMenu = _StringsMediaMenuDe._(_root);
|
||||
@override late final _StringsAccessibilityDe accessibility = _StringsAccessibilityDe._(_root);
|
||||
@override late final _StringsTooltipsDe tooltips = _StringsTooltipsDe._(_root);
|
||||
@override late final _StringsVideoControlsDe videoControls = _StringsVideoControlsDe._(_root);
|
||||
@override late final _StringsUserStatusDe userStatus = _StringsUserStatusDe._(_root);
|
||||
@@ -1189,6 +1231,23 @@ class _StringsMediaMenuDe implements _StringsMediaMenuEn {
|
||||
@override String get fileInfo => 'Dateiinfo';
|
||||
}
|
||||
|
||||
// Path: accessibility
|
||||
class _StringsAccessibilityDe implements _StringsAccessibilityEn {
|
||||
_StringsAccessibilityDe._(this._root);
|
||||
|
||||
@override final _StringsDe _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
@override String mediaCardMovie({required Object title}) => '${title}, movie';
|
||||
@override String mediaCardShow({required Object title}) => '${title}, TV show';
|
||||
@override String mediaCardEpisode({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}';
|
||||
@override String mediaCardSeason({required Object title, required Object seasonInfo}) => '${title}, ${seasonInfo}';
|
||||
@override String get mediaCardWatched => 'watched';
|
||||
@override String mediaCardPartiallyWatched({required Object percent}) => '${percent} percent watched';
|
||||
@override String get mediaCardUnwatched => 'unwatched';
|
||||
@override String get tapToPlay => 'Tap to play';
|
||||
}
|
||||
|
||||
// Path: tooltips
|
||||
class _StringsTooltipsDe implements _StringsTooltipsEn {
|
||||
_StringsTooltipsDe._(this._root);
|
||||
@@ -1225,6 +1284,29 @@ class _StringsVideoControlsDe implements _StringsVideoControlsEn {
|
||||
@override String get timerActive => 'Timer aktiv';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'Wiedergabe wird pausiert in ${duration}';
|
||||
@override String get sleepTimerCompleted => 'Schlaf-Timer abgelaufen - Wiedergabe pausiert';
|
||||
@override String get playButton => 'Play';
|
||||
@override String get pauseButton => 'Pause';
|
||||
@override String seekBackwardButton({required Object seconds}) => 'Seek backward ${seconds} seconds';
|
||||
@override String seekForwardButton({required Object seconds}) => 'Seek forward ${seconds} seconds';
|
||||
@override String get previousButton => 'Previous episode';
|
||||
@override String get nextButton => 'Next episode';
|
||||
@override String get previousChapterButton => 'Previous chapter';
|
||||
@override String get nextChapterButton => 'Next chapter';
|
||||
@override String get volumeButton => 'Volume';
|
||||
@override String get muteButton => 'Mute';
|
||||
@override String get unmuteButton => 'Unmute';
|
||||
@override String get settingsButton => 'Video settings';
|
||||
@override String get audioTrackButton => 'Audio tracks';
|
||||
@override String get subtitlesButton => 'Subtitles';
|
||||
@override String get chaptersButton => 'Chapters';
|
||||
@override String get versionsButton => 'Video versions';
|
||||
@override String get aspectRatioButton => 'Aspect ratio';
|
||||
@override String get fullscreenButton => 'Enter fullscreen';
|
||||
@override String get exitFullscreenButton => 'Exit fullscreen';
|
||||
@override String get rotationLockButton => 'Rotation lock';
|
||||
@override String get timelineSlider => 'Video timeline';
|
||||
@override String get volumeSlider => 'Volume level';
|
||||
@override String get backButton => 'Back';
|
||||
}
|
||||
|
||||
// Path: userStatus
|
||||
@@ -1651,6 +1733,7 @@ class _StringsIt implements Translations {
|
||||
@override late final _StringsPinEntryIt pinEntry = _StringsPinEntryIt._(_root);
|
||||
@override late final _StringsFileInfoIt fileInfo = _StringsFileInfoIt._(_root);
|
||||
@override late final _StringsMediaMenuIt mediaMenu = _StringsMediaMenuIt._(_root);
|
||||
@override late final _StringsAccessibilityIt accessibility = _StringsAccessibilityIt._(_root);
|
||||
@override late final _StringsTooltipsIt tooltips = _StringsTooltipsIt._(_root);
|
||||
@override late final _StringsVideoControlsIt videoControls = _StringsVideoControlsIt._(_root);
|
||||
@override late final _StringsUserStatusIt userStatus = _StringsUserStatusIt._(_root);
|
||||
@@ -1933,6 +2016,23 @@ class _StringsMediaMenuIt implements _StringsMediaMenuEn {
|
||||
@override String get fileInfo => 'Info sul file';
|
||||
}
|
||||
|
||||
// Path: accessibility
|
||||
class _StringsAccessibilityIt implements _StringsAccessibilityEn {
|
||||
_StringsAccessibilityIt._(this._root);
|
||||
|
||||
@override final _StringsIt _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
@override String mediaCardMovie({required Object title}) => '${title}, movie';
|
||||
@override String mediaCardShow({required Object title}) => '${title}, TV show';
|
||||
@override String mediaCardEpisode({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}';
|
||||
@override String mediaCardSeason({required Object title, required Object seasonInfo}) => '${title}, ${seasonInfo}';
|
||||
@override String get mediaCardWatched => 'watched';
|
||||
@override String mediaCardPartiallyWatched({required Object percent}) => '${percent} percent watched';
|
||||
@override String get mediaCardUnwatched => 'unwatched';
|
||||
@override String get tapToPlay => 'Tap to play';
|
||||
}
|
||||
|
||||
// Path: tooltips
|
||||
class _StringsTooltipsIt implements _StringsTooltipsEn {
|
||||
_StringsTooltipsIt._(this._root);
|
||||
@@ -1969,6 +2069,29 @@ class _StringsVideoControlsIt implements _StringsVideoControlsEn {
|
||||
@override String get timerActive => 'Timer attivo';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'La riproduzione si interromperà tra ${duration}';
|
||||
@override String get sleepTimerCompleted => 'Timer di spegnimento completato - riproduzione in pausa';
|
||||
@override String get playButton => 'Play';
|
||||
@override String get pauseButton => 'Pause';
|
||||
@override String seekBackwardButton({required Object seconds}) => 'Seek backward ${seconds} seconds';
|
||||
@override String seekForwardButton({required Object seconds}) => 'Seek forward ${seconds} seconds';
|
||||
@override String get previousButton => 'Previous episode';
|
||||
@override String get nextButton => 'Next episode';
|
||||
@override String get previousChapterButton => 'Previous chapter';
|
||||
@override String get nextChapterButton => 'Next chapter';
|
||||
@override String get volumeButton => 'Volume';
|
||||
@override String get muteButton => 'Mute';
|
||||
@override String get unmuteButton => 'Unmute';
|
||||
@override String get settingsButton => 'Video settings';
|
||||
@override String get audioTrackButton => 'Audio tracks';
|
||||
@override String get subtitlesButton => 'Subtitles';
|
||||
@override String get chaptersButton => 'Chapters';
|
||||
@override String get versionsButton => 'Video versions';
|
||||
@override String get aspectRatioButton => 'Aspect ratio';
|
||||
@override String get fullscreenButton => 'Enter fullscreen';
|
||||
@override String get exitFullscreenButton => 'Exit fullscreen';
|
||||
@override String get rotationLockButton => 'Rotation lock';
|
||||
@override String get timelineSlider => 'Video timeline';
|
||||
@override String get volumeSlider => 'Volume level';
|
||||
@override String get backButton => 'Back';
|
||||
}
|
||||
|
||||
// Path: userStatus
|
||||
@@ -2395,6 +2518,7 @@ class _StringsNl implements Translations {
|
||||
@override late final _StringsPinEntryNl pinEntry = _StringsPinEntryNl._(_root);
|
||||
@override late final _StringsFileInfoNl fileInfo = _StringsFileInfoNl._(_root);
|
||||
@override late final _StringsMediaMenuNl mediaMenu = _StringsMediaMenuNl._(_root);
|
||||
@override late final _StringsAccessibilityNl accessibility = _StringsAccessibilityNl._(_root);
|
||||
@override late final _StringsTooltipsNl tooltips = _StringsTooltipsNl._(_root);
|
||||
@override late final _StringsVideoControlsNl videoControls = _StringsVideoControlsNl._(_root);
|
||||
@override late final _StringsUserStatusNl userStatus = _StringsUserStatusNl._(_root);
|
||||
@@ -2677,6 +2801,23 @@ class _StringsMediaMenuNl implements _StringsMediaMenuEn {
|
||||
@override String get fileInfo => 'Bestand info';
|
||||
}
|
||||
|
||||
// Path: accessibility
|
||||
class _StringsAccessibilityNl implements _StringsAccessibilityEn {
|
||||
_StringsAccessibilityNl._(this._root);
|
||||
|
||||
@override final _StringsNl _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
@override String mediaCardMovie({required Object title}) => '${title}, movie';
|
||||
@override String mediaCardShow({required Object title}) => '${title}, TV show';
|
||||
@override String mediaCardEpisode({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}';
|
||||
@override String mediaCardSeason({required Object title, required Object seasonInfo}) => '${title}, ${seasonInfo}';
|
||||
@override String get mediaCardWatched => 'watched';
|
||||
@override String mediaCardPartiallyWatched({required Object percent}) => '${percent} percent watched';
|
||||
@override String get mediaCardUnwatched => 'unwatched';
|
||||
@override String get tapToPlay => 'Tap to play';
|
||||
}
|
||||
|
||||
// Path: tooltips
|
||||
class _StringsTooltipsNl implements _StringsTooltipsEn {
|
||||
_StringsTooltipsNl._(this._root);
|
||||
@@ -2713,6 +2854,29 @@ class _StringsVideoControlsNl implements _StringsVideoControlsEn {
|
||||
@override String get timerActive => 'Timer actief';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'Afspelen wordt gepauzeerd over ${duration}';
|
||||
@override String get sleepTimerCompleted => 'Slaaptimer voltooid - afspelen gepauzeerd';
|
||||
@override String get playButton => 'Play';
|
||||
@override String get pauseButton => 'Pause';
|
||||
@override String seekBackwardButton({required Object seconds}) => 'Seek backward ${seconds} seconds';
|
||||
@override String seekForwardButton({required Object seconds}) => 'Seek forward ${seconds} seconds';
|
||||
@override String get previousButton => 'Previous episode';
|
||||
@override String get nextButton => 'Next episode';
|
||||
@override String get previousChapterButton => 'Previous chapter';
|
||||
@override String get nextChapterButton => 'Next chapter';
|
||||
@override String get volumeButton => 'Volume';
|
||||
@override String get muteButton => 'Mute';
|
||||
@override String get unmuteButton => 'Unmute';
|
||||
@override String get settingsButton => 'Video settings';
|
||||
@override String get audioTrackButton => 'Audio tracks';
|
||||
@override String get subtitlesButton => 'Subtitles';
|
||||
@override String get chaptersButton => 'Chapters';
|
||||
@override String get versionsButton => 'Video versions';
|
||||
@override String get aspectRatioButton => 'Aspect ratio';
|
||||
@override String get fullscreenButton => 'Enter fullscreen';
|
||||
@override String get exitFullscreenButton => 'Exit fullscreen';
|
||||
@override String get rotationLockButton => 'Rotation lock';
|
||||
@override String get timelineSlider => 'Video timeline';
|
||||
@override String get volumeSlider => 'Volume level';
|
||||
@override String get backButton => 'Back';
|
||||
}
|
||||
|
||||
// Path: userStatus
|
||||
@@ -3139,6 +3303,7 @@ class _StringsSv implements Translations {
|
||||
@override late final _StringsPinEntrySv pinEntry = _StringsPinEntrySv._(_root);
|
||||
@override late final _StringsFileInfoSv fileInfo = _StringsFileInfoSv._(_root);
|
||||
@override late final _StringsMediaMenuSv mediaMenu = _StringsMediaMenuSv._(_root);
|
||||
@override late final _StringsAccessibilitySv accessibility = _StringsAccessibilitySv._(_root);
|
||||
@override late final _StringsTooltipsSv tooltips = _StringsTooltipsSv._(_root);
|
||||
@override late final _StringsVideoControlsSv videoControls = _StringsVideoControlsSv._(_root);
|
||||
@override late final _StringsUserStatusSv userStatus = _StringsUserStatusSv._(_root);
|
||||
@@ -3421,6 +3586,23 @@ class _StringsMediaMenuSv implements _StringsMediaMenuEn {
|
||||
@override String get fileInfo => 'Filinformation';
|
||||
}
|
||||
|
||||
// Path: accessibility
|
||||
class _StringsAccessibilitySv implements _StringsAccessibilityEn {
|
||||
_StringsAccessibilitySv._(this._root);
|
||||
|
||||
@override final _StringsSv _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
@override String mediaCardMovie({required Object title}) => '${title}, movie';
|
||||
@override String mediaCardShow({required Object title}) => '${title}, TV show';
|
||||
@override String mediaCardEpisode({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}';
|
||||
@override String mediaCardSeason({required Object title, required Object seasonInfo}) => '${title}, ${seasonInfo}';
|
||||
@override String get mediaCardWatched => 'watched';
|
||||
@override String mediaCardPartiallyWatched({required Object percent}) => '${percent} percent watched';
|
||||
@override String get mediaCardUnwatched => 'unwatched';
|
||||
@override String get tapToPlay => 'Tap to play';
|
||||
}
|
||||
|
||||
// Path: tooltips
|
||||
class _StringsTooltipsSv implements _StringsTooltipsEn {
|
||||
_StringsTooltipsSv._(this._root);
|
||||
@@ -3457,6 +3639,29 @@ class _StringsVideoControlsSv implements _StringsVideoControlsEn {
|
||||
@override String get timerActive => 'Timer aktiv';
|
||||
@override String playbackWillPauseIn({required Object duration}) => 'Uppspelningen pausas om ${duration}';
|
||||
@override String get sleepTimerCompleted => 'Sovtimer slutförd - uppspelning pausad';
|
||||
@override String get playButton => 'Play';
|
||||
@override String get pauseButton => 'Pause';
|
||||
@override String seekBackwardButton({required Object seconds}) => 'Seek backward ${seconds} seconds';
|
||||
@override String seekForwardButton({required Object seconds}) => 'Seek forward ${seconds} seconds';
|
||||
@override String get previousButton => 'Previous episode';
|
||||
@override String get nextButton => 'Next episode';
|
||||
@override String get previousChapterButton => 'Previous chapter';
|
||||
@override String get nextChapterButton => 'Next chapter';
|
||||
@override String get volumeButton => 'Volume';
|
||||
@override String get muteButton => 'Mute';
|
||||
@override String get unmuteButton => 'Unmute';
|
||||
@override String get settingsButton => 'Video settings';
|
||||
@override String get audioTrackButton => 'Audio tracks';
|
||||
@override String get subtitlesButton => 'Subtitles';
|
||||
@override String get chaptersButton => 'Chapters';
|
||||
@override String get versionsButton => 'Video versions';
|
||||
@override String get aspectRatioButton => 'Aspect ratio';
|
||||
@override String get fullscreenButton => 'Enter fullscreen';
|
||||
@override String get exitFullscreenButton => 'Exit fullscreen';
|
||||
@override String get rotationLockButton => 'Rotation lock';
|
||||
@override String get timelineSlider => 'Video timeline';
|
||||
@override String get volumeSlider => 'Volume level';
|
||||
@override String get backButton => 'Back';
|
||||
}
|
||||
|
||||
// Path: userStatus
|
||||
@@ -3883,6 +4088,7 @@ class _StringsZh implements Translations {
|
||||
@override late final _StringsPinEntryZh pinEntry = _StringsPinEntryZh._(_root);
|
||||
@override late final _StringsFileInfoZh fileInfo = _StringsFileInfoZh._(_root);
|
||||
@override late final _StringsMediaMenuZh mediaMenu = _StringsMediaMenuZh._(_root);
|
||||
@override late final _StringsAccessibilityZh accessibility = _StringsAccessibilityZh._(_root);
|
||||
@override late final _StringsTooltipsZh tooltips = _StringsTooltipsZh._(_root);
|
||||
@override late final _StringsVideoControlsZh videoControls = _StringsVideoControlsZh._(_root);
|
||||
@override late final _StringsUserStatusZh userStatus = _StringsUserStatusZh._(_root);
|
||||
@@ -4165,6 +4371,23 @@ class _StringsMediaMenuZh implements _StringsMediaMenuEn {
|
||||
@override String get fileInfo => '文件信息';
|
||||
}
|
||||
|
||||
// Path: accessibility
|
||||
class _StringsAccessibilityZh implements _StringsAccessibilityEn {
|
||||
_StringsAccessibilityZh._(this._root);
|
||||
|
||||
@override final _StringsZh _root; // ignore: unused_field
|
||||
|
||||
// Translations
|
||||
@override String mediaCardMovie({required Object title}) => '${title}, movie';
|
||||
@override String mediaCardShow({required Object title}) => '${title}, TV show';
|
||||
@override String mediaCardEpisode({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}';
|
||||
@override String mediaCardSeason({required Object title, required Object seasonInfo}) => '${title}, ${seasonInfo}';
|
||||
@override String get mediaCardWatched => 'watched';
|
||||
@override String mediaCardPartiallyWatched({required Object percent}) => '${percent} percent watched';
|
||||
@override String get mediaCardUnwatched => 'unwatched';
|
||||
@override String get tapToPlay => 'Tap to play';
|
||||
}
|
||||
|
||||
// Path: tooltips
|
||||
class _StringsTooltipsZh implements _StringsTooltipsEn {
|
||||
_StringsTooltipsZh._(this._root);
|
||||
@@ -4201,6 +4424,29 @@ class _StringsVideoControlsZh implements _StringsVideoControlsEn {
|
||||
@override String get timerActive => '定时器已激活';
|
||||
@override String playbackWillPauseIn({required Object duration}) => '播放将在 ${duration} 后暂停';
|
||||
@override String get sleepTimerCompleted => '睡眠定时器已完成 - 播放已暂停';
|
||||
@override String get playButton => 'Play';
|
||||
@override String get pauseButton => 'Pause';
|
||||
@override String seekBackwardButton({required Object seconds}) => 'Seek backward ${seconds} seconds';
|
||||
@override String seekForwardButton({required Object seconds}) => 'Seek forward ${seconds} seconds';
|
||||
@override String get previousButton => 'Previous episode';
|
||||
@override String get nextButton => 'Next episode';
|
||||
@override String get previousChapterButton => 'Previous chapter';
|
||||
@override String get nextChapterButton => 'Next chapter';
|
||||
@override String get volumeButton => 'Volume';
|
||||
@override String get muteButton => 'Mute';
|
||||
@override String get unmuteButton => 'Unmute';
|
||||
@override String get settingsButton => 'Video settings';
|
||||
@override String get audioTrackButton => 'Audio tracks';
|
||||
@override String get subtitlesButton => 'Subtitles';
|
||||
@override String get chaptersButton => 'Chapters';
|
||||
@override String get versionsButton => 'Video versions';
|
||||
@override String get aspectRatioButton => 'Aspect ratio';
|
||||
@override String get fullscreenButton => 'Enter fullscreen';
|
||||
@override String get exitFullscreenButton => 'Exit fullscreen';
|
||||
@override String get rotationLockButton => 'Rotation lock';
|
||||
@override String get timelineSlider => 'Video timeline';
|
||||
@override String get volumeSlider => 'Volume level';
|
||||
@override String get backButton => 'Back';
|
||||
}
|
||||
|
||||
// Path: userStatus
|
||||
@@ -4761,6 +5007,14 @@ extension on Translations {
|
||||
case 'mediaMenu.goToSeason': return 'Go to season';
|
||||
case 'mediaMenu.shufflePlay': return 'Shuffle Play';
|
||||
case 'mediaMenu.fileInfo': return 'File Info';
|
||||
case 'accessibility.mediaCardMovie': return ({required Object title}) => '${title}, movie';
|
||||
case 'accessibility.mediaCardShow': return ({required Object title}) => '${title}, TV show';
|
||||
case 'accessibility.mediaCardEpisode': return ({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}';
|
||||
case 'accessibility.mediaCardSeason': return ({required Object title, required Object seasonInfo}) => '${title}, ${seasonInfo}';
|
||||
case 'accessibility.mediaCardWatched': return 'watched';
|
||||
case 'accessibility.mediaCardPartiallyWatched': return ({required Object percent}) => '${percent} percent watched';
|
||||
case 'accessibility.mediaCardUnwatched': return 'unwatched';
|
||||
case 'accessibility.tapToPlay': return 'Tap to play';
|
||||
case 'tooltips.shufflePlay': return 'Shuffle play';
|
||||
case 'tooltips.markAsWatched': return 'Mark as watched';
|
||||
case 'tooltips.markAsUnwatched': return 'Mark as unwatched';
|
||||
@@ -4781,6 +5035,29 @@ extension on Translations {
|
||||
case 'videoControls.timerActive': return 'Timer Active';
|
||||
case 'videoControls.playbackWillPauseIn': return ({required Object duration}) => 'Playback will pause in ${duration}';
|
||||
case 'videoControls.sleepTimerCompleted': return 'Sleep timer completed - playback paused';
|
||||
case 'videoControls.playButton': return 'Play';
|
||||
case 'videoControls.pauseButton': return 'Pause';
|
||||
case 'videoControls.seekBackwardButton': return ({required Object seconds}) => 'Seek backward ${seconds} seconds';
|
||||
case 'videoControls.seekForwardButton': return ({required Object seconds}) => 'Seek forward ${seconds} seconds';
|
||||
case 'videoControls.previousButton': return 'Previous episode';
|
||||
case 'videoControls.nextButton': return 'Next episode';
|
||||
case 'videoControls.previousChapterButton': return 'Previous chapter';
|
||||
case 'videoControls.nextChapterButton': return 'Next chapter';
|
||||
case 'videoControls.volumeButton': return 'Volume';
|
||||
case 'videoControls.muteButton': return 'Mute';
|
||||
case 'videoControls.unmuteButton': return 'Unmute';
|
||||
case 'videoControls.settingsButton': return 'Video settings';
|
||||
case 'videoControls.audioTrackButton': return 'Audio tracks';
|
||||
case 'videoControls.subtitlesButton': return 'Subtitles';
|
||||
case 'videoControls.chaptersButton': return 'Chapters';
|
||||
case 'videoControls.versionsButton': return 'Video versions';
|
||||
case 'videoControls.aspectRatioButton': return 'Aspect ratio';
|
||||
case 'videoControls.fullscreenButton': return 'Enter fullscreen';
|
||||
case 'videoControls.exitFullscreenButton': return 'Exit fullscreen';
|
||||
case 'videoControls.rotationLockButton': return 'Rotation lock';
|
||||
case 'videoControls.timelineSlider': return 'Video timeline';
|
||||
case 'videoControls.volumeSlider': return 'Volume level';
|
||||
case 'videoControls.backButton': return 'Back';
|
||||
case 'userStatus.admin': return 'Admin';
|
||||
case 'userStatus.restricted': return 'Restricted';
|
||||
case 'userStatus.protected': return 'Protected';
|
||||
@@ -5177,6 +5454,14 @@ extension on _StringsDe {
|
||||
case 'mediaMenu.goToSeason': return 'Zur Staffel';
|
||||
case 'mediaMenu.shufflePlay': return 'Zufallswiedergabe';
|
||||
case 'mediaMenu.fileInfo': return 'Dateiinfo';
|
||||
case 'accessibility.mediaCardMovie': return ({required Object title}) => '${title}, movie';
|
||||
case 'accessibility.mediaCardShow': return ({required Object title}) => '${title}, TV show';
|
||||
case 'accessibility.mediaCardEpisode': return ({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}';
|
||||
case 'accessibility.mediaCardSeason': return ({required Object title, required Object seasonInfo}) => '${title}, ${seasonInfo}';
|
||||
case 'accessibility.mediaCardWatched': return 'watched';
|
||||
case 'accessibility.mediaCardPartiallyWatched': return ({required Object percent}) => '${percent} percent watched';
|
||||
case 'accessibility.mediaCardUnwatched': return 'unwatched';
|
||||
case 'accessibility.tapToPlay': return 'Tap to play';
|
||||
case 'tooltips.shufflePlay': return 'Zufallswiedergabe';
|
||||
case 'tooltips.markAsWatched': return 'Als gesehen markieren';
|
||||
case 'tooltips.markAsUnwatched': return 'Als ungesehen markieren';
|
||||
@@ -5197,6 +5482,29 @@ extension on _StringsDe {
|
||||
case 'videoControls.timerActive': return 'Timer aktiv';
|
||||
case 'videoControls.playbackWillPauseIn': return ({required Object duration}) => 'Wiedergabe wird pausiert in ${duration}';
|
||||
case 'videoControls.sleepTimerCompleted': return 'Schlaf-Timer abgelaufen - Wiedergabe pausiert';
|
||||
case 'videoControls.playButton': return 'Play';
|
||||
case 'videoControls.pauseButton': return 'Pause';
|
||||
case 'videoControls.seekBackwardButton': return ({required Object seconds}) => 'Seek backward ${seconds} seconds';
|
||||
case 'videoControls.seekForwardButton': return ({required Object seconds}) => 'Seek forward ${seconds} seconds';
|
||||
case 'videoControls.previousButton': return 'Previous episode';
|
||||
case 'videoControls.nextButton': return 'Next episode';
|
||||
case 'videoControls.previousChapterButton': return 'Previous chapter';
|
||||
case 'videoControls.nextChapterButton': return 'Next chapter';
|
||||
case 'videoControls.volumeButton': return 'Volume';
|
||||
case 'videoControls.muteButton': return 'Mute';
|
||||
case 'videoControls.unmuteButton': return 'Unmute';
|
||||
case 'videoControls.settingsButton': return 'Video settings';
|
||||
case 'videoControls.audioTrackButton': return 'Audio tracks';
|
||||
case 'videoControls.subtitlesButton': return 'Subtitles';
|
||||
case 'videoControls.chaptersButton': return 'Chapters';
|
||||
case 'videoControls.versionsButton': return 'Video versions';
|
||||
case 'videoControls.aspectRatioButton': return 'Aspect ratio';
|
||||
case 'videoControls.fullscreenButton': return 'Enter fullscreen';
|
||||
case 'videoControls.exitFullscreenButton': return 'Exit fullscreen';
|
||||
case 'videoControls.rotationLockButton': return 'Rotation lock';
|
||||
case 'videoControls.timelineSlider': return 'Video timeline';
|
||||
case 'videoControls.volumeSlider': return 'Volume level';
|
||||
case 'videoControls.backButton': return 'Back';
|
||||
case 'userStatus.admin': return 'Eigentümer';
|
||||
case 'userStatus.restricted': return 'Eingeschränkt';
|
||||
case 'userStatus.protected': return 'Geschützt';
|
||||
@@ -5593,6 +5901,14 @@ extension on _StringsIt {
|
||||
case 'mediaMenu.goToSeason': return 'Vai alla stagione';
|
||||
case 'mediaMenu.shufflePlay': return 'Riproduzione casuale';
|
||||
case 'mediaMenu.fileInfo': return 'Info sul file';
|
||||
case 'accessibility.mediaCardMovie': return ({required Object title}) => '${title}, movie';
|
||||
case 'accessibility.mediaCardShow': return ({required Object title}) => '${title}, TV show';
|
||||
case 'accessibility.mediaCardEpisode': return ({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}';
|
||||
case 'accessibility.mediaCardSeason': return ({required Object title, required Object seasonInfo}) => '${title}, ${seasonInfo}';
|
||||
case 'accessibility.mediaCardWatched': return 'watched';
|
||||
case 'accessibility.mediaCardPartiallyWatched': return ({required Object percent}) => '${percent} percent watched';
|
||||
case 'accessibility.mediaCardUnwatched': return 'unwatched';
|
||||
case 'accessibility.tapToPlay': return 'Tap to play';
|
||||
case 'tooltips.shufflePlay': return 'Riproduzione casuale';
|
||||
case 'tooltips.markAsWatched': return 'Segna come visto';
|
||||
case 'tooltips.markAsUnwatched': return 'Segna come non visto';
|
||||
@@ -5613,6 +5929,29 @@ extension on _StringsIt {
|
||||
case 'videoControls.timerActive': return 'Timer attivo';
|
||||
case 'videoControls.playbackWillPauseIn': return ({required Object duration}) => 'La riproduzione si interromperà tra ${duration}';
|
||||
case 'videoControls.sleepTimerCompleted': return 'Timer di spegnimento completato - riproduzione in pausa';
|
||||
case 'videoControls.playButton': return 'Play';
|
||||
case 'videoControls.pauseButton': return 'Pause';
|
||||
case 'videoControls.seekBackwardButton': return ({required Object seconds}) => 'Seek backward ${seconds} seconds';
|
||||
case 'videoControls.seekForwardButton': return ({required Object seconds}) => 'Seek forward ${seconds} seconds';
|
||||
case 'videoControls.previousButton': return 'Previous episode';
|
||||
case 'videoControls.nextButton': return 'Next episode';
|
||||
case 'videoControls.previousChapterButton': return 'Previous chapter';
|
||||
case 'videoControls.nextChapterButton': return 'Next chapter';
|
||||
case 'videoControls.volumeButton': return 'Volume';
|
||||
case 'videoControls.muteButton': return 'Mute';
|
||||
case 'videoControls.unmuteButton': return 'Unmute';
|
||||
case 'videoControls.settingsButton': return 'Video settings';
|
||||
case 'videoControls.audioTrackButton': return 'Audio tracks';
|
||||
case 'videoControls.subtitlesButton': return 'Subtitles';
|
||||
case 'videoControls.chaptersButton': return 'Chapters';
|
||||
case 'videoControls.versionsButton': return 'Video versions';
|
||||
case 'videoControls.aspectRatioButton': return 'Aspect ratio';
|
||||
case 'videoControls.fullscreenButton': return 'Enter fullscreen';
|
||||
case 'videoControls.exitFullscreenButton': return 'Exit fullscreen';
|
||||
case 'videoControls.rotationLockButton': return 'Rotation lock';
|
||||
case 'videoControls.timelineSlider': return 'Video timeline';
|
||||
case 'videoControls.volumeSlider': return 'Volume level';
|
||||
case 'videoControls.backButton': return 'Back';
|
||||
case 'userStatus.admin': return 'Admin';
|
||||
case 'userStatus.restricted': return 'Limitato';
|
||||
case 'userStatus.protected': return 'Protetto';
|
||||
@@ -6009,6 +6348,14 @@ extension on _StringsNl {
|
||||
case 'mediaMenu.goToSeason': return 'Ga naar seizoen';
|
||||
case 'mediaMenu.shufflePlay': return 'Willekeurig afspelen';
|
||||
case 'mediaMenu.fileInfo': return 'Bestand info';
|
||||
case 'accessibility.mediaCardMovie': return ({required Object title}) => '${title}, movie';
|
||||
case 'accessibility.mediaCardShow': return ({required Object title}) => '${title}, TV show';
|
||||
case 'accessibility.mediaCardEpisode': return ({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}';
|
||||
case 'accessibility.mediaCardSeason': return ({required Object title, required Object seasonInfo}) => '${title}, ${seasonInfo}';
|
||||
case 'accessibility.mediaCardWatched': return 'watched';
|
||||
case 'accessibility.mediaCardPartiallyWatched': return ({required Object percent}) => '${percent} percent watched';
|
||||
case 'accessibility.mediaCardUnwatched': return 'unwatched';
|
||||
case 'accessibility.tapToPlay': return 'Tap to play';
|
||||
case 'tooltips.shufflePlay': return 'Willekeurig afspelen';
|
||||
case 'tooltips.markAsWatched': return 'Markeer als gekeken';
|
||||
case 'tooltips.markAsUnwatched': return 'Markeer als ongekeken';
|
||||
@@ -6029,6 +6376,29 @@ extension on _StringsNl {
|
||||
case 'videoControls.timerActive': return 'Timer actief';
|
||||
case 'videoControls.playbackWillPauseIn': return ({required Object duration}) => 'Afspelen wordt gepauzeerd over ${duration}';
|
||||
case 'videoControls.sleepTimerCompleted': return 'Slaaptimer voltooid - afspelen gepauzeerd';
|
||||
case 'videoControls.playButton': return 'Play';
|
||||
case 'videoControls.pauseButton': return 'Pause';
|
||||
case 'videoControls.seekBackwardButton': return ({required Object seconds}) => 'Seek backward ${seconds} seconds';
|
||||
case 'videoControls.seekForwardButton': return ({required Object seconds}) => 'Seek forward ${seconds} seconds';
|
||||
case 'videoControls.previousButton': return 'Previous episode';
|
||||
case 'videoControls.nextButton': return 'Next episode';
|
||||
case 'videoControls.previousChapterButton': return 'Previous chapter';
|
||||
case 'videoControls.nextChapterButton': return 'Next chapter';
|
||||
case 'videoControls.volumeButton': return 'Volume';
|
||||
case 'videoControls.muteButton': return 'Mute';
|
||||
case 'videoControls.unmuteButton': return 'Unmute';
|
||||
case 'videoControls.settingsButton': return 'Video settings';
|
||||
case 'videoControls.audioTrackButton': return 'Audio tracks';
|
||||
case 'videoControls.subtitlesButton': return 'Subtitles';
|
||||
case 'videoControls.chaptersButton': return 'Chapters';
|
||||
case 'videoControls.versionsButton': return 'Video versions';
|
||||
case 'videoControls.aspectRatioButton': return 'Aspect ratio';
|
||||
case 'videoControls.fullscreenButton': return 'Enter fullscreen';
|
||||
case 'videoControls.exitFullscreenButton': return 'Exit fullscreen';
|
||||
case 'videoControls.rotationLockButton': return 'Rotation lock';
|
||||
case 'videoControls.timelineSlider': return 'Video timeline';
|
||||
case 'videoControls.volumeSlider': return 'Volume level';
|
||||
case 'videoControls.backButton': return 'Back';
|
||||
case 'userStatus.admin': return 'Beheerder';
|
||||
case 'userStatus.restricted': return 'Beperkt';
|
||||
case 'userStatus.protected': return 'Beschermd';
|
||||
@@ -6425,6 +6795,14 @@ extension on _StringsSv {
|
||||
case 'mediaMenu.goToSeason': return 'Gå till säsong';
|
||||
case 'mediaMenu.shufflePlay': return 'Blanda uppspelning';
|
||||
case 'mediaMenu.fileInfo': return 'Filinformation';
|
||||
case 'accessibility.mediaCardMovie': return ({required Object title}) => '${title}, movie';
|
||||
case 'accessibility.mediaCardShow': return ({required Object title}) => '${title}, TV show';
|
||||
case 'accessibility.mediaCardEpisode': return ({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}';
|
||||
case 'accessibility.mediaCardSeason': return ({required Object title, required Object seasonInfo}) => '${title}, ${seasonInfo}';
|
||||
case 'accessibility.mediaCardWatched': return 'watched';
|
||||
case 'accessibility.mediaCardPartiallyWatched': return ({required Object percent}) => '${percent} percent watched';
|
||||
case 'accessibility.mediaCardUnwatched': return 'unwatched';
|
||||
case 'accessibility.tapToPlay': return 'Tap to play';
|
||||
case 'tooltips.shufflePlay': return 'Blanda uppspelning';
|
||||
case 'tooltips.markAsWatched': return 'Markera som sedd';
|
||||
case 'tooltips.markAsUnwatched': return 'Markera som osedd';
|
||||
@@ -6445,6 +6823,29 @@ extension on _StringsSv {
|
||||
case 'videoControls.timerActive': return 'Timer aktiv';
|
||||
case 'videoControls.playbackWillPauseIn': return ({required Object duration}) => 'Uppspelningen pausas om ${duration}';
|
||||
case 'videoControls.sleepTimerCompleted': return 'Sovtimer slutförd - uppspelning pausad';
|
||||
case 'videoControls.playButton': return 'Play';
|
||||
case 'videoControls.pauseButton': return 'Pause';
|
||||
case 'videoControls.seekBackwardButton': return ({required Object seconds}) => 'Seek backward ${seconds} seconds';
|
||||
case 'videoControls.seekForwardButton': return ({required Object seconds}) => 'Seek forward ${seconds} seconds';
|
||||
case 'videoControls.previousButton': return 'Previous episode';
|
||||
case 'videoControls.nextButton': return 'Next episode';
|
||||
case 'videoControls.previousChapterButton': return 'Previous chapter';
|
||||
case 'videoControls.nextChapterButton': return 'Next chapter';
|
||||
case 'videoControls.volumeButton': return 'Volume';
|
||||
case 'videoControls.muteButton': return 'Mute';
|
||||
case 'videoControls.unmuteButton': return 'Unmute';
|
||||
case 'videoControls.settingsButton': return 'Video settings';
|
||||
case 'videoControls.audioTrackButton': return 'Audio tracks';
|
||||
case 'videoControls.subtitlesButton': return 'Subtitles';
|
||||
case 'videoControls.chaptersButton': return 'Chapters';
|
||||
case 'videoControls.versionsButton': return 'Video versions';
|
||||
case 'videoControls.aspectRatioButton': return 'Aspect ratio';
|
||||
case 'videoControls.fullscreenButton': return 'Enter fullscreen';
|
||||
case 'videoControls.exitFullscreenButton': return 'Exit fullscreen';
|
||||
case 'videoControls.rotationLockButton': return 'Rotation lock';
|
||||
case 'videoControls.timelineSlider': return 'Video timeline';
|
||||
case 'videoControls.volumeSlider': return 'Volume level';
|
||||
case 'videoControls.backButton': return 'Back';
|
||||
case 'userStatus.admin': return 'Admin';
|
||||
case 'userStatus.restricted': return 'Begränsad';
|
||||
case 'userStatus.protected': return 'Skyddad';
|
||||
@@ -6841,6 +7242,14 @@ extension on _StringsZh {
|
||||
case 'mediaMenu.goToSeason': return '转到季';
|
||||
case 'mediaMenu.shufflePlay': return '随机播放';
|
||||
case 'mediaMenu.fileInfo': return '文件信息';
|
||||
case 'accessibility.mediaCardMovie': return ({required Object title}) => '${title}, movie';
|
||||
case 'accessibility.mediaCardShow': return ({required Object title}) => '${title}, TV show';
|
||||
case 'accessibility.mediaCardEpisode': return ({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}';
|
||||
case 'accessibility.mediaCardSeason': return ({required Object title, required Object seasonInfo}) => '${title}, ${seasonInfo}';
|
||||
case 'accessibility.mediaCardWatched': return 'watched';
|
||||
case 'accessibility.mediaCardPartiallyWatched': return ({required Object percent}) => '${percent} percent watched';
|
||||
case 'accessibility.mediaCardUnwatched': return 'unwatched';
|
||||
case 'accessibility.tapToPlay': return 'Tap to play';
|
||||
case 'tooltips.shufflePlay': return '随机播放';
|
||||
case 'tooltips.markAsWatched': return '标记为已观看';
|
||||
case 'tooltips.markAsUnwatched': return '标记为未观看';
|
||||
@@ -6861,6 +7270,29 @@ extension on _StringsZh {
|
||||
case 'videoControls.timerActive': return '定时器已激活';
|
||||
case 'videoControls.playbackWillPauseIn': return ({required Object duration}) => '播放将在 ${duration} 后暂停';
|
||||
case 'videoControls.sleepTimerCompleted': return '睡眠定时器已完成 - 播放已暂停';
|
||||
case 'videoControls.playButton': return 'Play';
|
||||
case 'videoControls.pauseButton': return 'Pause';
|
||||
case 'videoControls.seekBackwardButton': return ({required Object seconds}) => 'Seek backward ${seconds} seconds';
|
||||
case 'videoControls.seekForwardButton': return ({required Object seconds}) => 'Seek forward ${seconds} seconds';
|
||||
case 'videoControls.previousButton': return 'Previous episode';
|
||||
case 'videoControls.nextButton': return 'Next episode';
|
||||
case 'videoControls.previousChapterButton': return 'Previous chapter';
|
||||
case 'videoControls.nextChapterButton': return 'Next chapter';
|
||||
case 'videoControls.volumeButton': return 'Volume';
|
||||
case 'videoControls.muteButton': return 'Mute';
|
||||
case 'videoControls.unmuteButton': return 'Unmute';
|
||||
case 'videoControls.settingsButton': return 'Video settings';
|
||||
case 'videoControls.audioTrackButton': return 'Audio tracks';
|
||||
case 'videoControls.subtitlesButton': return 'Subtitles';
|
||||
case 'videoControls.chaptersButton': return 'Chapters';
|
||||
case 'videoControls.versionsButton': return 'Video versions';
|
||||
case 'videoControls.aspectRatioButton': return 'Aspect ratio';
|
||||
case 'videoControls.fullscreenButton': return 'Enter fullscreen';
|
||||
case 'videoControls.exitFullscreenButton': return 'Exit fullscreen';
|
||||
case 'videoControls.rotationLockButton': return 'Rotation lock';
|
||||
case 'videoControls.timelineSlider': return 'Video timeline';
|
||||
case 'videoControls.volumeSlider': return 'Volume level';
|
||||
case 'videoControls.backButton': return 'Back';
|
||||
case 'userStatus.admin': return '管理员';
|
||||
case 'userStatus.restricted': return '受限';
|
||||
case 'userStatus.protected': return '受保护';
|
||||
|
||||
@@ -184,6 +184,16 @@
|
||||
"shufflePlay": "Shuffle Play",
|
||||
"fileInfo": "File Info"
|
||||
},
|
||||
"accessibility": {
|
||||
"mediaCardMovie": "${title}, movie",
|
||||
"mediaCardShow": "${title}, TV show",
|
||||
"mediaCardEpisode": "${title}, ${episodeInfo}",
|
||||
"mediaCardSeason": "${title}, ${seasonInfo}",
|
||||
"mediaCardWatched": "watched",
|
||||
"mediaCardPartiallyWatched": "${percent} percent watched",
|
||||
"mediaCardUnwatched": "unwatched",
|
||||
"tapToPlay": "Tap to play"
|
||||
},
|
||||
"tooltips": {
|
||||
"shufflePlay": "Shuffle play",
|
||||
"markAsWatched": "Mark as watched",
|
||||
@@ -206,7 +216,30 @@
|
||||
"sleepTimer": "Sleep Timer",
|
||||
"timerActive": "Timer Active",
|
||||
"playbackWillPauseIn": "Playback will pause in ${duration}",
|
||||
"sleepTimerCompleted": "Sleep timer completed - playback paused"
|
||||
"sleepTimerCompleted": "Sleep timer completed - playback paused",
|
||||
"playButton": "Play",
|
||||
"pauseButton": "Pause",
|
||||
"seekBackwardButton": "Seek backward ${seconds} seconds",
|
||||
"seekForwardButton": "Seek forward ${seconds} seconds",
|
||||
"previousButton": "Previous episode",
|
||||
"nextButton": "Next episode",
|
||||
"previousChapterButton": "Previous chapter",
|
||||
"nextChapterButton": "Next chapter",
|
||||
"volumeButton": "Volume",
|
||||
"muteButton": "Mute",
|
||||
"unmuteButton": "Unmute",
|
||||
"settingsButton": "Video settings",
|
||||
"audioTrackButton": "Audio tracks",
|
||||
"subtitlesButton": "Subtitles",
|
||||
"chaptersButton": "Chapters",
|
||||
"versionsButton": "Video versions",
|
||||
"aspectRatioButton": "Aspect ratio",
|
||||
"fullscreenButton": "Enter fullscreen",
|
||||
"exitFullscreenButton": "Exit fullscreen",
|
||||
"rotationLockButton": "Rotation lock",
|
||||
"timelineSlider": "Video timeline",
|
||||
"volumeSlider": "Volume level",
|
||||
"backButton": "Back"
|
||||
},
|
||||
"userStatus": {
|
||||
"admin": "Admin",
|
||||
|
||||
@@ -184,6 +184,16 @@
|
||||
"shufflePlay": "Zufallswiedergabe",
|
||||
"fileInfo": "Dateiinfo"
|
||||
},
|
||||
"accessibility": {
|
||||
"mediaCardMovie": "${title}, movie",
|
||||
"mediaCardShow": "${title}, TV show",
|
||||
"mediaCardEpisode": "${title}, ${episodeInfo}",
|
||||
"mediaCardSeason": "${title}, ${seasonInfo}",
|
||||
"mediaCardWatched": "watched",
|
||||
"mediaCardPartiallyWatched": "${percent} percent watched",
|
||||
"mediaCardUnwatched": "unwatched",
|
||||
"tapToPlay": "Tap to play"
|
||||
},
|
||||
"tooltips": {
|
||||
"shufflePlay": "Zufallswiedergabe",
|
||||
"markAsWatched": "Als gesehen markieren",
|
||||
@@ -206,7 +216,30 @@
|
||||
"sleepTimer": "Schlaf-Timer",
|
||||
"timerActive": "Timer aktiv",
|
||||
"playbackWillPauseIn": "Wiedergabe wird pausiert in ${duration}",
|
||||
"sleepTimerCompleted": "Schlaf-Timer abgelaufen - Wiedergabe pausiert"
|
||||
"sleepTimerCompleted": "Schlaf-Timer abgelaufen - Wiedergabe pausiert",
|
||||
"playButton": "Play",
|
||||
"pauseButton": "Pause",
|
||||
"seekBackwardButton": "Seek backward ${seconds} seconds",
|
||||
"seekForwardButton": "Seek forward ${seconds} seconds",
|
||||
"previousButton": "Previous episode",
|
||||
"nextButton": "Next episode",
|
||||
"previousChapterButton": "Previous chapter",
|
||||
"nextChapterButton": "Next chapter",
|
||||
"volumeButton": "Volume",
|
||||
"muteButton": "Mute",
|
||||
"unmuteButton": "Unmute",
|
||||
"settingsButton": "Video settings",
|
||||
"audioTrackButton": "Audio tracks",
|
||||
"subtitlesButton": "Subtitles",
|
||||
"chaptersButton": "Chapters",
|
||||
"versionsButton": "Video versions",
|
||||
"aspectRatioButton": "Aspect ratio",
|
||||
"fullscreenButton": "Enter fullscreen",
|
||||
"exitFullscreenButton": "Exit fullscreen",
|
||||
"rotationLockButton": "Rotation lock",
|
||||
"timelineSlider": "Video timeline",
|
||||
"volumeSlider": "Volume level",
|
||||
"backButton": "Back"
|
||||
},
|
||||
"userStatus": {
|
||||
"admin": "Eigentümer",
|
||||
|
||||
@@ -184,6 +184,16 @@
|
||||
"shufflePlay": "Riproduzione casuale",
|
||||
"fileInfo": "Info sul file"
|
||||
},
|
||||
"accessibility": {
|
||||
"mediaCardMovie": "${title}, movie",
|
||||
"mediaCardShow": "${title}, TV show",
|
||||
"mediaCardEpisode": "${title}, ${episodeInfo}",
|
||||
"mediaCardSeason": "${title}, ${seasonInfo}",
|
||||
"mediaCardWatched": "watched",
|
||||
"mediaCardPartiallyWatched": "${percent} percent watched",
|
||||
"mediaCardUnwatched": "unwatched",
|
||||
"tapToPlay": "Tap to play"
|
||||
},
|
||||
"tooltips": {
|
||||
"shufflePlay": "Riproduzione casuale",
|
||||
"markAsWatched": "Segna come visto",
|
||||
@@ -206,7 +216,30 @@
|
||||
"sleepTimer": "Timer di spegnimento",
|
||||
"timerActive": "Timer attivo",
|
||||
"playbackWillPauseIn": "La riproduzione si interromperà tra ${duration}",
|
||||
"sleepTimerCompleted": "Timer di spegnimento completato - riproduzione in pausa"
|
||||
"sleepTimerCompleted": "Timer di spegnimento completato - riproduzione in pausa",
|
||||
"playButton": "Play",
|
||||
"pauseButton": "Pause",
|
||||
"seekBackwardButton": "Seek backward ${seconds} seconds",
|
||||
"seekForwardButton": "Seek forward ${seconds} seconds",
|
||||
"previousButton": "Previous episode",
|
||||
"nextButton": "Next episode",
|
||||
"previousChapterButton": "Previous chapter",
|
||||
"nextChapterButton": "Next chapter",
|
||||
"volumeButton": "Volume",
|
||||
"muteButton": "Mute",
|
||||
"unmuteButton": "Unmute",
|
||||
"settingsButton": "Video settings",
|
||||
"audioTrackButton": "Audio tracks",
|
||||
"subtitlesButton": "Subtitles",
|
||||
"chaptersButton": "Chapters",
|
||||
"versionsButton": "Video versions",
|
||||
"aspectRatioButton": "Aspect ratio",
|
||||
"fullscreenButton": "Enter fullscreen",
|
||||
"exitFullscreenButton": "Exit fullscreen",
|
||||
"rotationLockButton": "Rotation lock",
|
||||
"timelineSlider": "Video timeline",
|
||||
"volumeSlider": "Volume level",
|
||||
"backButton": "Back"
|
||||
},
|
||||
"userStatus": {
|
||||
"admin": "Admin",
|
||||
|
||||
@@ -184,6 +184,16 @@
|
||||
"shufflePlay": "Willekeurig afspelen",
|
||||
"fileInfo": "Bestand info"
|
||||
},
|
||||
"accessibility": {
|
||||
"mediaCardMovie": "${title}, movie",
|
||||
"mediaCardShow": "${title}, TV show",
|
||||
"mediaCardEpisode": "${title}, ${episodeInfo}",
|
||||
"mediaCardSeason": "${title}, ${seasonInfo}",
|
||||
"mediaCardWatched": "watched",
|
||||
"mediaCardPartiallyWatched": "${percent} percent watched",
|
||||
"mediaCardUnwatched": "unwatched",
|
||||
"tapToPlay": "Tap to play"
|
||||
},
|
||||
"tooltips": {
|
||||
"shufflePlay": "Willekeurig afspelen",
|
||||
"markAsWatched": "Markeer als gekeken",
|
||||
@@ -206,7 +216,30 @@
|
||||
"sleepTimer": "Slaaptimer",
|
||||
"timerActive": "Timer actief",
|
||||
"playbackWillPauseIn": "Afspelen wordt gepauzeerd over ${duration}",
|
||||
"sleepTimerCompleted": "Slaaptimer voltooid - afspelen gepauzeerd"
|
||||
"sleepTimerCompleted": "Slaaptimer voltooid - afspelen gepauzeerd",
|
||||
"playButton": "Play",
|
||||
"pauseButton": "Pause",
|
||||
"seekBackwardButton": "Seek backward ${seconds} seconds",
|
||||
"seekForwardButton": "Seek forward ${seconds} seconds",
|
||||
"previousButton": "Previous episode",
|
||||
"nextButton": "Next episode",
|
||||
"previousChapterButton": "Previous chapter",
|
||||
"nextChapterButton": "Next chapter",
|
||||
"volumeButton": "Volume",
|
||||
"muteButton": "Mute",
|
||||
"unmuteButton": "Unmute",
|
||||
"settingsButton": "Video settings",
|
||||
"audioTrackButton": "Audio tracks",
|
||||
"subtitlesButton": "Subtitles",
|
||||
"chaptersButton": "Chapters",
|
||||
"versionsButton": "Video versions",
|
||||
"aspectRatioButton": "Aspect ratio",
|
||||
"fullscreenButton": "Enter fullscreen",
|
||||
"exitFullscreenButton": "Exit fullscreen",
|
||||
"rotationLockButton": "Rotation lock",
|
||||
"timelineSlider": "Video timeline",
|
||||
"volumeSlider": "Volume level",
|
||||
"backButton": "Back"
|
||||
},
|
||||
"userStatus": {
|
||||
"admin": "Beheerder",
|
||||
|
||||
@@ -184,6 +184,16 @@
|
||||
"shufflePlay": "Blanda uppspelning",
|
||||
"fileInfo": "Filinformation"
|
||||
},
|
||||
"accessibility": {
|
||||
"mediaCardMovie": "${title}, movie",
|
||||
"mediaCardShow": "${title}, TV show",
|
||||
"mediaCardEpisode": "${title}, ${episodeInfo}",
|
||||
"mediaCardSeason": "${title}, ${seasonInfo}",
|
||||
"mediaCardWatched": "watched",
|
||||
"mediaCardPartiallyWatched": "${percent} percent watched",
|
||||
"mediaCardUnwatched": "unwatched",
|
||||
"tapToPlay": "Tap to play"
|
||||
},
|
||||
"tooltips": {
|
||||
"shufflePlay": "Blanda uppspelning",
|
||||
"markAsWatched": "Markera som sedd",
|
||||
@@ -206,7 +216,30 @@
|
||||
"sleepTimer": "Sovtimer",
|
||||
"timerActive": "Timer aktiv",
|
||||
"playbackWillPauseIn": "Uppspelningen pausas om ${duration}",
|
||||
"sleepTimerCompleted": "Sovtimer slutförd - uppspelning pausad"
|
||||
"sleepTimerCompleted": "Sovtimer slutförd - uppspelning pausad",
|
||||
"playButton": "Play",
|
||||
"pauseButton": "Pause",
|
||||
"seekBackwardButton": "Seek backward ${seconds} seconds",
|
||||
"seekForwardButton": "Seek forward ${seconds} seconds",
|
||||
"previousButton": "Previous episode",
|
||||
"nextButton": "Next episode",
|
||||
"previousChapterButton": "Previous chapter",
|
||||
"nextChapterButton": "Next chapter",
|
||||
"volumeButton": "Volume",
|
||||
"muteButton": "Mute",
|
||||
"unmuteButton": "Unmute",
|
||||
"settingsButton": "Video settings",
|
||||
"audioTrackButton": "Audio tracks",
|
||||
"subtitlesButton": "Subtitles",
|
||||
"chaptersButton": "Chapters",
|
||||
"versionsButton": "Video versions",
|
||||
"aspectRatioButton": "Aspect ratio",
|
||||
"fullscreenButton": "Enter fullscreen",
|
||||
"exitFullscreenButton": "Exit fullscreen",
|
||||
"rotationLockButton": "Rotation lock",
|
||||
"timelineSlider": "Video timeline",
|
||||
"volumeSlider": "Volume level",
|
||||
"backButton": "Back"
|
||||
},
|
||||
"userStatus": {
|
||||
"admin": "Admin",
|
||||
|
||||
@@ -184,6 +184,16 @@
|
||||
"shufflePlay": "随机播放",
|
||||
"fileInfo": "文件信息"
|
||||
},
|
||||
"accessibility": {
|
||||
"mediaCardMovie": "${title}, movie",
|
||||
"mediaCardShow": "${title}, TV show",
|
||||
"mediaCardEpisode": "${title}, ${episodeInfo}",
|
||||
"mediaCardSeason": "${title}, ${seasonInfo}",
|
||||
"mediaCardWatched": "watched",
|
||||
"mediaCardPartiallyWatched": "${percent} percent watched",
|
||||
"mediaCardUnwatched": "unwatched",
|
||||
"tapToPlay": "Tap to play"
|
||||
},
|
||||
"tooltips": {
|
||||
"shufflePlay": "随机播放",
|
||||
"markAsWatched": "标记为已观看",
|
||||
@@ -206,7 +216,30 @@
|
||||
"sleepTimer": "睡眠定时器",
|
||||
"timerActive": "定时器已激活",
|
||||
"playbackWillPauseIn": "播放将在 ${duration} 后暂停",
|
||||
"sleepTimerCompleted": "睡眠定时器已完成 - 播放已暂停"
|
||||
"sleepTimerCompleted": "睡眠定时器已完成 - 播放已暂停",
|
||||
"playButton": "Play",
|
||||
"pauseButton": "Pause",
|
||||
"seekBackwardButton": "Seek backward ${seconds} seconds",
|
||||
"seekForwardButton": "Seek forward ${seconds} seconds",
|
||||
"previousButton": "Previous episode",
|
||||
"nextButton": "Next episode",
|
||||
"previousChapterButton": "Previous chapter",
|
||||
"nextChapterButton": "Next chapter",
|
||||
"volumeButton": "Volume",
|
||||
"muteButton": "Mute",
|
||||
"unmuteButton": "Unmute",
|
||||
"settingsButton": "Video settings",
|
||||
"audioTrackButton": "Audio tracks",
|
||||
"subtitlesButton": "Subtitles",
|
||||
"chaptersButton": "Chapters",
|
||||
"versionsButton": "Video versions",
|
||||
"aspectRatioButton": "Aspect ratio",
|
||||
"fullscreenButton": "Enter fullscreen",
|
||||
"exitFullscreenButton": "Exit fullscreen",
|
||||
"rotationLockButton": "Rotation lock",
|
||||
"timelineSlider": "Video timeline",
|
||||
"volumeSlider": "Volume level",
|
||||
"backButton": "Back"
|
||||
},
|
||||
"userStatus": {
|
||||
"admin": "管理员",
|
||||
|
||||
@@ -807,11 +807,15 @@ class _DiscoverScreenState extends State<DiscoverScreen>
|
||||
? t.discover.movie
|
||||
: t.discover.tvShow;
|
||||
|
||||
// Build semantic label for hero item
|
||||
final heroLabel = isEpisode
|
||||
? "${heroItem.grandparentTitle}, ${heroItem.title}"
|
||||
: heroItem.title;
|
||||
|
||||
return Semantics(
|
||||
label: "media-hero-${heroItem.ratingKey}",
|
||||
identifier: "media-hero-${heroItem.ratingKey}",
|
||||
label: heroLabel,
|
||||
button: true,
|
||||
hint: "Tap to play ${heroItem.title}",
|
||||
hint: t.accessibility.tapToPlay,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
final clientProvider = context.plexClient;
|
||||
|
||||
@@ -29,11 +29,13 @@ class AppBarBackButton extends StatefulWidget {
|
||||
/// [style] determines the visual appearance of the back button.
|
||||
/// [onPressed] is called when the button is tapped. If null, defaults to Navigator.pop.
|
||||
/// [color] overrides the default icon color. If null, uses white for circular/video, theme default for plain.
|
||||
/// [semanticLabel] provides accessibility label for screen readers.
|
||||
const AppBarBackButton({
|
||||
super.key,
|
||||
this.style = BackButtonStyle.circular,
|
||||
this.onPressed,
|
||||
this.color,
|
||||
this.semanticLabel,
|
||||
});
|
||||
|
||||
/// The visual style of the back button
|
||||
@@ -45,6 +47,9 @@ class AppBarBackButton extends StatefulWidget {
|
||||
/// The color of the back arrow icon. If null, uses style-appropriate default.
|
||||
final Color? color;
|
||||
|
||||
/// Semantic label for screen readers
|
||||
final String? semanticLabel;
|
||||
|
||||
@override
|
||||
State<AppBarBackButton> createState() => _AppBarBackButtonState();
|
||||
}
|
||||
@@ -124,7 +129,7 @@ class _AppBarBackButtonState extends State<AppBarBackButton>
|
||||
break;
|
||||
}
|
||||
|
||||
final button = MouseRegion(
|
||||
final buttonWidget = MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onEnter: (_) => _onHoverChange(true),
|
||||
onExit: (_) => _onHoverChange(false),
|
||||
@@ -154,6 +159,15 @@ class _AppBarBackButtonState extends State<AppBarBackButton>
|
||||
),
|
||||
);
|
||||
|
||||
final button = widget.semanticLabel != null
|
||||
? Semantics(
|
||||
label: widget.semanticLabel,
|
||||
button: true,
|
||||
excludeSemantics: true,
|
||||
child: buttonWidget,
|
||||
)
|
||||
: buttonWidget;
|
||||
|
||||
return widget.style == BackButtonStyle.circular
|
||||
? SafeArea(child: button)
|
||||
: button;
|
||||
|
||||
@@ -49,6 +49,50 @@ class MediaCard extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MediaCardState extends State<MediaCard> {
|
||||
String _buildSemanticLabel() {
|
||||
final item = widget.item;
|
||||
final itemType = item.type.toLowerCase();
|
||||
|
||||
// Build base label based on type
|
||||
String baseLabel;
|
||||
if (itemType == 'episode') {
|
||||
final episodeInfo = item.parentIndex != null && item.index != null
|
||||
? 'S${item.parentIndex} E${item.index}'
|
||||
: '';
|
||||
baseLabel = t.accessibility.mediaCardEpisode(
|
||||
title: item.displayTitle,
|
||||
episodeInfo: episodeInfo,
|
||||
);
|
||||
} else if (itemType == 'season') {
|
||||
final seasonInfo = item.parentIndex != null
|
||||
? 'Season ${item.parentIndex}'
|
||||
: '';
|
||||
baseLabel = t.accessibility.mediaCardSeason(
|
||||
title: item.displayTitle,
|
||||
seasonInfo: seasonInfo,
|
||||
);
|
||||
} else if (itemType == 'movie') {
|
||||
baseLabel = t.accessibility.mediaCardMovie(title: item.displayTitle);
|
||||
} else {
|
||||
baseLabel = t.accessibility.mediaCardShow(title: item.displayTitle);
|
||||
}
|
||||
|
||||
// Add watched status
|
||||
if (item.isWatched) {
|
||||
baseLabel = '$baseLabel, ${t.accessibility.mediaCardWatched}';
|
||||
} else if (item.viewOffset != null &&
|
||||
item.duration != null &&
|
||||
item.viewOffset! > 0) {
|
||||
final percent = ((item.viewOffset! / item.duration!) * 100).round();
|
||||
baseLabel =
|
||||
'$baseLabel, ${t.accessibility.mediaCardPartiallyWatched(percent: percent)}';
|
||||
} else {
|
||||
baseLabel = '$baseLabel, ${t.accessibility.mediaCardUnwatched}';
|
||||
}
|
||||
|
||||
return baseLabel;
|
||||
}
|
||||
|
||||
void _handleTap(BuildContext context) async {
|
||||
final client = context.client;
|
||||
if (client == null) return;
|
||||
@@ -138,15 +182,19 @@ class _MediaCardState extends State<MediaCard> {
|
||||
? ViewMode.grid
|
||||
: settingsProvider.viewMode;
|
||||
|
||||
final semanticLabel = _buildSemanticLabel();
|
||||
|
||||
final cardWidget = viewMode == ViewMode.grid
|
||||
? _MediaCardGrid(
|
||||
item: widget.item,
|
||||
width: widget.width,
|
||||
height: widget.height,
|
||||
semanticLabel: semanticLabel,
|
||||
onTap: () => _handleTap(context),
|
||||
)
|
||||
: _MediaCardList(
|
||||
item: widget.item,
|
||||
semanticLabel: semanticLabel,
|
||||
onTap: () => _handleTap(context),
|
||||
density: settingsProvider.libraryDensity,
|
||||
);
|
||||
@@ -170,12 +218,14 @@ class _MediaCardGrid extends StatelessWidget {
|
||||
final dynamic item; // Can be PlexMetadata or PlexPlaylist
|
||||
final double? width;
|
||||
final double? height;
|
||||
final String semanticLabel;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const _MediaCardGrid({
|
||||
required this.item,
|
||||
this.width,
|
||||
this.height,
|
||||
required this.semanticLabel,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
@@ -184,8 +234,7 @@ class _MediaCardGrid extends StatelessWidget {
|
||||
return SizedBox(
|
||||
width: width,
|
||||
child: Semantics(
|
||||
label: "media-card-${item.ratingKey}",
|
||||
identifier: "media-card-${item.ratingKey}",
|
||||
label: semanticLabel,
|
||||
button: true,
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
@@ -334,11 +383,13 @@ class _MediaCardGrid extends StatelessWidget {
|
||||
/// List layout for media cards
|
||||
class _MediaCardList extends StatelessWidget {
|
||||
final dynamic item; // Can be PlexMetadata or PlexPlaylist
|
||||
final String semanticLabel;
|
||||
final VoidCallback onTap;
|
||||
final LibraryDensity density;
|
||||
|
||||
const _MediaCardList({
|
||||
required this.item,
|
||||
required this.semanticLabel,
|
||||
required this.onTap,
|
||||
required this.density,
|
||||
});
|
||||
@@ -501,8 +552,7 @@ class _MediaCardList extends StatelessWidget {
|
||||
final subtitle = _buildSubtitleText();
|
||||
|
||||
return Semantics(
|
||||
label: "media-card-${item.ratingKey}",
|
||||
identifier: "media-card-${item.ratingKey}",
|
||||
label: semanticLabel,
|
||||
button: true,
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
|
||||
@@ -18,6 +18,10 @@ class VideoControlButton extends StatelessWidget {
|
||||
/// Optional tooltip text shown on hover or long press.
|
||||
final String? tooltip;
|
||||
|
||||
/// Optional semantic label for screen readers.
|
||||
/// If not provided, falls back to tooltip.
|
||||
final String? semanticLabel;
|
||||
|
||||
/// Whether this button represents an active state (e.g., a feature is enabled).
|
||||
/// When true, the icon color defaults to amber instead of white.
|
||||
final bool isActive;
|
||||
@@ -28,6 +32,7 @@ class VideoControlButton extends StatelessWidget {
|
||||
required this.onPressed,
|
||||
this.color,
|
||||
this.tooltip,
|
||||
this.semanticLabel,
|
||||
this.isActive = false,
|
||||
});
|
||||
|
||||
@@ -36,11 +41,20 @@ class VideoControlButton extends StatelessWidget {
|
||||
// Determine the effective color: explicit color > active amber > default white
|
||||
final effectiveColor = color ?? (isActive ? Colors.amber : Colors.white);
|
||||
|
||||
return IconButton(
|
||||
final button = IconButton(
|
||||
icon: Icon(icon, color: effectiveColor),
|
||||
onPressed: onPressed,
|
||||
tooltip: tooltip,
|
||||
constraints: const BoxConstraints(minWidth: 40, minHeight: 40),
|
||||
);
|
||||
|
||||
return semanticLabel != null
|
||||
? Semantics(
|
||||
label: semanticLabel,
|
||||
button: true,
|
||||
excludeSemantics: true,
|
||||
child: button,
|
||||
)
|
||||
: button;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,6 +455,7 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
return VideoControlButton(
|
||||
icon: Icons.tune,
|
||||
isActive: isActive,
|
||||
semanticLabel: t.videoControls.settingsButton,
|
||||
onPressed: () async {
|
||||
await VideoSettingsSheet.show(
|
||||
context,
|
||||
@@ -473,6 +474,7 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
if (_hasMultipleAudioTracks(tracks))
|
||||
VideoControlButton(
|
||||
icon: Icons.audiotrack,
|
||||
semanticLabel: t.videoControls.audioTrackButton,
|
||||
onPressed: () => AudioTrackSheet.show(
|
||||
context,
|
||||
widget.player,
|
||||
@@ -482,6 +484,7 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
if (_hasSubtitles(tracks))
|
||||
VideoControlButton(
|
||||
icon: Icons.subtitles,
|
||||
semanticLabel: t.videoControls.subtitlesButton,
|
||||
onPressed: () => SubtitleTrackSheet.show(
|
||||
context,
|
||||
widget.player,
|
||||
@@ -491,6 +494,7 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
if (_chapters.isNotEmpty)
|
||||
VideoControlButton(
|
||||
icon: Icons.video_library,
|
||||
semanticLabel: t.videoControls.chaptersButton,
|
||||
onPressed: () => ChapterSheet.show(
|
||||
context,
|
||||
widget.player,
|
||||
@@ -501,6 +505,7 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
if (widget.availableVersions.length > 1)
|
||||
VideoControlButton(
|
||||
icon: Icons.video_file,
|
||||
semanticLabel: t.videoControls.versionsButton,
|
||||
onPressed: () => VersionSheet.show(
|
||||
context,
|
||||
widget.availableVersions,
|
||||
@@ -513,6 +518,7 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
VideoControlButton(
|
||||
icon: _getBoxFitIcon(widget.boxFitMode),
|
||||
tooltip: _getBoxFitTooltip(widget.boxFitMode),
|
||||
semanticLabel: t.videoControls.aspectRatioButton,
|
||||
onPressed: widget.onCycleBoxFitMode,
|
||||
),
|
||||
// Rotation lock toggle (mobile only)
|
||||
@@ -524,6 +530,7 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
tooltip: _isRotationLocked
|
||||
? t.videoControls.unlockRotation
|
||||
: t.videoControls.lockRotation,
|
||||
semanticLabel: t.videoControls.rotationLockButton,
|
||||
onPressed: _toggleRotationLock,
|
||||
),
|
||||
// Fullscreen toggle (desktop only)
|
||||
@@ -532,6 +539,9 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
icon: _isFullscreen
|
||||
? Icons.fullscreen_exit
|
||||
: Icons.fullscreen,
|
||||
semanticLabel: _isFullscreen
|
||||
? t.videoControls.exitFullscreenButton
|
||||
: t.videoControls.fullscreenButton,
|
||||
onPressed: _toggleFullscreen,
|
||||
),
|
||||
],
|
||||
@@ -1030,6 +1040,7 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
children: [
|
||||
AppBarBackButton(
|
||||
style: BackButtonStyle.video,
|
||||
semanticLabel: t.videoControls.backButton,
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
@@ -1094,16 +1105,23 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
color: Colors.black.withValues(alpha: 0.5),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
_getReplayIcon(_seekTimeSmall),
|
||||
color: Colors.white,
|
||||
size: 48,
|
||||
child: Semantics(
|
||||
label: t.videoControls.seekBackwardButton(
|
||||
seconds: _seekTimeSmall,
|
||||
),
|
||||
button: true,
|
||||
excludeSemantics: true,
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
_getReplayIcon(_seekTimeSmall),
|
||||
color: Colors.white,
|
||||
size: 48,
|
||||
),
|
||||
iconSize: 48,
|
||||
onPressed: () {
|
||||
_seekWithClamping(Duration(seconds: -_seekTimeSmall));
|
||||
},
|
||||
),
|
||||
iconSize: 48,
|
||||
onPressed: () {
|
||||
_seekWithClamping(Duration(seconds: -_seekTimeSmall));
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 48),
|
||||
@@ -1112,22 +1130,29 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
color: Colors.black.withValues(alpha: 0.5),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
isPlaying ? Icons.pause : Icons.play_arrow,
|
||||
color: Colors.white,
|
||||
size: 72,
|
||||
child: Semantics(
|
||||
label: isPlaying
|
||||
? t.videoControls.pauseButton
|
||||
: t.videoControls.playButton,
|
||||
button: true,
|
||||
excludeSemantics: true,
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
isPlaying ? Icons.pause : Icons.play_arrow,
|
||||
color: Colors.white,
|
||||
size: 72,
|
||||
),
|
||||
iconSize: 72,
|
||||
onPressed: () {
|
||||
if (isPlaying) {
|
||||
widget.player.pause();
|
||||
_hideTimer?.cancel(); // Cancel auto-hide when paused
|
||||
} else {
|
||||
widget.player.play();
|
||||
_startHideTimer(); // Start auto-hide when playing
|
||||
}
|
||||
},
|
||||
),
|
||||
iconSize: 72,
|
||||
onPressed: () {
|
||||
if (isPlaying) {
|
||||
widget.player.pause();
|
||||
_hideTimer?.cancel(); // Cancel auto-hide when paused
|
||||
} else {
|
||||
widget.player.play();
|
||||
_startHideTimer(); // Start auto-hide when playing
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 48),
|
||||
@@ -1136,16 +1161,23 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
color: Colors.black.withValues(alpha: 0.5),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
_getForwardIcon(_seekTimeSmall),
|
||||
color: Colors.white,
|
||||
size: 48,
|
||||
child: Semantics(
|
||||
label: t.videoControls.seekForwardButton(
|
||||
seconds: _seekTimeSmall,
|
||||
),
|
||||
button: true,
|
||||
excludeSemantics: true,
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
_getForwardIcon(_seekTimeSmall),
|
||||
color: Colors.white,
|
||||
size: 48,
|
||||
),
|
||||
iconSize: 48,
|
||||
onPressed: () {
|
||||
_seekWithClamping(Duration(seconds: _seekTimeSmall));
|
||||
},
|
||||
),
|
||||
iconSize: 48,
|
||||
onPressed: () {
|
||||
_seekWithClamping(Duration(seconds: _seekTimeSmall));
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -1235,6 +1267,7 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
children: [
|
||||
AppBarBackButton(
|
||||
style: BackButtonStyle.video,
|
||||
semanticLabel: t.videoControls.backButton,
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
@@ -1360,24 +1393,38 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
Row(
|
||||
children: [
|
||||
// Previous item
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.skip_previous,
|
||||
color: widget.onPrevious != null
|
||||
? Colors.white
|
||||
: Colors.white54,
|
||||
Semantics(
|
||||
label: t.videoControls.previousButton,
|
||||
button: true,
|
||||
excludeSemantics: true,
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
Icons.skip_previous,
|
||||
color: widget.onPrevious != null
|
||||
? Colors.white
|
||||
: Colors.white54,
|
||||
),
|
||||
onPressed: widget.onPrevious,
|
||||
),
|
||||
onPressed: widget.onPrevious,
|
||||
),
|
||||
// Previous chapter (or skip backward if no chapters)
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
_chapters.isEmpty
|
||||
? _getReplayIcon(_seekTimeSmall)
|
||||
: Icons.fast_rewind,
|
||||
color: Colors.white,
|
||||
Semantics(
|
||||
label: _chapters.isEmpty
|
||||
? t.videoControls.seekBackwardButton(
|
||||
seconds: _seekTimeSmall,
|
||||
)
|
||||
: t.videoControls.previousChapterButton,
|
||||
button: true,
|
||||
excludeSemantics: true,
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
_chapters.isEmpty
|
||||
? _getReplayIcon(_seekTimeSmall)
|
||||
: Icons.fast_rewind,
|
||||
color: Colors.white,
|
||||
),
|
||||
onPressed: _seekToPreviousChapter,
|
||||
),
|
||||
onPressed: _seekToPreviousChapter,
|
||||
),
|
||||
// Play/Pause
|
||||
StreamBuilder<bool>(
|
||||
@@ -1385,42 +1432,63 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
initialData: widget.player.state.playing,
|
||||
builder: (context, snapshot) {
|
||||
final isPlaying = snapshot.data ?? false;
|
||||
return IconButton(
|
||||
icon: Icon(
|
||||
isPlaying ? Icons.pause : Icons.play_arrow,
|
||||
color: Colors.white,
|
||||
size: 32,
|
||||
return Semantics(
|
||||
label: isPlaying
|
||||
? t.videoControls.pauseButton
|
||||
: t.videoControls.playButton,
|
||||
button: true,
|
||||
excludeSemantics: true,
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
isPlaying ? Icons.pause : Icons.play_arrow,
|
||||
color: Colors.white,
|
||||
size: 32,
|
||||
),
|
||||
iconSize: 32,
|
||||
onPressed: () {
|
||||
if (isPlaying) {
|
||||
widget.player.pause();
|
||||
_hideTimer?.cancel(); // Cancel auto-hide when paused
|
||||
} else {
|
||||
widget.player.play();
|
||||
_startHideTimer(); // Start auto-hide when playing
|
||||
}
|
||||
},
|
||||
),
|
||||
iconSize: 32,
|
||||
onPressed: () {
|
||||
if (isPlaying) {
|
||||
widget.player.pause();
|
||||
_hideTimer?.cancel(); // Cancel auto-hide when paused
|
||||
} else {
|
||||
widget.player.play();
|
||||
_startHideTimer(); // Start auto-hide when playing
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
// Next chapter (or skip forward if no chapters)
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
_chapters.isEmpty
|
||||
? _getForwardIcon(_seekTimeSmall)
|
||||
: Icons.fast_forward,
|
||||
color: Colors.white,
|
||||
Semantics(
|
||||
label: _chapters.isEmpty
|
||||
? t.videoControls.seekForwardButton(seconds: _seekTimeSmall)
|
||||
: t.videoControls.nextChapterButton,
|
||||
button: true,
|
||||
excludeSemantics: true,
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
_chapters.isEmpty
|
||||
? _getForwardIcon(_seekTimeSmall)
|
||||
: Icons.fast_forward,
|
||||
color: Colors.white,
|
||||
),
|
||||
onPressed: _seekToNextChapter,
|
||||
),
|
||||
onPressed: _seekToNextChapter,
|
||||
),
|
||||
// Next item
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.skip_next,
|
||||
color: widget.onNext != null ? Colors.white : Colors.white54,
|
||||
Semantics(
|
||||
label: t.videoControls.nextButton,
|
||||
button: true,
|
||||
excludeSemantics: true,
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
Icons.skip_next,
|
||||
color: widget.onNext != null
|
||||
? Colors.white
|
||||
: Colors.white54,
|
||||
),
|
||||
onPressed: widget.onNext,
|
||||
),
|
||||
onPressed: widget.onNext,
|
||||
),
|
||||
const Spacer(),
|
||||
// Volume control
|
||||
@@ -1479,20 +1547,24 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
),
|
||||
),
|
||||
// Slider
|
||||
Slider(
|
||||
value: duration.inMilliseconds > 0
|
||||
? position.inMilliseconds.toDouble()
|
||||
: 0.0,
|
||||
min: 0.0,
|
||||
max: duration.inMilliseconds.toDouble(),
|
||||
onChanged: (value) {
|
||||
_throttledSeek(Duration(milliseconds: value.toInt()));
|
||||
},
|
||||
onChangeEnd: (value) {
|
||||
_finalizeSeek(Duration(milliseconds: value.toInt()));
|
||||
},
|
||||
activeColor: Colors.white,
|
||||
inactiveColor: Colors.white.withValues(alpha: 0.3),
|
||||
Semantics(
|
||||
label: t.videoControls.timelineSlider,
|
||||
slider: true,
|
||||
child: Slider(
|
||||
value: duration.inMilliseconds > 0
|
||||
? position.inMilliseconds.toDouble()
|
||||
: 0.0,
|
||||
min: 0.0,
|
||||
max: duration.inMilliseconds.toDouble(),
|
||||
onChanged: (value) {
|
||||
_throttledSeek(Duration(milliseconds: value.toInt()));
|
||||
},
|
||||
onChangeEnd: (value) {
|
||||
_finalizeSeek(Duration(milliseconds: value.toInt()));
|
||||
},
|
||||
activeColor: Colors.white,
|
||||
inactiveColor: Colors.white.withValues(alpha: 0.3),
|
||||
),
|
||||
),
|
||||
// Chapter marker indicators
|
||||
if (_chaptersLoaded &&
|
||||
@@ -1526,19 +1598,26 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
isMuted ? Icons.volume_off : Icons.volume_up,
|
||||
color: Colors.white,
|
||||
Semantics(
|
||||
label: isMuted
|
||||
? t.videoControls.unmuteButton
|
||||
: t.videoControls.muteButton,
|
||||
button: true,
|
||||
excludeSemantics: true,
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
isMuted ? Icons.volume_off : Icons.volume_up,
|
||||
color: Colors.white,
|
||||
),
|
||||
onPressed: () async {
|
||||
final newVolume = isMuted ? 100.0 : 0.0;
|
||||
widget.player.setVolume(newVolume);
|
||||
final settings = await SettingsService.getInstance();
|
||||
await settings.setVolume(newVolume);
|
||||
},
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints(),
|
||||
),
|
||||
onPressed: () async {
|
||||
final newVolume = isMuted ? 100.0 : 0.0;
|
||||
widget.player.setVolume(newVolume);
|
||||
final settings = await SettingsService.getInstance();
|
||||
await settings.setVolume(newVolume);
|
||||
},
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints(),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
SizedBox(
|
||||
@@ -1553,19 +1632,23 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
overlayRadius: 12,
|
||||
),
|
||||
),
|
||||
child: Slider(
|
||||
value: volume,
|
||||
min: 0.0,
|
||||
max: 100.0,
|
||||
onChanged: (value) {
|
||||
widget.player.setVolume(value);
|
||||
},
|
||||
onChangeEnd: (value) async {
|
||||
final settings = await SettingsService.getInstance();
|
||||
await settings.setVolume(value);
|
||||
},
|
||||
activeColor: Colors.white,
|
||||
inactiveColor: Colors.white.withValues(alpha: 0.3),
|
||||
child: Semantics(
|
||||
label: t.videoControls.volumeSlider,
|
||||
slider: true,
|
||||
child: Slider(
|
||||
value: volume,
|
||||
min: 0.0,
|
||||
max: 100.0,
|
||||
onChanged: (value) {
|
||||
widget.player.setVolume(value);
|
||||
},
|
||||
onChangeEnd: (value) async {
|
||||
final settings = await SettingsService.getInstance();
|
||||
await settings.setVolume(value);
|
||||
},
|
||||
activeColor: Colors.white,
|
||||
inactiveColor: Colors.white.withValues(alpha: 0.3),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user