fix: Web and input device switching in video player

This commit is contained in:
PartyDonut 2025-10-27 20:20:26 +01:00
parent 1eeecdc18f
commit 3b4eec6c4f
5 changed files with 110 additions and 63 deletions

View file

@ -13,6 +13,7 @@ import 'package:fladder/screens/video_player/components/video_player_next_wrappe
import 'package:fladder/screens/video_player/video_player_controls.dart';
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
import 'package:fladder/util/themes_data.dart';
import 'package:fladder/widgets/shared/back_intent_dpad.dart';
class VideoPlayer extends ConsumerStatefulWidget {
const VideoPlayer({super.key});
@ -83,7 +84,8 @@ class _VideoPlayerState extends ConsumerState<VideoPlayer> with WidgetsBindingOb
},
);
return Material(
return BackIntentDpad(
child: Material(
color: Colors.black,
child: Theme(
data: ThemesData.of(context).dark,
@ -119,6 +121,7 @@ class _VideoPlayerState extends ConsumerState<VideoPlayer> with WidgetsBindingOb
),
),
),
),
);
}
}

View file

@ -48,6 +48,8 @@ class DesktopControls extends ConsumerStatefulWidget {
class _DesktopControlsState extends ConsumerState<DesktopControls> {
final GlobalKey _bottomControlsKey = GlobalKey();
late final initInputDevice = AdaptiveLayout.inputDeviceOf(context);
late RestartableTimer timer = RestartableTimer(
const Duration(seconds: 5),
() => mounted ? toggleOverlay(value: false) : null,
@ -95,12 +97,9 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
children: [
Positioned.fill(
child: GestureDetector(
onTap: AdaptiveLayout.inputDeviceOf(context) == InputDevice.pointer
? () => player.playOrPause()
: () => toggleOverlay(),
onDoubleTap: AdaptiveLayout.inputDeviceOf(context) == InputDevice.pointer
? () => fullScreenHelper.toggleFullScreen(ref)
: null,
onTap: initInputDevice == InputDevice.pointer ? () => player.playOrPause() : () => toggleOverlay(),
onDoubleTap:
initInputDevice == InputDevice.pointer ? () => fullScreenHelper.toggleFullScreen(ref) : null,
),
),
if (subtitleWidget != null) subtitleWidget,
@ -245,7 +244,7 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
],
),
),
if (AdaptiveLayout.inputDeviceOf(context) == InputDevice.touch)
if (initInputDevice == InputDevice.touch)
Align(
alignment: Alignment.centerRight,
child: Tooltip(
@ -362,7 +361,7 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (AdaptiveLayout.isDesktop(context))
if (initInputDevice == InputDevice.pointer)
Tooltip(
message: context.localized.stop,
child: IconButton(
@ -379,7 +378,7 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
),
),
},
if (AdaptiveLayout.isDesktop(context) &&
if (initInputDevice == InputDevice.pointer &&
AdaptiveLayout.viewSizeOf(context) > ViewSize.phone) ...[
VideoVolumeSlider(
onChanged: () => resetTimer(),
@ -651,7 +650,7 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
Future<void> clearOverlaySettings() async {
toggleOverlay(value: true);
if (AdaptiveLayout.inputDeviceOf(context) != InputDevice.pointer) {
if (initInputDevice != InputDevice.pointer) {
ScreenBrightness().resetApplicationScreenBrightness();
} else {
disableFullScreen();
@ -717,7 +716,7 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
return true;
case VideoHotKeys.exit:
disableFullScreen();
return true;
return false;
case VideoHotKeys.mute:
if (volume != 0) {
previousVolume = volume;

View file

@ -10,6 +10,7 @@ import 'package:fladder/routes/auto_router.dart';
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
import 'package:fladder/widgets/navigation_scaffold/components/destination_model.dart';
import 'package:fladder/widgets/navigation_scaffold/components/side_navigation_bar.dart';
import 'package:fladder/widgets/shared/back_intent_dpad.dart';
class NavigationBody extends ConsumerStatefulWidget {
final BuildContext parentContext;
@ -64,7 +65,8 @@ class _NavigationBodyState extends ConsumerState<NavigationBody> {
child: widget.child,
);
return FocusTraversalGroup(
return BackIntentDpad(
child: FocusTraversalGroup(
policy: GlobalFallbackTraversalPolicy(fallbackNode: navBarNode),
child: switch (AdaptiveLayout.layoutOf(context)) {
ViewSize.phone => paddedChild(),
@ -85,6 +87,7 @@ class _NavigationBodyState extends ConsumerState<NavigationBody> {
scaffoldKey: widget.drawerKey,
)
},
),
);
}

View file

@ -0,0 +1,42 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:auto_route/auto_route.dart';
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
class BackIntentDpad extends StatelessWidget {
final Widget child;
const BackIntentDpad({required this.child, super.key});
@override
Widget build(BuildContext context) {
if (AdaptiveLayout.inputDeviceOf(context) == InputDevice.touch) {
return child;
}
return Shortcuts(
shortcuts: <LogicalKeySet, Intent>{
LogicalKeySet(LogicalKeyboardKey.backspace): const BackIntent(),
},
child: Actions(
actions: <Type, Action<Intent>>{
BackIntent: CallbackAction<BackIntent>(
onInvoke: (intent) async {
final navigator = await context.maybePop();
if (navigator) {
return true;
} else {
return false;
}
},
),
},
child: child,
),
);
}
}
class BackIntent extends Intent {
const BackIntent();
}

View file

@ -56,7 +56,7 @@ class MediaControlsWrapper extends BaseAudioHandler implements VideoPlayerContro
Future<void> init() async {
if (!initializedWrapper) {
initializedWrapper = true;
if (!kIsWeb || Platform.isAndroid) {
if (!kIsWeb && Platform.isAndroid) {
VideoPlayerControlsCallback.setUp(this);
}
await AudioService.init(