mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-07 21:48:14 -08:00
fix: Web and input device switching in video player
This commit is contained in:
parent
1eeecdc18f
commit
3b4eec6c4f
5 changed files with 110 additions and 63 deletions
|
|
@ -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/screens/video_player/video_player_controls.dart';
|
||||||
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
|
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
|
||||||
import 'package:fladder/util/themes_data.dart';
|
import 'package:fladder/util/themes_data.dart';
|
||||||
|
import 'package:fladder/widgets/shared/back_intent_dpad.dart';
|
||||||
|
|
||||||
class VideoPlayer extends ConsumerStatefulWidget {
|
class VideoPlayer extends ConsumerStatefulWidget {
|
||||||
const VideoPlayer({super.key});
|
const VideoPlayer({super.key});
|
||||||
|
|
@ -83,38 +84,40 @@ class _VideoPlayerState extends ConsumerState<VideoPlayer> with WidgetsBindingOb
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return Material(
|
return BackIntentDpad(
|
||||||
color: Colors.black,
|
child: Material(
|
||||||
child: Theme(
|
color: Colors.black,
|
||||||
data: ThemesData.of(context).dark,
|
child: Theme(
|
||||||
child: Container(
|
data: ThemesData.of(context).dark,
|
||||||
color: Colors.black,
|
child: Container(
|
||||||
child: GestureDetector(
|
color: Colors.black,
|
||||||
onScaleUpdate: (details) {
|
child: GestureDetector(
|
||||||
lastScale = details.scale;
|
onScaleUpdate: (details) {
|
||||||
},
|
lastScale = details.scale;
|
||||||
onScaleEnd: (details) {
|
},
|
||||||
if (lastScale < 1.0) {
|
onScaleEnd: (details) {
|
||||||
ref.read(videoPlayerSettingsProvider.notifier).setFillScreen(false, context: context);
|
if (lastScale < 1.0) {
|
||||||
} else if (lastScale > 1.0) {
|
ref.read(videoPlayerSettingsProvider.notifier).setFillScreen(false, context: context);
|
||||||
ref.read(videoPlayerSettingsProvider.notifier).setFillScreen(true, context: context);
|
} else if (lastScale > 1.0) {
|
||||||
}
|
ref.read(videoPlayerSettingsProvider.notifier).setFillScreen(true, context: context);
|
||||||
lastScale = 0.0;
|
}
|
||||||
},
|
lastScale = 0.0;
|
||||||
child: VideoPlayerNextWrapper(
|
},
|
||||||
video: Padding(
|
child: VideoPlayerNextWrapper(
|
||||||
padding: fillScreen ? EdgeInsets.zero : EdgeInsets.only(left: padding.left, right: padding.right),
|
video: Padding(
|
||||||
child: playerController.videoWidget(
|
padding: fillScreen ? EdgeInsets.zero : EdgeInsets.only(left: padding.left, right: padding.right),
|
||||||
const Key("VideoPlayer"),
|
child: playerController.videoWidget(
|
||||||
fillScreen
|
const Key("VideoPlayer"),
|
||||||
? (MediaQuery.of(context).orientation == Orientation.portrait ? videoFit : BoxFit.cover)
|
fillScreen
|
||||||
: videoFit,
|
? (MediaQuery.of(context).orientation == Orientation.portrait ? videoFit : BoxFit.cover)
|
||||||
|
: videoFit,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
controls: const DesktopControls(),
|
||||||
|
overlays: [
|
||||||
|
if (errorPlaying) const _VideoErrorWidget(),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
controls: const DesktopControls(),
|
|
||||||
overlays: [
|
|
||||||
if (errorPlaying) const _VideoErrorWidget(),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ class DesktopControls extends ConsumerStatefulWidget {
|
||||||
class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
||||||
final GlobalKey _bottomControlsKey = GlobalKey();
|
final GlobalKey _bottomControlsKey = GlobalKey();
|
||||||
|
|
||||||
|
late final initInputDevice = AdaptiveLayout.inputDeviceOf(context);
|
||||||
|
|
||||||
late RestartableTimer timer = RestartableTimer(
|
late RestartableTimer timer = RestartableTimer(
|
||||||
const Duration(seconds: 5),
|
const Duration(seconds: 5),
|
||||||
() => mounted ? toggleOverlay(value: false) : null,
|
() => mounted ? toggleOverlay(value: false) : null,
|
||||||
|
|
@ -95,12 +97,9 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
||||||
children: [
|
children: [
|
||||||
Positioned.fill(
|
Positioned.fill(
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: AdaptiveLayout.inputDeviceOf(context) == InputDevice.pointer
|
onTap: initInputDevice == InputDevice.pointer ? () => player.playOrPause() : () => toggleOverlay(),
|
||||||
? () => player.playOrPause()
|
onDoubleTap:
|
||||||
: () => toggleOverlay(),
|
initInputDevice == InputDevice.pointer ? () => fullScreenHelper.toggleFullScreen(ref) : null,
|
||||||
onDoubleTap: AdaptiveLayout.inputDeviceOf(context) == InputDevice.pointer
|
|
||||||
? () => fullScreenHelper.toggleFullScreen(ref)
|
|
||||||
: null,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (subtitleWidget != null) subtitleWidget,
|
if (subtitleWidget != null) subtitleWidget,
|
||||||
|
|
@ -245,7 +244,7 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (AdaptiveLayout.inputDeviceOf(context) == InputDevice.touch)
|
if (initInputDevice == InputDevice.touch)
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: Tooltip(
|
child: Tooltip(
|
||||||
|
|
@ -362,7 +361,7 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
if (AdaptiveLayout.isDesktop(context))
|
if (initInputDevice == InputDevice.pointer)
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message: context.localized.stop,
|
message: context.localized.stop,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
|
|
@ -379,7 +378,7 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
if (AdaptiveLayout.isDesktop(context) &&
|
if (initInputDevice == InputDevice.pointer &&
|
||||||
AdaptiveLayout.viewSizeOf(context) > ViewSize.phone) ...[
|
AdaptiveLayout.viewSizeOf(context) > ViewSize.phone) ...[
|
||||||
VideoVolumeSlider(
|
VideoVolumeSlider(
|
||||||
onChanged: () => resetTimer(),
|
onChanged: () => resetTimer(),
|
||||||
|
|
@ -651,7 +650,7 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
||||||
|
|
||||||
Future<void> clearOverlaySettings() async {
|
Future<void> clearOverlaySettings() async {
|
||||||
toggleOverlay(value: true);
|
toggleOverlay(value: true);
|
||||||
if (AdaptiveLayout.inputDeviceOf(context) != InputDevice.pointer) {
|
if (initInputDevice != InputDevice.pointer) {
|
||||||
ScreenBrightness().resetApplicationScreenBrightness();
|
ScreenBrightness().resetApplicationScreenBrightness();
|
||||||
} else {
|
} else {
|
||||||
disableFullScreen();
|
disableFullScreen();
|
||||||
|
|
@ -717,7 +716,7 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
|
||||||
return true;
|
return true;
|
||||||
case VideoHotKeys.exit:
|
case VideoHotKeys.exit:
|
||||||
disableFullScreen();
|
disableFullScreen();
|
||||||
return true;
|
return false;
|
||||||
case VideoHotKeys.mute:
|
case VideoHotKeys.mute:
|
||||||
if (volume != 0) {
|
if (volume != 0) {
|
||||||
previousVolume = volume;
|
previousVolume = volume;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import 'package:fladder/routes/auto_router.dart';
|
||||||
import 'package:fladder/util/adaptive_layout/adaptive_layout.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/destination_model.dart';
|
||||||
import 'package:fladder/widgets/navigation_scaffold/components/side_navigation_bar.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 {
|
class NavigationBody extends ConsumerStatefulWidget {
|
||||||
final BuildContext parentContext;
|
final BuildContext parentContext;
|
||||||
|
|
@ -64,27 +65,29 @@ class _NavigationBodyState extends ConsumerState<NavigationBody> {
|
||||||
child: widget.child,
|
child: widget.child,
|
||||||
);
|
);
|
||||||
|
|
||||||
return FocusTraversalGroup(
|
return BackIntentDpad(
|
||||||
policy: GlobalFallbackTraversalPolicy(fallbackNode: navBarNode),
|
child: FocusTraversalGroup(
|
||||||
child: switch (AdaptiveLayout.layoutOf(context)) {
|
policy: GlobalFallbackTraversalPolicy(fallbackNode: navBarNode),
|
||||||
ViewSize.phone => paddedChild(),
|
child: switch (AdaptiveLayout.layoutOf(context)) {
|
||||||
ViewSize.tablet => hasOverlay
|
ViewSize.phone => paddedChild(),
|
||||||
? SideNavigationBar(
|
ViewSize.tablet => hasOverlay
|
||||||
currentIndex: widget.currentIndex,
|
? SideNavigationBar(
|
||||||
destinations: widget.destinations,
|
currentIndex: widget.currentIndex,
|
||||||
currentLocation: widget.currentLocation,
|
destinations: widget.destinations,
|
||||||
child: paddedChild(),
|
currentLocation: widget.currentLocation,
|
||||||
scaffoldKey: widget.drawerKey,
|
child: paddedChild(),
|
||||||
)
|
scaffoldKey: widget.drawerKey,
|
||||||
: paddedChild(),
|
)
|
||||||
ViewSize.desktop || ViewSize.television => SideNavigationBar(
|
: paddedChild(),
|
||||||
currentIndex: widget.currentIndex,
|
ViewSize.desktop || ViewSize.television => SideNavigationBar(
|
||||||
destinations: widget.destinations,
|
currentIndex: widget.currentIndex,
|
||||||
currentLocation: widget.currentLocation,
|
destinations: widget.destinations,
|
||||||
child: paddedChild(),
|
currentLocation: widget.currentLocation,
|
||||||
scaffoldKey: widget.drawerKey,
|
child: paddedChild(),
|
||||||
)
|
scaffoldKey: widget.drawerKey,
|
||||||
},
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
42
lib/widgets/shared/back_intent_dpad.dart
Normal file
42
lib/widgets/shared/back_intent_dpad.dart
Normal 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();
|
||||||
|
}
|
||||||
|
|
@ -56,7 +56,7 @@ class MediaControlsWrapper extends BaseAudioHandler implements VideoPlayerContro
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
if (!initializedWrapper) {
|
if (!initializedWrapper) {
|
||||||
initializedWrapper = true;
|
initializedWrapper = true;
|
||||||
if (!kIsWeb || Platform.isAndroid) {
|
if (!kIsWeb && Platform.isAndroid) {
|
||||||
VideoPlayerControlsCallback.setUp(this);
|
VideoPlayerControlsCallback.setUp(this);
|
||||||
}
|
}
|
||||||
await AudioService.init(
|
await AudioService.init(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue