Files
PiliPlus/lib/pages/video/widgets/player_focus.dart
bggRGjQaUbCoE 6559aa767d opt ui
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
2025-09-19 12:21:20 +08:00

204 lines
6.4 KiB
Dart

import 'dart:async';
import 'dart:math' as math;
import 'package:PiliPlus/pages/common/common_intro_controller.dart';
import 'package:PiliPlus/pages/video/introduction/ugc/controller.dart';
import 'package:PiliPlus/plugin/pl_player/controller.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:PiliPlus/utils/storage_key.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart'
show KeyDownEvent, KeyUpEvent, LogicalKeyboardKey;
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
class PlayerFocus extends StatelessWidget {
const PlayerFocus({
super.key,
required this.child,
required this.plPlayerController,
this.introController,
required this.onSendDanmaku,
this.canPlay,
});
final Widget child;
final PlPlayerController plPlayerController;
final CommonIntroController? introController;
final VoidCallback onSendDanmaku;
final bool Function()? canPlay;
static bool _shouldHandled(KeyEvent event) {
return event.logicalKey == LogicalKeyboardKey.tab ||
event.logicalKey == LogicalKeyboardKey.arrowLeft ||
event.logicalKey == LogicalKeyboardKey.arrowRight ||
event.logicalKey == LogicalKeyboardKey.arrowUp ||
event.logicalKey == LogicalKeyboardKey.arrowDown;
}
@override
Widget build(BuildContext context) {
return Focus(
autofocus: true,
onKeyEvent: (node, event) {
final handled = _handleKey(event);
if (handled || _shouldHandled(event)) {
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
},
child: child,
);
}
bool get isFullScreen => plPlayerController.isFullScreen.value;
bool get hasPlayer => plPlayerController.videoPlayerController != null;
bool _handleKey(KeyEvent event) {
final key = event.logicalKey;
if (event is KeyDownEvent) {
switch (key) {
case LogicalKeyboardKey.space:
if (plPlayerController.isLive || canPlay!()) {
if (hasPlayer) {
plPlayerController.onDoubleTapCenter();
}
}
return true;
case LogicalKeyboardKey.keyF:
plPlayerController.triggerFullScreen(status: !isFullScreen);
return true;
case LogicalKeyboardKey.escape:
if (isFullScreen) {
plPlayerController.triggerFullScreen(status: false);
} else {
Get.back();
}
return true;
case LogicalKeyboardKey.keyD:
if (plPlayerController.isLive) {
final newVal = !plPlayerController.enableShowLiveDanmaku.value;
plPlayerController.enableShowLiveDanmaku.value = newVal;
if (!plPlayerController.tempPlayerConf) {
GStorage.setting.put(SettingBoxKey.enableShowLiveDanmaku, newVal);
}
} else {
final newVal = !plPlayerController.enableShowDanmaku.value;
plPlayerController.enableShowDanmaku.value = newVal;
if (!plPlayerController.tempPlayerConf) {
GStorage.setting.put(SettingBoxKey.enableShowDanmaku, newVal);
}
}
return true;
case LogicalKeyboardKey.arrowUp:
if (hasPlayer) {
final volume = math.min(1.0, plPlayerController.volume.value + 0.1);
plPlayerController.setVolume(volume);
}
return true;
case LogicalKeyboardKey.arrowDown:
if (hasPlayer) {
final volume = math.max(0.0, plPlayerController.volume.value - 0.1);
plPlayerController.setVolume(volume);
}
return true;
case LogicalKeyboardKey.keyM:
if (hasPlayer) {
final isMuted = !plPlayerController.isMuted;
plPlayerController.videoPlayerController!.setVolume(
isMuted ? 0 : plPlayerController.volume.value * 100,
);
plPlayerController.isMuted = isMuted;
SmartDialog.showToast('${isMuted ? '' : '取消'}静音');
}
return true;
case LogicalKeyboardKey.enter:
onSendDanmaku();
return true;
}
if (!plPlayerController.isLive) {
switch (key) {
case LogicalKeyboardKey.arrowLeft:
if (hasPlayer) {
plPlayerController.onBackward(
plPlayerController.fastForBackwardDuration,
);
}
return true;
case LogicalKeyboardKey.keyQ:
introController?.actionLikeVideo();
return true;
case LogicalKeyboardKey.keyW:
introController?.actionCoinVideo();
return true;
case LogicalKeyboardKey.keyE:
introController?.actionFavVideo(isQuick: true);
return true;
case LogicalKeyboardKey.keyR:
introController?.viewLater();
return true;
case LogicalKeyboardKey.keyG:
if (introController case UgcIntroController ugcCtr) {
ugcCtr.actionRelationMod(Get.context!);
}
return true;
case LogicalKeyboardKey.bracketLeft:
if (introController case final introController?) {
if (!introController.prevPlay()) {
SmartDialog.showToast('已经是第一集了');
}
}
return true;
case LogicalKeyboardKey.bracketRight:
if (introController case final introController?) {
if (!introController.nextPlay()) {
SmartDialog.showToast('已经是最后一集了');
}
}
return true;
}
}
}
if (key == LogicalKeyboardKey.arrowRight) {
if (!plPlayerController.isLive && hasPlayer) {
if (event is KeyDownEvent) {
if (!plPlayerController.longPressStatus.value) {
plPlayerController.longPressTimer ??= Timer(
const Duration(milliseconds: 200),
() => plPlayerController.setLongPressStatus(true),
);
}
} else if (event is KeyUpEvent) {
plPlayerController.cancelLongPressTimer();
if (plPlayerController.longPressStatus.value) {
plPlayerController.setLongPressStatus(false);
} else {
plPlayerController.onForward(
plPlayerController.fastForBackwardDuration,
);
}
}
}
return true;
}
return false;
}
}