@@ -12,6 +12,7 @@ import 'package:chewie/src/models/option_item.dart';
12
12
import 'package:chewie/src/models/subtitle_model.dart' ;
13
13
import 'package:chewie/src/notifiers/index.dart' ;
14
14
import 'package:flutter/material.dart' ;
15
+ import 'package:flutter/services.dart' ;
15
16
import 'package:provider/provider.dart' ;
16
17
import 'package:video_player/video_player.dart' ;
17
18
@@ -49,16 +50,36 @@ class _MaterialDesktopControlsState extends State<MaterialDesktopControls>
49
50
50
51
late VideoPlayerController controller;
51
52
ChewieController ? _chewieController;
53
+ late final FocusNode _focusNode;
52
54
53
55
// We know that _chewieController is set in didChangeDependencies
54
56
ChewieController get chewieController => _chewieController! ;
55
57
56
58
@override
57
59
void initState () {
58
60
super .initState ();
61
+ _focusNode = FocusNode ();
62
+ _focusNode.requestFocus ();
59
63
notifier = Provider .of <PlayerNotifier >(context, listen: false );
60
64
}
61
65
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
+
62
83
@override
63
84
Widget build (BuildContext context) {
64
85
if (_latestValue.hasError) {
@@ -75,39 +96,44 @@ class _MaterialDesktopControlsState extends State<MaterialDesktopControls>
75
96
);
76
97
}
77
98
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! ),
103
131
),
104
- child:
105
- _buildSubtitles (context, chewieController.subtitle! ),
106
- ),
107
- _buildBottomBar (context),
108
- ],
109
- ),
110
- ],
132
+ _buildBottomBar (context),
133
+ ],
134
+ ),
135
+ ],
136
+ ),
111
137
),
112
138
),
113
139
),
@@ -117,6 +143,7 @@ class _MaterialDesktopControlsState extends State<MaterialDesktopControls>
117
143
@override
118
144
void dispose () {
119
145
_dispose ();
146
+ _focusNode.dispose ();
120
147
super .dispose ();
121
148
}
122
149
@@ -565,6 +592,36 @@ class _MaterialDesktopControlsState extends State<MaterialDesktopControls>
565
592
});
566
593
}
567
594
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
+
568
625
Widget _buildProgressBar () {
569
626
return Expanded (
570
627
child: MaterialVideoProgressBar (
0 commit comments