mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-06-01 00:28:18 +08:00
add physical keyboard controls for playback (#1203)
This commit is contained in:
@@ -58,7 +58,8 @@ import 'package:floating/floating.dart';
|
|||||||
import 'package:flutter/foundation.dart' show kDebugMode;
|
import 'package:flutter/foundation.dart' show kDebugMode;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/services.dart' show SystemUiOverlayStyle;
|
import 'package:flutter/services.dart'
|
||||||
|
show SystemUiOverlayStyle, KeyDownEvent, LogicalKeyboardKey;
|
||||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:get/get.dart' hide ContextExtensionss;
|
import 'package:get/get.dart' hide ContextExtensionss;
|
||||||
@@ -84,19 +85,24 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
late final UgcIntroController ugcIntroController;
|
late final UgcIntroController ugcIntroController;
|
||||||
late final PgcIntroController pgcIntroController;
|
late final PgcIntroController pgcIntroController;
|
||||||
ScrollController? _introScrollController;
|
ScrollController? _introScrollController;
|
||||||
|
|
||||||
ScrollController get introScrollController =>
|
ScrollController get introScrollController =>
|
||||||
_introScrollController ??= ScrollController();
|
_introScrollController ??= ScrollController();
|
||||||
|
|
||||||
bool get autoExitFullscreen =>
|
bool get autoExitFullscreen =>
|
||||||
videoDetailController.plPlayerController.autoExitFullscreen;
|
videoDetailController.plPlayerController.autoExitFullscreen;
|
||||||
|
|
||||||
bool get autoPlayEnable =>
|
bool get autoPlayEnable =>
|
||||||
videoDetailController.plPlayerController.autoPlayEnable;
|
videoDetailController.plPlayerController.autoPlayEnable;
|
||||||
|
|
||||||
bool get enableVerticalExpand =>
|
bool get enableVerticalExpand =>
|
||||||
videoDetailController.plPlayerController.enableVerticalExpand;
|
videoDetailController.plPlayerController.enableVerticalExpand;
|
||||||
|
|
||||||
bool get pipNoDanmaku =>
|
bool get pipNoDanmaku =>
|
||||||
videoDetailController.plPlayerController.pipNoDanmaku;
|
videoDetailController.plPlayerController.pipNoDanmaku;
|
||||||
|
|
||||||
bool isShowing = true;
|
bool isShowing = true;
|
||||||
|
|
||||||
bool get isFullScreen =>
|
bool get isFullScreen =>
|
||||||
videoDetailController.plPlayerController.isFullScreen.value;
|
videoDetailController.plPlayerController.isFullScreen.value;
|
||||||
|
|
||||||
@@ -505,6 +511,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
}
|
}
|
||||||
|
|
||||||
late double animHeight;
|
late double animHeight;
|
||||||
|
|
||||||
void cal() {
|
void cal() {
|
||||||
if (videoDetailController.isExpanding) {
|
if (videoDetailController.isExpanding) {
|
||||||
animHeight = clampDouble(
|
animHeight = clampDouble(
|
||||||
@@ -1491,6 +1498,19 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
} else {
|
} else {
|
||||||
child = autoChoose(childWhenDisabledAlmostSquare);
|
child = autoChoose(childWhenDisabledAlmostSquare);
|
||||||
}
|
}
|
||||||
|
child = Focus(
|
||||||
|
onKeyEvent: (node, event) {
|
||||||
|
if (event is KeyDownEvent &&
|
||||||
|
(event.logicalKey == LogicalKeyboardKey.arrowLeft ||
|
||||||
|
event.logicalKey == LogicalKeyboardKey.arrowRight ||
|
||||||
|
event.logicalKey == LogicalKeyboardKey.arrowUp ||
|
||||||
|
event.logicalKey == LogicalKeyboardKey.arrowDown)) {
|
||||||
|
return KeyEventResult.handled;
|
||||||
|
}
|
||||||
|
return KeyEventResult.ignored;
|
||||||
|
},
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
return videoDetailController.plPlayerController.darkVideoPage
|
return videoDetailController.plPlayerController.darkVideoPage
|
||||||
? Theme(data: themeData, child: child)
|
? Theme(data: themeData, child: child)
|
||||||
: child;
|
: child;
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ import 'package:easy_debounce/easy_throttle.dart';
|
|||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
import 'package:flutter_volume_controller/flutter_volume_controller.dart';
|
import 'package:flutter_volume_controller/flutter_volume_controller.dart';
|
||||||
@@ -90,6 +91,7 @@ class PLVideoPlayer extends StatefulWidget {
|
|||||||
final Widget headerControl;
|
final Widget headerControl;
|
||||||
final Widget? bottomControl;
|
final Widget? bottomControl;
|
||||||
final Widget? danmuWidget;
|
final Widget? danmuWidget;
|
||||||
|
|
||||||
// List<Widget> or Widget
|
// List<Widget> or Widget
|
||||||
|
|
||||||
final Widget? customWidget;
|
final Widget? customWidget;
|
||||||
@@ -110,6 +112,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
late VideoController videoController;
|
late VideoController videoController;
|
||||||
late final CommonIntroController introController = widget.introController!;
|
late final CommonIntroController introController = widget.introController!;
|
||||||
|
|
||||||
|
final GlobalKey _keyboardKey = GlobalKey();
|
||||||
final GlobalKey _playerKey = GlobalKey();
|
final GlobalKey _playerKey = GlobalKey();
|
||||||
final GlobalKey<VideoState> key = GlobalKey<VideoState>();
|
final GlobalKey<VideoState> key = GlobalKey<VideoState>();
|
||||||
|
|
||||||
@@ -133,14 +136,17 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
|
|
||||||
Offset _initialFocalPoint = Offset.zero;
|
Offset _initialFocalPoint = Offset.zero;
|
||||||
GestureType? _gestureType;
|
GestureType? _gestureType;
|
||||||
|
|
||||||
//播放器放缩
|
//播放器放缩
|
||||||
bool interacting = false;
|
bool interacting = false;
|
||||||
|
|
||||||
// 是否在调整固定进度条
|
// 是否在调整固定进度条
|
||||||
RxBool draggingFixedProgressBar = false.obs;
|
RxBool draggingFixedProgressBar = false.obs;
|
||||||
|
|
||||||
// 阅读器限制
|
// 阅读器限制
|
||||||
// Timer? _accessibilityDebounce;
|
// Timer? _accessibilityDebounce;
|
||||||
// double _lastAnnouncedValue = -1;
|
// double _lastAnnouncedValue = -1;
|
||||||
|
final FocusNode _focusNode = FocusNode();
|
||||||
|
|
||||||
void onDoubleTapSeekBackward() {
|
void onDoubleTapSeekBackward() {
|
||||||
_mountSeekBackwardButton.value = true;
|
_mountSeekBackwardButton.value = true;
|
||||||
@@ -1117,6 +1123,40 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
doubleTapFuc(type);
|
doubleTapFuc(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _handleKey(KeyEvent event) {
|
||||||
|
if (event is KeyDownEvent) {
|
||||||
|
final key = event.logicalKey;
|
||||||
|
switch (key) {
|
||||||
|
case LogicalKeyboardKey.space:
|
||||||
|
onDoubleTapCenter();
|
||||||
|
break;
|
||||||
|
case LogicalKeyboardKey.keyF:
|
||||||
|
plPlayerController.triggerFullScreen(status: !isFullScreen);
|
||||||
|
break;
|
||||||
|
case LogicalKeyboardKey.arrowLeft:
|
||||||
|
onDoubleTapSeekBackward();
|
||||||
|
break;
|
||||||
|
case LogicalKeyboardKey.arrowRight:
|
||||||
|
onDoubleTapSeekForward();
|
||||||
|
break;
|
||||||
|
case LogicalKeyboardKey.escape:
|
||||||
|
if (isFullScreen) {
|
||||||
|
plPlayerController.triggerFullScreen(status: false);
|
||||||
|
} else {
|
||||||
|
Get.back();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LogicalKeyboardKey.keyD:
|
||||||
|
final newVal = !plPlayerController.enableShowDanmaku.value;
|
||||||
|
plPlayerController.enableShowDanmaku.value = newVal;
|
||||||
|
if (!plPlayerController.tempPlayerConf) {
|
||||||
|
GStorage.setting.put(SettingBoxKey.enableShowDanmaku, newVal);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
theme = Theme.of(context);
|
theme = Theme.of(context);
|
||||||
@@ -1130,7 +1170,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
final isFullScreen = this.isFullScreen;
|
final isFullScreen = this.isFullScreen;
|
||||||
final isLive = plPlayerController.isLive;
|
final isLive = plPlayerController.isLive;
|
||||||
|
|
||||||
return Stack(
|
Widget buildContent() => Stack(
|
||||||
fit: StackFit.passthrough,
|
fit: StackFit.passthrough,
|
||||||
key: _playerKey,
|
key: _playerKey,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
@@ -1866,12 +1906,21 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return KeyboardListener(
|
||||||
|
key: _keyboardKey,
|
||||||
|
focusNode: _focusNode,
|
||||||
|
autofocus: true,
|
||||||
|
onKeyEvent: _handleKey,
|
||||||
|
child: buildContent(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
late final segment = Pair(
|
late final segment = Pair(
|
||||||
first: plPlayerController.position.value.inMilliseconds / 1000.0,
|
first: plPlayerController.position.value.inMilliseconds / 1000.0,
|
||||||
second: plPlayerController.position.value.inMilliseconds / 1000.0,
|
second: plPlayerController.position.value.inMilliseconds / 1000.0,
|
||||||
);
|
);
|
||||||
|
|
||||||
Future<void> screenshotWebp() async {
|
Future<void> screenshotWebp() async {
|
||||||
final videoCtr = widget.videoDetailController!;
|
final videoCtr = widget.videoDetailController!;
|
||||||
final videoInfo = videoCtr.data;
|
final videoInfo = videoCtr.data;
|
||||||
|
|||||||
Reference in New Issue
Block a user