Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-06-21 12:46:34 +08:00
parent 5f3f158932
commit 604d78ad6a
161 changed files with 4873 additions and 4770 deletions

View File

@@ -3,17 +3,16 @@ import 'dart:convert';
import 'dart:io';
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/widgets/pair.dart';
import 'package:PiliPlus/common/widgets/progress_bar/segment_progress_bar.dart';
import 'package:PiliPlus/http/init.dart';
import 'package:PiliPlus/http/video.dart';
import 'package:PiliPlus/models/common/account_type.dart';
import 'package:PiliPlus/models/common/audio_normalization.dart';
import 'package:PiliPlus/models/common/sponsor_block/segment_type.dart';
import 'package:PiliPlus/models/common/sponsor_block/skip_type.dart';
import 'package:PiliPlus/models/user/danmaku_rule.dart';
import 'package:PiliPlus/models_new/video/video_shot/data.dart';
import 'package:PiliPlus/pages/mine/controller.dart';
import 'package:PiliPlus/plugin/pl_player/models/bottom_progress_behavior.dart';
import 'package:PiliPlus/plugin/pl_player/models/data_source.dart';
import 'package:PiliPlus/plugin/pl_player/models/data_status.dart';
import 'package:PiliPlus/plugin/pl_player/models/fullscreen_mode.dart';
@@ -21,10 +20,13 @@ import 'package:PiliPlus/plugin/pl_player/models/play_repeat.dart';
import 'package:PiliPlus/plugin/pl_player/models/play_status.dart';
import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart';
import 'package:PiliPlus/services/service_locator.dart';
import 'package:PiliPlus/utils/accounts.dart';
import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/feed_back.dart';
import 'package:PiliPlus/utils/page_utils.dart' show PageUtils;
import 'package:PiliPlus/utils/storage.dart';
import 'package:PiliPlus/utils/storage_key.dart';
import 'package:PiliPlus/utils/storage_pref.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:canvas_danmaku/canvas_danmaku.dart';
import 'package:crclib/catalog.dart';
@@ -78,8 +80,8 @@ class PlPlayerController {
final RxInt _playerCount = 0.obs;
late double lastPlaybackSpeed = 1.0;
final RxDouble _playbackSpeed = 1.0.obs;
final RxDouble _longPressSpeed = 2.0.obs;
final RxDouble _playbackSpeed = Pref.playSpeedDefault.obs;
late final RxDouble _longPressSpeed = Pref.longPressSpeedDefault.obs;
final RxDouble _currentVolume = 1.0.obs;
final RxDouble _currentBrightness = (-1.0).obs;
@@ -91,7 +93,7 @@ class PlPlayerController {
final RxBool _controlsLock = false.obs;
final RxBool _isFullScreen = false.obs;
// 默认投稿视频格式
static RxString _videoType = 'archive'.obs;
static final RxString _videoType = 'archive'.obs;
final RxString _direction = 'horizontal'.obs;
@@ -100,7 +102,8 @@ class PlPlayerController {
late StreamSubscription<DataStatus> _dataListenerForEnterFullscreen;
/// 后台播放
late final RxBool _continuePlayInBackground = false.obs;
late final RxBool _continuePlayInBackground =
Pref.continuePlayInBackground.obs;
late final RxBool _flipX = false.obs;
@@ -135,7 +138,7 @@ class PlPlayerController {
final RxBool showVP = true.obs;
final RxList<Segment> segmentList = <Segment>[].obs;
Box get setting => GStorage.setting;
Box setting = GStorage.setting;
// final Durations durations;
@@ -246,10 +249,9 @@ class PlPlayerController {
RxString get videoType => _videoType;
/// 弹幕开关
RxBool isOpenDanmu = false.obs;
RxBool enableShowDanmaku = Pref.enableShowDanmaku.obs;
bool autoPiP =
GStorage.setting.get(SettingBoxKey.autoPiP, defaultValue: false);
late final bool autoPiP = Pref.autoPiP;
void enterPip() {
if (Get.currentRoute.startsWith('/video')) {
@@ -258,82 +260,97 @@ class PlPlayerController {
}
/// 弹幕权重
int danmakuWeight = 0;
late RuleFilter filters;
late int danmakuWeight = Pref.danmakuWeight;
late RuleFilter filters = Pref.danmakuFilterRule;
// 关联弹幕控制器
DanmakuController? danmakuController;
bool showDanmaku = true;
Set<int> dmState = <int>{};
late final mergeDanmaku = GStorage.mergeDanmaku;
late final mergeDanmaku = Pref.mergeDanmaku;
late final String midHash = Crc32Xz()
.convert(utf8.encode(Accounts.main.mid.toString()))
.toRadixString(16);
// 弹幕相关配置
late Set<int> blockTypes;
late double showArea;
late double opacity;
late double fontSize;
late double fontSizeFS;
late double strokeWidth;
late int fontWeight;
late bool massiveMode;
late double danmakuDuration;
late double danmakuStaticDuration;
late List<double> speedList;
late bool enableAutoLongPressSpeed = false;
late bool enableLongShowControl;
double subtitleFontScale = 1.0;
double subtitleFontScaleFS = 1.5;
late double danmakuLineHeight = GStorage.danmakuLineHeight;
late int subtitlePaddingH = GStorage.subtitlePaddingH;
late int subtitlePaddingB = GStorage.subtitlePaddingB;
late double subtitleBgOpaticy = GStorage.subtitleBgOpaticy;
late bool showVipDanmaku = GStorage.showVipDanmaku;
late bool showSpecialDanmaku = GStorage.showSpecialDanmaku;
late double subtitleStrokeWidth = GStorage.subtitleStrokeWidth;
late int subtitleFontWeight = GStorage.subtitleFontWeight;
late Set<int> blockTypes = Pref.danmakuBlockType;
late double showArea = Pref.danmakuShowArea;
late double danmakuOpacity = Pref.danmakuOpacity;
late double danmakuFontScale = Pref.danmakuFontScale;
late double danmakuFontScaleFS = Pref.danmakuFontScaleFS;
late double strokeWidth = Pref.strokeWidth;
late int fontWeight = Pref.fontWeight;
late bool massiveMode = Pref.danmakuMassiveMode;
late double danmakuDuration = Pref.danmakuDuration;
late double danmakuStaticDuration = Pref.danmakuStaticDuration;
late List<double> speedList = Pref.speedList;
late bool enableAutoLongPressSpeed = Pref.enableAutoLongPressSpeed;
late bool enableLongShowControl = Pref.enableLongShowControl;
late double subtitleFontScale = Pref.subtitleFontScale;
late double subtitleFontScaleFS = Pref.subtitleFontScaleFS;
late double danmakuLineHeight = Pref.danmakuLineHeight;
late int subtitlePaddingH = Pref.subtitlePaddingH;
late int subtitlePaddingB = Pref.subtitlePaddingB;
late double subtitleBgOpaticy = Pref.subtitleBgOpaticy;
late bool showVipDanmaku = Pref.showVipDanmaku;
late bool showSpecialDanmaku = Pref.showSpecialDanmaku;
late double subtitleStrokeWidth = Pref.subtitleStrokeWidth;
late int subtitleFontWeight = Pref.subtitleFontWeight;
// sponsor block
late final bool enableSponsorBlock =
setting.get(SettingBoxKey.enableSponsorBlock, defaultValue: false);
late final double blockLimit = GStorage.blockLimit;
late final List<Pair<SegmentType, SkipType>> blockSettings =
GStorage.blockSettings;
late final List<Color> blockColor = GStorage.blockColor;
late final bool enableSponsorBlock = Pref.enableSponsorBlock;
late final double blockLimit = Pref.blockLimit;
late final blockSettings = Pref.blockSettings;
late final List<Color> blockColor = Pref.blockColor;
late final Set<String> enableList = blockSettings
.where((item) => item.second != SkipType.disable)
.map((item) => item.first.name)
.toSet();
late final blockServer = GStorage.blockServer;
late final blockServer = Pref.blockServer;
// settings
late final showFSActionItem = GStorage.showFSActionItem;
late final enableShrinkVideoSize = GStorage.enableShrinkVideoSize;
late final darkVideoPage = GStorage.darkVideoPage;
late final enableSlideVolumeBrightness = GStorage.enableSlideVolumeBrightness;
late final enableSlideFS = GStorage.enableSlideFS;
late final enableDragSubtitle = GStorage.enableDragSubtitle;
late final fastForBackwardDuration = GStorage.fastForBackwardDuration;
late final showFSActionItem = Pref.showFSActionItem;
late final enableShrinkVideoSize = Pref.enableShrinkVideoSize;
late final darkVideoPage = Pref.darkVideoPage;
late final enableSlideVolumeBrightness = Pref.enableSlideVolumeBrightness;
late final enableSlideFS = Pref.enableSlideFS;
late final enableDragSubtitle = Pref.enableDragSubtitle;
late final fastForBackwardDuration = Pref.fastForBackwardDuration;
late final horizontalSeasonPanel = GStorage.horizontalSeasonPanel;
late final preInitPlayer = GStorage.preInitPlayer;
late final showRelatedVideo = GStorage.showRelatedVideo;
late final showVideoReply = GStorage.showVideoReply;
late final showBangumiReply = GStorage.showBangumiReply;
late final reverseFromFirst = GStorage.reverseFromFirst;
late final horizontalPreview = GStorage.horizontalPreview;
late final showDmChart = GStorage.showDmChart;
late final horizontalSeasonPanel = Pref.horizontalSeasonPanel;
late final preInitPlayer = Pref.preInitPlayer;
late final showRelatedVideo = Pref.showRelatedVideo;
late final showVideoReply = Pref.showVideoReply;
late final showBangumiReply = Pref.showBangumiReply;
late final reverseFromFirst = Pref.reverseFromFirst;
late final horizontalPreview = Pref.horizontalPreview;
late final showDmChart = Pref.showDmChart;
late final bool autoExitFullscreen = Pref.autoExitFullscreen;
late final bool autoPlayEnable = Pref.autoPlayEnable;
late final bool enableVerticalExpand = Pref.enableVerticalExpand;
late final bool pipNoDanmaku = Pref.pipNoDanmaku;
late final bool removeSafeArea = Pref.removeSafeArea;
int? cacheVideoQa;
late int cacheAudioQa;
bool enableHeart = true;
bool enableHA =
GStorage.setting.get(SettingBoxKey.enableHA, defaultValue: true);
String hwdec = GStorage.hardwareDecoding;
late final bool enableHA = Pref.enableHA;
late final String hwdec = Pref.hardwareDecoding;
late final defaultBtmProgressBehavior =
BtmProgressBehavior.values[Pref.btmProgressBehavior];
late final enableQuickDouble = Pref.enableQuickDouble;
late final fullScreenGestureReverse = Pref.fullScreenGestureReverse;
late final isRelative = Pref.useRelativeSlide;
late final offset =
isRelative ? Pref.sliderDuration / 100 : Pref.sliderDuration * 1000;
num get sliderScale =>
isRelative ? duration.value.inMilliseconds * offset : offset;
// 播放顺序相关
PlayRepeat playRepeat = PlayRepeat.pause;
late PlayRepeat playRepeat = PlayRepeat.values[Pref.playRepeat];
TextStyle get subTitleStyle => TextStyle(
height: 1.5,
@@ -442,60 +459,10 @@ class PlPlayerController {
await _instance?.setVolume(volumeNew, videoPlayerVolume: videoPlayerVolume);
}
Box get video => GStorage.video;
Box video = GStorage.video;
// 添加一个私有构造函数
PlPlayerController._() {
_videoType = videoType;
isOpenDanmu.value =
setting.get(SettingBoxKey.enableShowDanmaku, defaultValue: true);
danmakuWeight = setting.get(SettingBoxKey.danmakuWeight, defaultValue: 0);
filters = GStorage.danmakuFilterRule;
blockTypes =
(setting.get(SettingBoxKey.danmakuBlockType, defaultValue: <int>[])
as Iterable)
.cast<int>()
.toSet();
showArea = setting.get(SettingBoxKey.danmakuShowArea, defaultValue: 0.5);
// 不透明度
opacity = setting.get(SettingBoxKey.danmakuOpacity, defaultValue: 1.0);
// 字体大小
fontSize = setting.get(SettingBoxKey.danmakuFontScale, defaultValue: 1.0);
// 全屏字体大小
fontSizeFS = GStorage.danmakuFontScaleFS;
subtitleFontScale = GStorage.subtitleFontScale;
subtitleFontScaleFS = GStorage.subtitleFontScaleFS;
massiveMode = GStorage.danmakuMassiveMode;
// 弹幕时间
danmakuDuration =
setting.get(SettingBoxKey.danmakuDuration, defaultValue: 7.0);
danmakuStaticDuration =
setting.get(SettingBoxKey.danmakuStaticDuration, defaultValue: 4.0);
// 描边粗细
strokeWidth = setting.get(SettingBoxKey.strokeWidth, defaultValue: 1.5);
// 弹幕字体粗细
fontWeight = setting.get(SettingBoxKey.fontWeight, defaultValue: 5);
playRepeat = PlayRepeat.values.toList().firstWhere(
(e) =>
e.value ==
video.get(VideoBoxKey.playRepeat,
defaultValue: PlayRepeat.pause.value),
);
_playbackSpeed.value =
video.get(VideoBoxKey.playSpeedDefault, defaultValue: 1.0);
enableAutoLongPressSpeed = setting
.get(SettingBoxKey.enableAutoLongPressSpeed, defaultValue: false);
// 后台播放
_continuePlayInBackground.value = setting
.get(SettingBoxKey.continuePlayInBackground, defaultValue: false);
if (!enableAutoLongPressSpeed) {
_longPressSpeed.value =
video.get(VideoBoxKey.longPressSpeedDefault, defaultValue: 3.0);
}
enableLongShowControl =
setting.get(SettingBoxKey.enableLongShowControl, defaultValue: false);
speedList = GStorage.speedList;
if (!Accounts.get(AccountType.heartbeat).isLogin ||
GStorage.localCache.get(LocalCacheKey.historyPause) == true) {
enableHeart = false;
@@ -663,7 +630,7 @@ class PlPlayerController {
bool get _isPgc =>
Get.parameters['type'] == '1' || Get.parameters['type'] == '4';
late int superResolutionType = _isPgc ? GStorage.superResolutionType : 0;
late int superResolutionType = _isPgc ? Pref.superResolutionType : 0;
Future<void> setShader([int? type, NativePlayer? pp]) async {
if (type == null) {
type ??= superResolutionType;
@@ -714,27 +681,26 @@ class PlPlayerController {
_heartDuration = 0;
_position.value = Duration.zero;
// 初始化时清空弹幕,防止上次重叠
if (danmakuController != null) {
danmakuController!.clear();
}
int bufferSize =
setting.get(SettingBoxKey.expandBuffer, defaultValue: false)
? (videoType.value == 'live' ? 64 * 1024 * 1024 : 32 * 1024 * 1024)
: (videoType.value == 'live' ? 16 * 1024 * 1024 : 4 * 1024 * 1024);
danmakuController?.clear();
Player player = _videoPlayerController ??
Player(
configuration: PlayerConfiguration(
// 默认缓冲 4M 大小
bufferSize: bufferSize,
bufferSize: Pref.expandBuffer
? (videoType.value == 'live'
? 64 * 1024 * 1024
: 32 * 1024 * 1024)
: (videoType.value == 'live'
? 16 * 1024 * 1024
: 4 * 1024 * 1024),
),
);
var pp = player.platform as NativePlayer;
// 解除倍速限制
if (_isPgc) {
setShader(superResolutionType, pp);
}
if (_videoPlayerController == null) {
String audioNormalization = GStorage.audioNormalization;
if (_isPgc) {
setShader(superResolutionType, pp);
}
String audioNormalization = Pref.audioNormalization;
audioNormalization = switch (audioNormalization) {
'0' => '',
'1' => ',${AudioNormalization.dynaudnorm.param}',
@@ -745,25 +711,21 @@ class PlPlayerController {
"af",
"scaletempo2=max-speed=8$audioNormalization",
);
if (Platform.isAndroid) {
await pp.setProperty("volume-max", "100");
String ao =
Pref.useOpenSLES ? "opensles,audiotrack" : "audiotrack,opensles";
await pp.setProperty("ao", ao);
}
// video-sync=display-resample
await pp.setProperty("video-sync", Pref.videoSync);
// vo=gpu-next & gpu-context=android & gpu-api=opengl
// await pp.setProperty("vo", "gpu-next");
// await pp.setProperty("gpu-context", "android");
// await pp.setProperty("gpu-api", "opengl");
await player.setAudioTrack(AudioTrack.auto());
}
// 音量不一致
if (Platform.isAndroid) {
await pp.setProperty("volume-max", "100");
String ao = setting.get(SettingBoxKey.useOpenSLES, defaultValue: true)
? "opensles,audiotrack"
: "audiotrack,opensles";
await pp.setProperty("ao", ao);
}
// video-sync=display-resample
await pp.setProperty("video-sync",
setting.get(SettingBoxKey.videoSync, defaultValue: 'display-resample'));
// // vo=gpu-next & gpu-context=android & gpu-api=opengl
// await pp.setProperty("vo", "gpu-next");
// await pp.setProperty("gpu-context", "android");
// await pp.setProperty("gpu-api", "opengl");
await player.setAudioTrack(
AudioTrack.auto(),
);
// 音轨
if (dataSource.audioSource?.isNotEmpty == true) {
await pp.setProperty(
@@ -777,7 +739,7 @@ class PlPlayerController {
}
// 字幕
if (dataSource.subFiles != '' && dataSource.subFiles != null) {
if (dataSource.subFiles?.isNotEmpty == true) {
await pp.setProperty(
'sub-files',
UniversalPlatform.isWindows
@@ -881,10 +843,9 @@ class PlPlayerController {
}
}
late final bool enableAutoEnter = Pref.enableAutoEnter;
Future<void> autoEnterFullscreen() async {
bool autoEnterFullscreen = GStorage.setting
.get(SettingBoxKey.enableAutoEnter, defaultValue: false);
if (autoEnterFullscreen) {
if (enableAutoEnter) {
Future.delayed(const Duration(milliseconds: 500), () {
if (dataStatus.status.value != DataStatus.loaded) {
_dataListenerForEnterFullscreen = dataStatus.status.listen((status) {
@@ -1115,10 +1076,10 @@ class PlPlayerController {
}
// 还原默认速度
double playSpeedDefault = Pref.playSpeedDefault;
Future<void> setDefaultSpeed() async {
double speed = video.get(VideoBoxKey.playSpeedDefault, defaultValue: 1.0);
await _videoPlayerController?.setRate(speed);
_playbackSpeed.value = speed;
await _videoPlayerController?.setRate(playSpeedDefault);
_playbackSpeed.value = playSpeedDefault;
}
/// 播放视频
@@ -1281,8 +1242,8 @@ class PlPlayerController {
}
/// 读取fit
int fitValue = Pref.cacheVideoFit;
Future<void> getVideoFit() async {
int fitValue = video.get(VideoBoxKey.cacheVideoFit, defaultValue: 1);
var attr = BoxFit.values[fitValue];
// 由于none与scaleDown涉及视频原始尺寸需要等待视频加载后再设置否则尺寸会变为0出现错误;
if (attr == BoxFit.none || attr == BoxFit.scaleDown) {
@@ -1291,8 +1252,6 @@ class PlPlayerController {
_dataListenerForVideoFit = dataStatus.status.listen((status) {
if (status == DataStatus.loaded) {
_dataListenerForVideoFit.cancel();
int fitValue =
video.get(VideoBoxKey.cacheVideoFit, defaultValue: 1);
var attr = BoxFit.values[fitValue];
if (attr == BoxFit.none || attr == BoxFit.scaleDown) {
_videoFit.value = attr;
@@ -1309,17 +1268,10 @@ class PlPlayerController {
/// 设置后台播放
Future<void> setBackgroundPlay(bool val) async {
videoPlayerServiceHandler.enableBackgroundPlay = val;
setting.put(SettingBoxKey.enableBackgroundPlay, val);
videoPlayerServiceHandler.revalidateSetting();
}
/// 读取亮度
// Future<void> getVideoBrightness() async {
// double brightnessValue =
// video.get(VideoBoxKey.videoBrightness, defaultValue: 0.5);
// setBrightness(brightnessValue);
// }
set controls(bool visible) {
_showControls.value = visible;
_timer?.cancel();
@@ -1369,9 +1321,8 @@ class PlPlayerController {
updateSubtitleStyle();
}
late final FullScreenMode mode = FullScreenModeCode.fromCode(
setting.get(SettingBoxKey.fullScreenMode, defaultValue: 0));
late final horizontalScreen = GStorage.horizontalScreen;
late final FullScreenMode mode = FullScreenMode.values[Pref.fullScreenMode];
late final horizontalScreen = Pref.horizontalScreen;
// 全屏
void triggerFullScreen({bool status = true, int duration = 500}) {
@@ -1403,8 +1354,6 @@ class PlPlayerController {
await landScape();
}
} else if (isFullScreen.value && !status) {
late bool removeSafeArea = setting
.get(SettingBoxKey.videoPlayerRemoveSafeArea, defaultValue: false);
if (Get.currentRoute.startsWith('/liveRoom') || !removeSafeArea) {
showStatusBar();
}
@@ -1500,7 +1449,7 @@ class PlPlayerController {
void setPlayRepeat(PlayRepeat type) {
playRepeat = type;
video.put(VideoBoxKey.playRepeat, type.value);
video.put(VideoBoxKey.playRepeat, type.index);
}
void putDanmakuSettings() {
@@ -1508,9 +1457,9 @@ class PlPlayerController {
..put(SettingBoxKey.danmakuWeight, danmakuWeight)
..put(SettingBoxKey.danmakuBlockType, blockTypes.toList())
..put(SettingBoxKey.danmakuShowArea, showArea)
..put(SettingBoxKey.danmakuOpacity, opacity)
..put(SettingBoxKey.danmakuFontScale, fontSize)
..put(SettingBoxKey.danmakuFontScaleFS, fontSizeFS)
..put(SettingBoxKey.danmakuOpacity, danmakuOpacity)
..put(SettingBoxKey.danmakuFontScale, danmakuFontScale)
..put(SettingBoxKey.danmakuFontScaleFS, danmakuFontScaleFS)
..put(SettingBoxKey.danmakuDuration, danmakuDuration)
..put(SettingBoxKey.danmakuStaticDuration, danmakuStaticDuration)
..put(SettingBoxKey.strokeWidth, strokeWidth)
@@ -1596,7 +1545,7 @@ class PlPlayerController {
onlyPlayAudio.value ? VideoTrack.no() : VideoTrack.auto());
}
late final showSeekPreview = GStorage.showSeekPreview;
late final showSeekPreview = Pref.showSeekPreview;
late bool _isQueryingVideoShot = false;
Map? videoShot;
late final RxBool showPreview = false.obs;

View File

@@ -1,18 +1,10 @@
enum BtmProgressBehavior {
alwaysShow,
alwaysHide,
onlyShowFullScreen,
onlyHideFullScreen,
}
alwaysShow('始终展示'),
alwaysHide('始终隐藏'),
onlyShowFullScreen('仅全屏时展示'),
onlyHideFullScreen('仅全屏时隐藏'),
;
extension BtmProgresBehaviorDesc on BtmProgressBehavior {
String get description => const ['始终展示', '始终隐藏', '仅全屏时展示', '仅全屏时隐藏'][index];
}
extension BtmProgresBehaviorCode on BtmProgressBehavior {
int get code => index;
static BtmProgressBehavior fromCode(int code) {
return BtmProgressBehavior.values[code];
}
final String desc;
const BtmProgressBehavior(this.desc);
}

View File

@@ -1,34 +1,19 @@
// 全屏模式
enum FullScreenMode {
// 根据内容自适应
auto,
auto('按视频方向(默认)'),
// 不改变当前方向
none,
none('不改变当前方向'),
// 始终竖屏
vertical,
vertical('强制竖屏'),
// 始终横屏
horizontal,
horizontal('强制竖屏'),
// 屏幕长宽比<1.25或为竖屏视频时竖屏,否则横屏
ratio,
ratio('屏幕长宽比<1.25或为竖屏视频时竖屏,否则横屏'),
// 强制重力转屏(仅安卓)
gravity,
}
gravity('忽略系统方向锁定,强制按重力转屏(仅安卓)'),
;
extension FullScreenModeDesc on FullScreenMode {
String get description => const [
'按视频方向(默认)',
'不改变当前方向',
'强制竖屏',
'强制横屏',
'屏幕长宽比<1.25或为竖屏视频时竖屏,否则横屏',
'忽略系统方向锁定,强制按重力转屏(仅安卓)'
][index];
}
extension FullScreenModeCode on FullScreenMode {
int get code => index;
static FullScreenMode fromCode(int code) {
return FullScreenMode.values[code];
}
final String desc;
const FullScreenMode(this.desc);
}

View File

@@ -1,28 +1,11 @@
enum PlayRepeat {
pause,
listOrder,
singleCycle,
listCycle,
autoPlayRelated,
}
pause('播完暂停'),
listOrder('顺序播放'),
singleCycle('单个循环'),
listCycle('列表循环'),
autoPlayRelated('自动连播'),
;
extension PlayRepeatExtension on PlayRepeat {
static const List<String> _descList = <String>[
'播完暂停',
'顺序播放',
'单个循环',
'列表循环',
'自动连播',
];
String get description => _descList[index];
static const List<double> _valueList = [
1,
2,
3,
4,
5,
];
double get value => _valueList[index];
double get defaultValue => _valueList[1];
final String desc;
const PlayRepeat(this.desc);
}

View File

@@ -1,39 +1,18 @@
enum PlaySpeed {
pointFive,
pointSevenFive,
pointFive(0.5),
pointSevenFive(0.75),
one,
onePointTwoFive,
onePointFive,
onePointSevenFive,
one(1.0),
onePointTwoFive(1.25),
onePointFive(1.5),
onePointSevenFive(1.75),
two,
three,
}
extension PlaySpeedExtension on PlaySpeed {
static const List<String> _descList = [
'0.5',
'0.75',
'正常',
'1.25',
'1.5',
'1.75',
'2.0',
'3.0'
];
String get description => _descList[index];
static const List<double> _valueList = [
0.5,
0.75,
1.0,
1.25,
1.5,
1.75,
2.0,
3.0,
];
double get value => _valueList[index];
double get defaultValue => _valueList[3];
two(2.0),
three(3.0),
;
final double value;
const PlaySpeed(this.value);
String get desc => value == 1.0 ? '正常' : value.toString();
}

View File

@@ -1,7 +1,7 @@
import 'dart:async';
import 'dart:io';
import 'package:PiliPlus/utils/storage.dart';
import 'package:PiliPlus/utils/storage_pref.dart';
import 'package:auto_orientation/auto_orientation.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/foundation.dart';
@@ -55,8 +55,7 @@ Future<void> verticalScreen() async {
//全向
Future<void> autoScreen() async {
if (!GStorage.setting
.get(SettingBoxKey.allowRotateScreen, defaultValue: true)) {
if (!Pref.allowRotateScreen) {
return;
}
await SystemChrome.setPreferredOrientations([

View File

@@ -28,7 +28,6 @@ import 'package:PiliPlus/plugin/pl_player/widgets/play_pause_btn.dart';
import 'package:PiliPlus/utils/duration_util.dart';
import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/id_utils.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:easy_debounce/easy_throttle.dart';
import 'package:fl_chart/fl_chart.dart';
@@ -107,21 +106,9 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
final RxBool _volumeInterceptEventStream = false.obs;
late FullScreenMode mode;
late int defaultBtmProgressBehavior;
late bool enableQuickDouble;
late bool fullScreenGestureReverse;
late final RxBool showRestoreScaleBtn = false.obs;
late final _isRelative = GStorage.useRelativeSlide;
late final _offset = _isRelative
? GStorage.sliderDuration / 100
: GStorage.sliderDuration * 1000;
num get sliderScale => _isRelative
? plPlayerController.duration.value.inMilliseconds * _offset
: _offset;
Offset _initialFocalPoint = Offset.zero;
String? _gestureType;
//播放器放缩
@@ -152,7 +139,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
}
void doubleTapFuc(String type) {
if (!enableQuickDouble) {
if (!plPlayerController.enableQuickDouble) {
onDoubleTapCenter();
return;
}
@@ -182,13 +169,6 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
videoController = plPlayerController.videoController!;
videoIntroController = widget.videoIntroController;
pgcIntroController = widget.pgcIntroController;
defaultBtmProgressBehavior = GStorage.setting.get(
SettingBoxKey.btmProgressBehavior,
defaultValue: BtmProgressBehavior.values.first.code);
enableQuickDouble = GStorage.setting
.get(SettingBoxKey.enableQuickDouble, defaultValue: true);
fullScreenGestureReverse = GStorage.setting
.get(SettingBoxKey.fullScreenGestureReverse, defaultValue: false);
Future.microtask(() async {
try {
FlutterVolumeController.updateShowSystemUI(true);
@@ -820,7 +800,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
final double width = renderBox.size.width;
final Duration pos = Duration(
milliseconds: curSliderPosition +
(sliderScale * delta.dx / width).round()); // TODO
(plPlayerController.sliderScale * delta.dx / width)
.round()); // TODO
final Duration result =
pos.clamp(Duration.zero, plPlayerController.duration.value);
final height = renderBox.size.height * 0.125;
@@ -897,14 +878,18 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
if (cumulativeDy > threshold) {
_gestureType = 'center_down';
if (isFullScreen ^ fullScreenGestureReverse) {
fullScreenTrigger(fullScreenGestureReverse);
if (isFullScreen ^
plPlayerController.fullScreenGestureReverse) {
fullScreenTrigger(
plPlayerController.fullScreenGestureReverse);
}
// if (kDebugMode) debugPrint('center_down:$cumulativeDy');
} else if (cumulativeDy < -threshold) {
_gestureType = 'center_up';
if (!isFullScreen ^ fullScreenGestureReverse) {
fullScreenTrigger(!fullScreenGestureReverse);
if (!isFullScreen ^
plPlayerController.fullScreenGestureReverse) {
fullScreenTrigger(
!plPlayerController.fullScreenGestureReverse);
}
// if (kDebugMode) debugPrint('center_up:$cumulativeDy');
}
@@ -1007,14 +992,18 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
if (cumulativeDy > threshold) {
_gestureType = 'center_down';
if (isFullScreen ^ fullScreenGestureReverse) {
fullScreenTrigger(fullScreenGestureReverse);
if (isFullScreen ^
plPlayerController.fullScreenGestureReverse) {
fullScreenTrigger(
plPlayerController.fullScreenGestureReverse);
}
// if (kDebugMode) debugPrint('center_down:$cumulativeDy');
} else if (cumulativeDy < -threshold) {
_gestureType = 'center_up';
if (!isFullScreen ^ fullScreenGestureReverse) {
fullScreenTrigger(!fullScreenGestureReverse);
if (!isFullScreen ^
plPlayerController.fullScreenGestureReverse) {
fullScreenTrigger(
!plPlayerController.fullScreenGestureReverse);
}
// if (kDebugMode) debugPrint('center_up:$cumulativeDy');
}
@@ -1363,26 +1352,30 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
if (plPlayerController.showControls.value) {
return const SizedBox.shrink();
}
if (defaultBtmProgressBehavior ==
BtmProgressBehavior.alwaysHide.code) {
return const SizedBox.shrink();
}
if (defaultBtmProgressBehavior ==
BtmProgressBehavior.onlyShowFullScreen.code &&
!isFullScreen) {
return const SizedBox.shrink();
} else if (defaultBtmProgressBehavior ==
BtmProgressBehavior.onlyHideFullScreen.code &&
isFullScreen) {
return const SizedBox.shrink();
switch (plPlayerController.defaultBtmProgressBehavior) {
case BtmProgressBehavior.alwaysShow:
break;
case BtmProgressBehavior.alwaysHide:
return const SizedBox.shrink();
case BtmProgressBehavior.onlyShowFullScreen:
if (!isFullScreen) {
return const SizedBox.shrink();
}
case BtmProgressBehavior.onlyHideFullScreen:
if (isFullScreen) {
return const SizedBox.shrink();
}
}
if (plPlayerController.videoType.value == 'live') {
return const SizedBox.shrink();
}
if (value > max || max <= 0) {
return const SizedBox.shrink();
}
return Positioned(
bottom: -2.2,
left: 0,