@@ -12,6 +12,7 @@ import 'package:chewie/src/models/option_item.dart';
1212import 'package:chewie/src/models/subtitle_model.dart' ;
1313import 'package:chewie/src/notifiers/index.dart' ;
1414import 'package:flutter/material.dart' ;
15+ import 'package:flutter/services.dart' ;
1516import 'package:provider/provider.dart' ;
1617import 'package:video_player/video_player.dart' ;
1718
@@ -49,16 +50,36 @@ class _MaterialDesktopControlsState extends State<MaterialDesktopControls>
4950
5051 late VideoPlayerController controller;
5152 ChewieController ? _chewieController;
53+ late final FocusNode _focusNode;
5254
5355 // We know that _chewieController is set in didChangeDependencies
5456 ChewieController get chewieController => _chewieController! ;
5557
5658 @override
5759 void initState () {
5860 super .initState ();
61+ _focusNode = FocusNode ();
62+ _focusNode.requestFocus ();
5963 notifier = Provider .of <PlayerNotifier >(context, listen: false );
6064 }
6165
66+ void _handleKeyPress (event) {
67+ if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey .space) {
68+ _playPause ();
69+ } else if (event is KeyDownEvent &&
70+ event.logicalKey == LogicalKeyboardKey .arrowRight) {
71+ _seekForward ();
72+ } else if (event is KeyDownEvent &&
73+ event.logicalKey == LogicalKeyboardKey .arrowLeft) {
74+ _seekBackward ();
75+ } else if (event is KeyDownEvent &&
76+ event.logicalKey == LogicalKeyboardKey .escape) {
77+ if (chewieController.isFullScreen) {
78+ _onExpandCollapse ();
79+ }
80+ }
81+ }
82+
6283 @override
6384 Widget build (BuildContext context) {
6485 if (_latestValue.hasError) {
@@ -75,39 +96,44 @@ class _MaterialDesktopControlsState extends State<MaterialDesktopControls>
7596 );
7697 }
7798
78- return MouseRegion (
79- onHover: (_) {
80- _cancelAndRestartTimer ();
81- },
82- child: GestureDetector (
83- onTap: () => _cancelAndRestartTimer (),
84- child: AbsorbPointer (
85- absorbing: notifier.hideStuff,
86- child: Stack (
87- children: [
88- if (_displayBufferingIndicator)
89- _chewieController? .bufferingBuilder? .call (context) ??
90- const Center (
91- child: CircularProgressIndicator (),
92- )
93- else
94- _buildHitArea (),
95- Column (
96- mainAxisAlignment: MainAxisAlignment .end,
97- children: < Widget > [
98- if (_subtitleOn)
99- Transform .translate (
100- offset: Offset (
101- 0.0 ,
102- notifier.hideStuff ? barHeight * 0.8 : 0.0 ,
99+ return KeyboardListener (
100+ focusNode: _focusNode,
101+ onKeyEvent: _handleKeyPress,
102+ child: MouseRegion (
103+ onHover: (_) {
104+ _focusNode.requestFocus ();
105+ _cancelAndRestartTimer ();
106+ },
107+ child: GestureDetector (
108+ onTap: () => _cancelAndRestartTimer (),
109+ child: AbsorbPointer (
110+ absorbing: notifier.hideStuff,
111+ child: Stack (
112+ children: [
113+ if (_displayBufferingIndicator)
114+ _chewieController? .bufferingBuilder? .call (context) ??
115+ const Center (
116+ child: CircularProgressIndicator (),
117+ )
118+ else
119+ _buildHitArea (),
120+ Column (
121+ mainAxisAlignment: MainAxisAlignment .end,
122+ children: < Widget > [
123+ if (_subtitleOn)
124+ Transform .translate (
125+ offset: Offset (
126+ 0.0 ,
127+ notifier.hideStuff ? barHeight * 0.8 : 0.0 ,
128+ ),
129+ child: _buildSubtitles (
130+ context, chewieController.subtitle! ),
103131 ),
104- child:
105- _buildSubtitles (context, chewieController.subtitle! ),
106- ),
107- _buildBottomBar (context),
108- ],
109- ),
110- ],
132+ _buildBottomBar (context),
133+ ],
134+ ),
135+ ],
136+ ),
111137 ),
112138 ),
113139 ),
@@ -117,6 +143,7 @@ class _MaterialDesktopControlsState extends State<MaterialDesktopControls>
117143 @override
118144 void dispose () {
119145 _dispose ();
146+ _focusNode.dispose ();
120147 super .dispose ();
121148 }
122149
@@ -565,6 +592,36 @@ class _MaterialDesktopControlsState extends State<MaterialDesktopControls>
565592 });
566593 }
567594
595+ void _seekBackward () {
596+ _seekRelative (
597+ const Duration (
598+ seconds: - 10 ,
599+ ),
600+ );
601+ }
602+
603+ void _seekForward () {
604+ _seekRelative (
605+ const Duration (
606+ seconds: 10 ,
607+ ),
608+ );
609+ }
610+
611+ void _seekRelative (Duration relativeSeek) {
612+ _cancelAndRestartTimer ();
613+ final position = _latestValue.position + relativeSeek;
614+ final duration = _latestValue.duration;
615+
616+ if (position < Duration .zero) {
617+ controller.seekTo (Duration .zero);
618+ } else if (position > duration) {
619+ controller.seekTo (duration);
620+ } else {
621+ controller.seekTo (position);
622+ }
623+ }
624+
568625 Widget _buildProgressBar () {
569626 return Expanded (
570627 child: MaterialVideoProgressBar (
0 commit comments