mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-15 02:05:58 -07:00
fix: Keyboard controls and translations (#79)
Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
parent
7394077726
commit
1babf05834
11 changed files with 796 additions and 745 deletions
|
|
@ -19,6 +19,7 @@ import 'package:fladder/screens/playlists/add_to_playlists.dart';
|
|||
import 'package:fladder/screens/video_player/components/video_player_queue.dart';
|
||||
import 'package:fladder/screens/video_player/components/video_subtitle_controls.dart';
|
||||
import 'package:fladder/util/adaptive_layout.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:fladder/util/refresh_state.dart';
|
||||
import 'package:fladder/util/string_extensions.dart';
|
||||
import 'package:fladder/widgets/shared/enum_selection.dart';
|
||||
|
|
@ -91,7 +92,7 @@ class _VideoOptionsMobileState extends ConsumerState<VideoOptions> {
|
|||
title: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Flexible(flex: 1, child: Text("Screen Brightness")),
|
||||
Flexible(flex: 1, child: Text(context.localized.screenBrightness)),
|
||||
Flexible(
|
||||
child: Row(
|
||||
children: [
|
||||
|
|
@ -124,13 +125,13 @@ class _VideoOptionsMobileState extends ConsumerState<VideoOptions> {
|
|||
),
|
||||
),
|
||||
SpacedListTile(
|
||||
title: const Text("Subtitles"),
|
||||
content: Text(currentMediaStreams?.currentSubStream?.displayTitle ?? "Off"),
|
||||
title: Text(context.localized.subtitles),
|
||||
content: Text(currentMediaStreams?.currentSubStream?.label(context) ?? context.localized.off),
|
||||
onTap: currentMediaStreams?.subStreams.isNotEmpty == true ? () => showSubSelection(context) : null,
|
||||
),
|
||||
SpacedListTile(
|
||||
title: const Text("Audio"),
|
||||
content: Text(currentMediaStreams?.currentAudioStream?.displayTitle ?? "Off"),
|
||||
title: Text(context.localized.audio),
|
||||
content: Text(currentMediaStreams?.currentAudioStream?.label(context) ?? context.localized.off),
|
||||
onTap: currentMediaStreams?.audioStreams.isNotEmpty == true ? () => showAudioSelection(context) : null,
|
||||
),
|
||||
ListTile(
|
||||
|
|
@ -139,7 +140,7 @@ class _VideoOptionsMobileState extends ConsumerState<VideoOptions> {
|
|||
children: [
|
||||
Flexible(
|
||||
child: EnumSelection(
|
||||
label: const Text("Scale"),
|
||||
label: Text(context.localized.scale),
|
||||
current: videoSettings.videoFit.name.toUpperCaseSplit(),
|
||||
itemBuilder: (context) => BoxFit.values
|
||||
.map((value) => PopupMenuItem(
|
||||
|
|
@ -159,9 +160,9 @@ class _VideoOptionsMobileState extends ConsumerState<VideoOptions> {
|
|||
title: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Expanded(
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Text("Fill-screen"),
|
||||
child: Text(context.localized.videoScalingFill),
|
||||
),
|
||||
const Spacer(),
|
||||
Switch.adaptive(
|
||||
|
|
@ -235,7 +236,7 @@ class _VideoOptionsMobileState extends ConsumerState<VideoOptions> {
|
|||
widget.minimizePlayer();
|
||||
(this as EpisodeModel).parentBaseModel.navigateTo(context);
|
||||
},
|
||||
title: const Text("Open show"),
|
||||
title: Text(context.localized.openShow),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () async {
|
||||
|
|
@ -243,7 +244,7 @@ class _VideoOptionsMobileState extends ConsumerState<VideoOptions> {
|
|||
widget.minimizePlayer();
|
||||
await currentItem.navigateTo(context);
|
||||
},
|
||||
title: const Text("Show details"),
|
||||
title: Text(context.localized.showDetails),
|
||||
),
|
||||
if (currentItem.type != FladderItemType.boxset)
|
||||
ListTile(
|
||||
|
|
@ -253,7 +254,7 @@ class _VideoOptionsMobileState extends ConsumerState<VideoOptions> {
|
|||
context.refreshData();
|
||||
}
|
||||
},
|
||||
title: const Text("Add to collection"),
|
||||
title: Text(context.localized.addToCollection),
|
||||
),
|
||||
if (currentItem.type != FladderItemType.playlist)
|
||||
ListTile(
|
||||
|
|
@ -263,7 +264,7 @@ class _VideoOptionsMobileState extends ConsumerState<VideoOptions> {
|
|||
context.refreshData();
|
||||
}
|
||||
},
|
||||
title: const Text("Add to playlist"),
|
||||
title: Text(context.localized.addToPlaylist),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () async {
|
||||
|
|
@ -280,14 +281,16 @@ class _VideoOptionsMobileState extends ConsumerState<VideoOptions> {
|
|||
ref.read(playBackModel.notifier).update((state) => playbackModel);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
title: Text(currentItem.userData.isFavourite == true ? "Remove from favorites" : "Add to favourites"),
|
||||
title: Text(currentItem.userData.isFavourite == true
|
||||
? context.localized.removeAsFavorite
|
||||
: context.localized.addAsFavorite),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
showInfoScreen(context, currentItem);
|
||||
},
|
||||
title: const Text('Media info'),
|
||||
title: Text(context.localized.info),
|
||||
),
|
||||
}
|
||||
],
|
||||
|
|
@ -340,14 +343,14 @@ Future<void> showSubSelection(BuildContext context) {
|
|||
contentPadding: const EdgeInsets.only(top: 8, bottom: 24),
|
||||
title: Row(
|
||||
children: [
|
||||
const Text("Subtitle"),
|
||||
Text(context.localized.subtitle),
|
||||
const Spacer(),
|
||||
IconButton.outlined(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
showSubtitleControls(
|
||||
context: context,
|
||||
label: 'Subtitle configuration',
|
||||
label: context.localized.subtitleConfiguration,
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.display_settings_rounded))
|
||||
|
|
@ -357,7 +360,7 @@ Future<void> showSubSelection(BuildContext context) {
|
|||
(index, subModel) {
|
||||
final selected = playbackModel.mediaStreams?.defaultSubStreamIndex == subModel.index;
|
||||
return ListTile(
|
||||
title: Text(subModel.displayTitle),
|
||||
title: Text(subModel.label(context)),
|
||||
tileColor: selected ? Theme.of(context).colorScheme.primary.withOpacity(0.3) : null,
|
||||
subtitle: subModel.language.isNotEmpty
|
||||
? Opacity(opacity: 0.6, child: Text(subModel.language.capitalize()))
|
||||
|
|
@ -391,24 +394,14 @@ Future<void> showAudioSelection(BuildContext context) {
|
|||
contentPadding: const EdgeInsets.only(top: 8, bottom: 24),
|
||||
title: Row(
|
||||
children: [
|
||||
const Text("Subtitle"),
|
||||
const Spacer(),
|
||||
IconButton.outlined(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
showSubtitleControls(
|
||||
context: context,
|
||||
label: 'Subtitle configuration',
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.display_settings_rounded))
|
||||
Text(context.localized.audio),
|
||||
],
|
||||
),
|
||||
children: playbackModel?.audioStreams?.mapIndexed(
|
||||
(index, audioStream) {
|
||||
final selected = playbackModel.mediaStreams?.defaultAudioStreamIndex == audioStream.index;
|
||||
return ListTile(
|
||||
title: Text(audioStream.displayTitle),
|
||||
title: Text(audioStream.label(context)),
|
||||
tileColor: selected ? Theme.of(context).colorScheme.primary.withOpacity(0.3) : null,
|
||||
subtitle: audioStream.language.isNotEmpty
|
||||
? Opacity(opacity: 0.6, child: Text(audioStream.language.capitalize()))
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import 'package:fladder/providers/settings/subtitle_settings_provider.dart';
|
||||
import 'package:fladder/screens/shared/flat_button.dart';
|
||||
import 'package:fladder/util/list_padding.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:fladder/util/widget_extensions.dart';
|
||||
import 'package:fladder/widgets/shared/fladder_slider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
Future<void> showSubtitleControls({
|
||||
required BuildContext context,
|
||||
|
|
@ -18,7 +20,8 @@ Future<void> showSubtitleControls({
|
|||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
content: ConstrainedBox(
|
||||
constraints: BoxConstraints(minWidth: MediaQuery.sizeOf(context).width * 0.75), child: VideoSubtitleControls(label: label)),
|
||||
constraints: BoxConstraints(minWidth: MediaQuery.sizeOf(context).width * 0.75),
|
||||
child: VideoSubtitleControls(label: label)),
|
||||
),
|
||||
);
|
||||
return;
|
||||
|
|
@ -52,6 +55,8 @@ class _VideoSubtitleControlsState extends ConsumerState<VideoSubtitleControls> {
|
|||
final provider = ref.read(subtitleSettingsProvider.notifier);
|
||||
final controlsHidden = hideControls ? false : showPartial;
|
||||
return AnimatedContainer(
|
||||
height: MediaQuery.sizeOf(context).width * 0.85,
|
||||
width: MediaQuery.sizeOf(context).height * 0.7,
|
||||
duration: const Duration(milliseconds: 250),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
|
|
@ -90,7 +95,9 @@ class _VideoSubtitleControlsState extends ConsumerState<VideoSubtitleControls> {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: subSettings != lastSettings ? () => provider.resetSettings(value: lastSettings) : null,
|
||||
onPressed: subSettings != lastSettings
|
||||
? () => provider.resetSettings(value: lastSettings)
|
||||
: null,
|
||||
child: Text(context.localized.clearChanges),
|
||||
),
|
||||
const SizedBox(width: 32),
|
||||
|
|
@ -105,15 +112,18 @@ class _VideoSubtitleControlsState extends ConsumerState<VideoSubtitleControls> {
|
|||
multiSelectionEnabled: false,
|
||||
segments: [
|
||||
ButtonSegment(
|
||||
label: Text(context.localized.light, style: const TextStyle(fontWeight: FontWeight.w100)),
|
||||
label:
|
||||
Text(context.localized.light, style: const TextStyle(fontWeight: FontWeight.w100)),
|
||||
value: FontWeight.w100,
|
||||
),
|
||||
ButtonSegment(
|
||||
label: Text(context.localized.normal, style: const TextStyle(fontWeight: FontWeight.w500)),
|
||||
label:
|
||||
Text(context.localized.normal, style: const TextStyle(fontWeight: FontWeight.w500)),
|
||||
value: FontWeight.normal,
|
||||
),
|
||||
ButtonSegment(
|
||||
label: Text(context.localized.bold, style: const TextStyle(fontWeight: FontWeight.w900)),
|
||||
label:
|
||||
Text(context.localized.bold, style: const TextStyle(fontWeight: FontWeight.w900)),
|
||||
value: FontWeight.bold,
|
||||
),
|
||||
],
|
||||
|
|
@ -210,7 +220,8 @@ class _VideoSubtitleControlsState extends ConsumerState<VideoSubtitleControls> {
|
|||
const Icon(Icons.border_color_rounded),
|
||||
...[Colors.white, Colors.yellow, Colors.black, Colors.grey, Colors.transparent].map(
|
||||
(e) => FlatButton(
|
||||
onTap: () => provider.setOutlineColor(e == Colors.transparent ? e : e.withOpacity(0.85)),
|
||||
onTap: () =>
|
||||
provider.setOutlineColor(e == Colors.transparent ? e : e.withOpacity(0.85)),
|
||||
borderRadiusGeometry: BorderRadius.circular(5),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Container(
|
||||
|
|
@ -290,7 +301,8 @@ class _VideoSubtitleControlsState extends ConsumerState<VideoSubtitleControls> {
|
|||
),
|
||||
Text(context.localized.backgroundOpacity),
|
||||
],
|
||||
).addVisiblity(activeKey == null ? controlsHidden : activeKey == const Key('backGroundOpacity')),
|
||||
).addVisiblity(
|
||||
activeKey == null ? controlsHidden : activeKey == const Key('backGroundOpacity')),
|
||||
Column(
|
||||
children: [
|
||||
Row(
|
||||
|
|
|
|||
|
|
@ -42,6 +42,11 @@ class DesktopControls extends ConsumerStatefulWidget {
|
|||
}
|
||||
|
||||
class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
||||
late RestartableTimer timer = RestartableTimer(
|
||||
const Duration(seconds: 5),
|
||||
() => mounted ? toggleOverlay(value: false) : null,
|
||||
);
|
||||
|
||||
final fadeDuration = const Duration(milliseconds: 350);
|
||||
final focusNode = FocusNode();
|
||||
bool showOverlay = true;
|
||||
|
|
@ -50,6 +55,72 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
|||
late final double topPadding = MediaQuery.of(context).viewPadding.top;
|
||||
late final double bottomPadding = MediaQuery.of(context).viewPadding.bottom;
|
||||
|
||||
bool _onKey(KeyEvent value) {
|
||||
final introSkipModel = ref.read(playBackModel.select((value) => value?.introSkipModel));
|
||||
final position = ref.read(mediaPlaybackProvider).position;
|
||||
bool showIntroSkipButton = introSkipModel?.introInRange(position) ?? false;
|
||||
bool showCreditSkipButton = introSkipModel?.creditsInRange(position) ?? false;
|
||||
if (value is KeyRepeatEvent) {
|
||||
if (value.logicalKey == LogicalKeyboardKey.arrowUp) {
|
||||
resetTimer();
|
||||
ref.read(videoPlayerSettingsProvider.notifier).steppedVolume(5);
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.arrowDown) {
|
||||
resetTimer();
|
||||
ref.read(videoPlayerSettingsProvider.notifier).steppedVolume(-5);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (value is KeyDownEvent) {
|
||||
if (value.logicalKey == LogicalKeyboardKey.keyS) {
|
||||
if (showIntroSkipButton) {
|
||||
skipIntro(introSkipModel);
|
||||
} else if (showCreditSkipButton) {
|
||||
skipCredits(introSkipModel);
|
||||
}
|
||||
focusNode.requestFocus();
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.escape) {
|
||||
disableFullscreen();
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.space) {
|
||||
ref.read(videoPlayerProvider).playOrPause();
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.arrowLeft) {
|
||||
seekBack(ref);
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.arrowRight) {
|
||||
seekForward(ref);
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.keyF) {
|
||||
toggleFullScreen(ref);
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.arrowUp) {
|
||||
resetTimer();
|
||||
ref.read(videoPlayerSettingsProvider.notifier).steppedVolume(5);
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.arrowDown) {
|
||||
resetTimer();
|
||||
ref.read(videoPlayerSettingsProvider.notifier).steppedVolume(-5);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
ServicesBinding.instance.keyboard.addHandler(_onKey);
|
||||
timer.reset();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
ServicesBinding.instance.keyboard.removeHandler(_onKey);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final introSkipModel = ref.watch(playBackModel.select((value) => value?.introSkipModel));
|
||||
|
|
@ -66,121 +137,75 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
|||
closePlayer();
|
||||
}
|
||||
},
|
||||
child: KeyboardListener(
|
||||
focusNode: focusNode,
|
||||
autofocus: AdaptiveLayout.of(context).inputDevice == InputDevice.pointer,
|
||||
onKeyEvent: (value) {
|
||||
final position = ref.read(mediaPlaybackProvider).position;
|
||||
bool showIntroSkipButton = introSkipModel?.introInRange(position) ?? false;
|
||||
bool showCreditSkipButton = introSkipModel?.creditsInRange(position) ?? false;
|
||||
if (value is KeyRepeatEvent) {}
|
||||
if (value is KeyDownEvent) {
|
||||
if (value.logicalKey == LogicalKeyboardKey.keyS) {
|
||||
if (showIntroSkipButton) {
|
||||
skipIntro(introSkipModel);
|
||||
} else if (showCreditSkipButton) {
|
||||
skipCredits(introSkipModel);
|
||||
}
|
||||
focusNode.requestFocus();
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.escape) {
|
||||
disableFullscreen();
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.space) {
|
||||
ref.read(videoPlayerProvider).playOrPause();
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.arrowLeft) {
|
||||
seekBack(ref);
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.arrowRight) {
|
||||
seekForward(ref);
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.keyF) {
|
||||
toggleFullScreen();
|
||||
}
|
||||
if (AdaptiveLayout.of(context).isDesktop || kIsWeb) {
|
||||
if (value.logicalKey == LogicalKeyboardKey.arrowUp) {
|
||||
resetTimer();
|
||||
ref.read(videoPlayerSettingsProvider.notifier).steppedVolume(5);
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.arrowDown) {
|
||||
resetTimer();
|
||||
ref.read(videoPlayerSettingsProvider.notifier).steppedVolume(-5);
|
||||
}
|
||||
}
|
||||
focusNode.requestFocus();
|
||||
}
|
||||
},
|
||||
child: GestureDetector(
|
||||
onTap: () => toggleOverlay(),
|
||||
child: MouseRegion(
|
||||
cursor: showOverlay ? SystemMouseCursors.basic : SystemMouseCursors.none,
|
||||
onEnter: (event) => toggleOverlay(value: true),
|
||||
onExit: (event) => toggleOverlay(value: false),
|
||||
onHover: AdaptiveLayout.of(context).isDesktop || kIsWeb ? (event) => toggleOverlay(value: true) : null,
|
||||
child: Stack(
|
||||
children: [
|
||||
if (player != null)
|
||||
VideoSubtitles(
|
||||
key: const Key('subtitles'),
|
||||
controller: player,
|
||||
overlayed: showOverlay,
|
||||
),
|
||||
if (AdaptiveLayout.of(context).isDesktop)
|
||||
Consumer(builder: (context, ref, child) {
|
||||
final playing = ref.watch(mediaPlaybackProvider.select((value) => value.playing));
|
||||
final buffering = ref.watch(mediaPlaybackProvider.select((value) => value.buffering));
|
||||
return playButton(playing, buffering);
|
||||
}),
|
||||
IgnorePointer(
|
||||
ignoring: !showOverlay,
|
||||
child: AnimatedOpacity(
|
||||
duration: fadeDuration,
|
||||
opacity: showOverlay ? 1 : 0,
|
||||
child: Column(
|
||||
children: [
|
||||
topButtons(context),
|
||||
const Spacer(),
|
||||
bottomButtons(context),
|
||||
],
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () => toggleOverlay(),
|
||||
child: MouseRegion(
|
||||
cursor: showOverlay ? SystemMouseCursors.basic : SystemMouseCursors.none,
|
||||
onEnter: (event) => toggleOverlay(value: true),
|
||||
onExit: (event) => toggleOverlay(value: false),
|
||||
onHover: AdaptiveLayout.of(context).isDesktop || kIsWeb ? (event) => toggleOverlay(value: true) : null,
|
||||
child: Stack(
|
||||
children: [
|
||||
if (player != null)
|
||||
VideoSubtitles(
|
||||
key: const Key('subtitles'),
|
||||
controller: player,
|
||||
overlayed: showOverlay,
|
||||
),
|
||||
if (AdaptiveLayout.of(context).isDesktop)
|
||||
Consumer(builder: (context, ref, child) {
|
||||
final playing = ref.watch(mediaPlaybackProvider.select((value) => value.playing));
|
||||
final buffering = ref.watch(mediaPlaybackProvider.select((value) => value.buffering));
|
||||
return playButton(playing, buffering);
|
||||
}),
|
||||
IgnorePointer(
|
||||
ignoring: !showOverlay,
|
||||
child: AnimatedOpacity(
|
||||
duration: fadeDuration,
|
||||
opacity: showOverlay ? 1 : 0,
|
||||
child: Column(
|
||||
children: [
|
||||
topButtons(context),
|
||||
const Spacer(),
|
||||
bottomButtons(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
Consumer(
|
||||
builder: (context, ref, child) {
|
||||
final position = ref.watch(mediaPlaybackProvider.select((value) => value.position));
|
||||
bool showIntroSkipButton = introSkipModel?.introInRange(position) ?? false;
|
||||
bool showCreditSkipButton = introSkipModel?.creditsInRange(position) ?? false;
|
||||
return Stack(
|
||||
children: [
|
||||
if (showIntroSkipButton)
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: IntroSkipButton(
|
||||
isOverlayVisible: showOverlay,
|
||||
skipIntro: () => skipIntro(introSkipModel),
|
||||
),
|
||||
),
|
||||
Consumer(
|
||||
builder: (context, ref, child) {
|
||||
final position = ref.watch(mediaPlaybackProvider.select((value) => value.position));
|
||||
bool showIntroSkipButton = introSkipModel?.introInRange(position) ?? false;
|
||||
bool showCreditSkipButton = introSkipModel?.creditsInRange(position) ?? false;
|
||||
return Stack(
|
||||
children: [
|
||||
if (showIntroSkipButton)
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: IntroSkipButton(
|
||||
isOverlayVisible: showOverlay,
|
||||
skipIntro: () => skipIntro(introSkipModel),
|
||||
),
|
||||
),
|
||||
if (showCreditSkipButton)
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: CreditsSkipButton(
|
||||
isOverlayVisible: showOverlay,
|
||||
skipCredits: () => skipCredits(introSkipModel),
|
||||
),
|
||||
),
|
||||
if (showCreditSkipButton)
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: CreditsSkipButton(
|
||||
isOverlayVisible: showOverlay,
|
||||
skipCredits: () => skipCredits(introSkipModel),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -317,11 +342,11 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
|||
onPressed: () => showSubSelection(context),
|
||||
icon: const Icon(IconsaxOutline.subtitle),
|
||||
label: Text(
|
||||
ref
|
||||
.watch(playBackModel.select((value) => value?.mediaStreams?.currentSubStream))
|
||||
?.language
|
||||
.capitalize() ??
|
||||
"Off",
|
||||
ref.watch(playBackModel.select((value) {
|
||||
final language = value?.mediaStreams?.currentSubStream?.language;
|
||||
return language?.isEmpty == true ? context.localized.off : language;
|
||||
}))?.capitalize() ??
|
||||
"",
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
|
|
@ -331,11 +356,11 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
|||
onPressed: () => showAudioSelection(context),
|
||||
icon: const Icon(IconsaxOutline.audio_square),
|
||||
label: Text(
|
||||
ref
|
||||
.watch(playBackModel.select((value) => value?.mediaStreams?.currentAudioStream))
|
||||
?.language
|
||||
.capitalize() ??
|
||||
"Off",
|
||||
ref.watch(playBackModel.select((value) {
|
||||
final language = value?.mediaStreams?.currentAudioStream?.language;
|
||||
return language?.isEmpty == true ? context.localized.off : language;
|
||||
}))?.capitalize() ??
|
||||
"",
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
|
|
@ -591,11 +616,6 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
|||
ref.read(videoPlayerProvider).seek(Duration(seconds: newPosition));
|
||||
}
|
||||
|
||||
late RestartableTimer timer = RestartableTimer(
|
||||
const Duration(seconds: 5),
|
||||
() => mounted ? toggleOverlay(value: false) : null,
|
||||
);
|
||||
|
||||
void toggleOverlay({bool? value}) {
|
||||
if (showOverlay == (value ?? !showOverlay)) return;
|
||||
setState(() => showOverlay = (value ?? !showOverlay));
|
||||
|
|
@ -652,9 +672,4 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> toggleFullScreen() async {
|
||||
final isFullScreen = await windowManager.isFullScreen();
|
||||
await windowManager.setFullScreen(!isFullScreen);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue