Compare commits

..

3 Commits

Author SHA1 Message Date
bggRGjQaUbCoE
4256c2b023 opt ui
Closes #1680

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
2025-10-24 14:34:13 +08:00
bggRGjQaUbCoE
bbcf0dec1b upgrade deps
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
2025-10-23 23:21:33 +08:00
bggRGjQaUbCoE
da52cac2c6 tweaks
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
2025-10-23 23:21:28 +08:00
12 changed files with 170 additions and 217 deletions

View File

@@ -2,7 +2,7 @@
enum SearchType { enum SearchType {
// all('综合'), // all('综合'),
// 视频video // 视频video
video('视频', hasHeader: true), video('视频'),
// 番剧media_bangumi, // 番剧media_bangumi,
media_bangumi('番剧'), media_bangumi('番剧'),
// 影视media_ft // 影视media_ft
@@ -16,13 +16,12 @@ enum SearchType {
// 话题topic // 话题topic
// topic, // topic,
// 用户bili_user // 用户bili_user
bili_user('用户', hasHeader: true), bili_user('用户'),
// 专栏article // 专栏article
article('专栏', hasHeader: true); article('专栏');
// 相簿photo // 相簿photo
// photo // photo
final bool hasHeader;
final String label; final String label;
const SearchType(this.label, {this.hasHeader = false}); const SearchType(this.label);
} }

View File

@@ -735,8 +735,8 @@ class _AudioPageState extends State<AudioPage> {
final baseBarColor = colorScheme.brightness.isDark final baseBarColor = colorScheme.brightness.isDark
? const Color(0x33FFFFFF) ? const Color(0x33FFFFFF)
: const Color(0x33999999); : const Color(0x33999999);
return Obx(() { final child = Obx(
final child = ProgressBar( () => ProgressBar(
progress: _controller.position.value, progress: _controller.position.value,
total: _controller.duration.value, total: _controller.duration.value,
baseBarColor: baseBarColor, baseBarColor: baseBarColor,
@@ -749,15 +749,15 @@ class _AudioPageState extends State<AudioPage> {
onDragStart: _onDragStart, onDragStart: _onDragStart,
onDragUpdate: _onDragUpdate, onDragUpdate: _onDragUpdate,
onSeek: _onSeek, onSeek: _onSeek,
),
);
if (Utils.isDesktop) {
return MouseRegion(
cursor: SystemMouseCursors.click,
child: child,
); );
if (Utils.isDesktop) { }
return MouseRegion( return child;
cursor: SystemMouseCursors.click,
child: child,
);
}
return child;
});
} }
Widget _buildDuration(ColorScheme colorScheme) { Widget _buildDuration(ColorScheme colorScheme) {

View File

@@ -33,7 +33,6 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:canvas_danmaku/canvas_danmaku.dart'; import 'package:canvas_danmaku/canvas_danmaku.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/services.dart' show SystemUiOverlayStyle;
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart' hide ContextExtensionss; import 'package:get/get.dart' hide ContextExtensionss;
import 'package:screen_brightness_platform_interface/screen_brightness_platform_interface.dart'; import 'package:screen_brightness_platform_interface/screen_brightness_platform_interface.dart';
@@ -351,38 +350,16 @@ class _LiveRoomPageState extends State<LiveRoomPage>
); );
} }
SystemUiOverlayStyle _systemOverlayStyleForBrightness(
Brightness brightness, [
Color? backgroundColor,
]) {
final SystemUiOverlayStyle style = brightness == Brightness.dark
? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark;
// For backward compatibility, create an overlay style without system navigation bar settings.
return SystemUiOverlayStyle(
statusBarColor: backgroundColor,
statusBarBrightness: style.statusBarBrightness,
statusBarIconBrightness: style.statusBarIconBrightness,
systemStatusBarContrastEnforced: style.systemStatusBarContrastEnforced,
);
}
Widget get childWhenDisabled { Widget get childWhenDisabled {
return AnnotatedRegion<SystemUiOverlayStyle>( return Obx(() {
value: _systemOverlayStyleForBrightness( final isFullScreen = this.isFullScreen;
Brightness.dark, return Stack(
Theme.of(context).useMaterial3 ? const Color(0x00000000) : null, clipBehavior: Clip.none,
), children: [
child: ColoredBox( const SizedBox.expand(child: ColoredBox(color: Colors.black)),
color: Colors.black, if (!isFullScreen)
child: Stack(
clipBehavior: Clip.none,
children: [
Obx( Obx(
() { () {
if (isFullScreen) {
return const SizedBox.shrink();
}
final appBackground = _liveRoomController final appBackground = _liveRoomController
.roomInfoH5 .roomInfoH5
.value .value
@@ -407,34 +384,31 @@ class _LiveRoomPageState extends State<LiveRoomPage>
); );
}, },
), ),
if (isPortrait) Scaffold(
Obx( backgroundColor: Colors.transparent,
() { appBar: _buildAppBar(isFullScreen),
if (_liveRoomController.isPortrait.value) { body: isPortrait
return _buildPP; ? Obx(
} () {
return _buildPH; if (_liveRoomController.isPortrait.value) {
}, return _buildPP(isFullScreen);
) }
else return _buildPH(isFullScreen);
_buildBodyH, },
], )
), : _buildBodyH(isFullScreen),
), ),
); ],
);
});
} }
Widget get _buildPH { Widget _buildPH(bool isFullScreen) {
final isFullScreen = this.isFullScreen;
final height = maxWidth * 9 / 16; final height = maxWidth * 9 / 16;
final videoHeight = isFullScreen ? maxHeight : height; final videoHeight = isFullScreen ? maxHeight - padding.top : height;
final bottomHeight = maxHeight - padding.top - height - kToolbarHeight; final bottomHeight = maxHeight - padding.top - height - kToolbarHeight;
return Column( return Column(
children: [ children: [
Offstage(
offstage: isFullScreen,
child: _buildAppBar,
),
SizedBox( SizedBox(
width: maxWidth, width: maxWidth,
height: videoHeight, height: videoHeight,
@@ -456,18 +430,15 @@ class _LiveRoomPageState extends State<LiveRoomPage>
); );
} }
Widget get _buildPP { Widget _buildPP(bool isFullScreen) {
final isFullScreen = this.isFullScreen;
final bottomHeight = 70 + padding.bottom; final bottomHeight = 70 + padding.bottom;
final topPadding = padding.top + kToolbarHeight;
final videoHeight = isFullScreen final videoHeight = isFullScreen
? maxHeight - padding.top ? maxHeight - padding.top
: maxHeight - bottomHeight - topPadding; : maxHeight - bottomHeight;
return Stack( return Stack(
clipBehavior: Clip.none, clipBehavior: Clip.none,
children: [ children: [
Positioned.fill( Positioned.fill(
top: isFullScreen ? padding.top : topPadding,
bottom: isFullScreen ? 0 : bottomHeight, bottom: isFullScreen ? 0 : bottomHeight,
child: videoPlayerPanel( child: videoPlayerPanel(
width: maxWidth, width: maxWidth,
@@ -477,15 +448,6 @@ class _LiveRoomPageState extends State<LiveRoomPage>
alignment: isFullScreen ? Alignment.center : Alignment.topCenter, alignment: isFullScreen ? Alignment.center : Alignment.topCenter,
), ),
), ),
Positioned(
top: 0,
left: 0,
right: 0,
child: Offstage(
offstage: isFullScreen,
child: _buildAppBar,
),
),
Positioned( Positioned(
left: 0, left: 0,
right: 0, right: 0,
@@ -514,9 +476,10 @@ class _LiveRoomPageState extends State<LiveRoomPage>
); );
} }
PreferredSizeWidget get _buildAppBar { PreferredSizeWidget _buildAppBar(bool isFullScreen) {
final color = Theme.of(context).colorScheme.onSurfaceVariant; final color = Theme.of(context).colorScheme.onSurfaceVariant;
return AppBar( return AppBar(
toolbarHeight: isFullScreen ? 0 : null,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
foregroundColor: Colors.white, foregroundColor: Colors.white,
titleTextStyle: const TextStyle(color: Colors.white), titleTextStyle: const TextStyle(color: Colors.white),
@@ -677,56 +640,41 @@ class _LiveRoomPageState extends State<LiveRoomPage>
); );
} }
Widget get _buildBodyH { Widget _buildBodyH(bool isFullScreen) {
double videoWidth = double videoWidth =
clampDouble(maxHeight / maxWidth * 1.08, 0.56, 0.7) * maxWidth; clampDouble(maxHeight / maxWidth * 1.08, 0.56, 0.7) * maxWidth;
final rigthWidth = min(400.0, maxWidth - videoWidth - padding.horizontal); final rigthWidth = min(400.0, maxWidth - videoWidth - padding.horizontal);
videoWidth = maxWidth - rigthWidth; videoWidth = maxWidth - rigthWidth - padding.horizontal;
final videoHeight = maxHeight - padding.top; final videoHeight = maxHeight - padding.top;
return Obx( final width = isFullScreen ? maxWidth : videoWidth;
() { final height = isFullScreen ? maxHeight - padding.top : videoHeight;
final isFullScreen = this.isFullScreen; return Padding(
final width = isFullScreen ? maxWidth : videoWidth; padding: isFullScreen
final height = isFullScreen ? maxHeight : videoHeight; ? EdgeInsets.zero
return Column( : EdgeInsets.only(left: padding.left, right: padding.right),
children: [ child: Row(
Offstage( children: [
offstage: isFullScreen, Container(
child: _buildAppBar, width: width,
height: height,
margin: EdgeInsets.only(bottom: padding.bottom),
child: videoPlayerPanel(
isFullScreen,
fill: Colors.transparent,
width: width,
height: height,
), ),
Expanded( ),
child: Padding( Offstage(
padding: isFullScreen offstage: isFullScreen,
? EdgeInsets.zero child: SizedBox(
: EdgeInsets.only(left: padding.left, right: padding.right), width: rigthWidth,
child: Row( height: videoHeight,
children: [ child: _buildBottomWidget,
Container(
margin: EdgeInsets.only(bottom: padding.bottom),
width: width,
height: height,
child: videoPlayerPanel(
isFullScreen,
fill: Colors.transparent,
width: width,
height: height,
),
),
Offstage(
offstage: isFullScreen,
child: SizedBox(
width: rigthWidth,
height: videoHeight,
child: _buildBottomWidget,
),
),
],
),
),
), ),
], ),
); ],
}, ),
); );
} }

View File

@@ -42,8 +42,13 @@ abstract class CommonSearchPanelState<
controller: controller.scrollController, controller: controller.scrollController,
physics: const AlwaysScrollableScrollPhysics(), physics: const AlwaysScrollableScrollPhysics(),
slivers: [ slivers: [
if (widget.searchType.hasHeader) buildHeader(theme), ?buildHeader(theme),
Obx(() => _buildBody(theme, controller.loadingState.value)), SliverPadding(
padding: EdgeInsets.only(
bottom: MediaQuery.viewPaddingOf(context).bottom + 100,
),
sliver: Obx(() => _buildBody(theme, controller.loadingState.value)),
),
], ],
), ),
); );
@@ -56,12 +61,7 @@ abstract class CommonSearchPanelState<
Loading() => buildLoading, Loading() => buildLoading,
Success(:var response) => Success(:var response) =>
response?.isNotEmpty == true response?.isNotEmpty == true
? SliverPadding( ? buildList(theme, response!)
padding: EdgeInsets.only(
bottom: MediaQuery.viewPaddingOf(context).bottom + 100,
),
sliver: buildList(theme, response!),
)
: HttpError(onReload: controller.onReload), : HttpError(onReload: controller.onReload),
Error(:var errMsg) => HttpError( Error(:var errMsg) => HttpError(
errMsg: errMsg, errMsg: errMsg,
@@ -70,7 +70,7 @@ abstract class CommonSearchPanelState<
}; };
} }
Widget buildHeader(ThemeData theme) => throw UnimplementedError(); Widget? buildHeader(ThemeData theme) => null;
Widget buildList(ThemeData theme, List<T> list); Widget buildList(ThemeData theme, List<T> list);
} }

View File

@@ -76,6 +76,7 @@ class _MediaListPanelState extends State<MediaListPanel>
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
actions: [ actions: [
iconButton( iconButton(
iconSize: 20,
tooltip: widget.desc ? '顺序播放' : '倒序播放', tooltip: widget.desc ? '顺序播放' : '倒序播放',
icon: widget.desc icon: widget.desc
? const Icon(MdiIcons.sortAscending) ? const Icon(MdiIcons.sortAscending)
@@ -86,6 +87,7 @@ class _MediaListPanelState extends State<MediaListPanel>
}, },
), ),
iconButton( iconButton(
iconSize: 20,
tooltip: '关闭', tooltip: '关闭',
icon: const Icon(Icons.close), icon: const Icon(Icons.close),
onPressed: Get.back, onPressed: Get.back,

View File

@@ -181,7 +181,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
if (!(mode == FullScreenMode.vertical || if (!(mode == FullScreenMode.vertical ||
(mode == FullScreenMode.auto && isVertical) || (mode == FullScreenMode.auto && isVertical) ||
(mode == FullScreenMode.ratio && (mode == FullScreenMode.ratio &&
(isVertical || maxHeight / maxWidth < 1.25)))) { (isVertical || maxHeight / maxWidth < kScreenRatio)))) {
landscape(); landscape();
} }
}); });
@@ -581,9 +581,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
if (shouldShow) if (shouldShow)
AppBar( AppBar(
backgroundColor: themeData.colorScheme.surface backgroundColor: themeData.colorScheme.surface
.withValues( .withValues(alpha: scrollRatio),
alpha: scrollRatio,
),
toolbarHeight: 0, toolbarHeight: 0,
systemOverlayStyle: Platform.isAndroid systemOverlayStyle: Platform.isAndroid
? SystemUiOverlayStyle( ? SystemUiOverlayStyle(
@@ -605,7 +603,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
onlyOneScrollInBody: true, onlyOneScrollInBody: true,
pinnedHeaderSliverHeightBuilder: () { pinnedHeaderSliverHeightBuilder: () {
double pinnedHeight = this.isFullScreen || !isPortrait double pinnedHeight = this.isFullScreen || !isPortrait
? maxHeight - (isPortrait ? padding.top : 0) ? maxHeight - padding.top
: videoDetailController.isExpanding || : videoDetailController.isExpanding ||
videoDetailController.isCollapsing videoDetailController.isCollapsing
? animHeight ? animHeight
@@ -632,7 +630,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
}, },
headerSliverBuilder: (context, innerBoxIsScrolled) { headerSliverBuilder: (context, innerBoxIsScrolled) {
final height = isFullScreen || !isPortrait final height = isFullScreen || !isPortrait
? maxHeight - (isPortrait ? padding.top : 0) ? maxHeight - padding.top
: videoDetailController.isExpanding || : videoDetailController.isExpanding ||
videoDetailController.isCollapsing videoDetailController.isCollapsing
? animHeight ? animHeight
@@ -875,13 +873,10 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
final isFullScreen = this.isFullScreen; final isFullScreen = this.isFullScreen;
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
appBar: isFullScreen appBar: AppBar(backgroundColor: Colors.black, toolbarHeight: 0),
? null
: AppBar(backgroundColor: Colors.black, toolbarHeight: 0),
extendBodyBehindAppBar: true,
body: Padding( body: Padding(
padding: !isFullScreen padding: !isFullScreen
? padding.copyWith(bottom: 0) ? padding.copyWith(top: 0, bottom: 0)
: EdgeInsets.zero, : EdgeInsets.zero,
child: childWhenDisabledLandscapeInner(isFullScreen, padding), child: childWhenDisabledLandscapeInner(isFullScreen, padding),
), ),
@@ -893,6 +888,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
final double videoHeight = maxHeight - padding.vertical; final double videoHeight = maxHeight - padding.vertical;
final double width = videoHeight * ratio; final double width = videoHeight * ratio;
final videoWidth = isFullScreen ? maxWidth : width; final videoWidth = isFullScreen ? maxWidth : width;
final introWidth = maxWidth - width - padding.horizontal;
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@@ -907,7 +903,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
Offstage( Offstage(
offstage: isFullScreen, offstage: isFullScreen,
child: SizedBox( child: SizedBox(
width: maxWidth - width - padding.horizontal, width: introWidth,
height: maxHeight - padding.top, height: maxHeight - padding.top,
child: Scaffold( child: Scaffold(
key: videoDetailController.childKey, key: videoDetailController.childKey,
@@ -922,7 +918,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
controller: videoDetailController.tabCtr, controller: videoDetailController.tabCtr,
children: [ children: [
videoIntro( videoIntro(
width: maxWidth - width, width: introWidth,
height: maxHeight, height: maxHeight,
), ),
if (videoDetailController.showReply) videoReplyPanel(), if (videoDetailController.showReply) videoReplyPanel(),
@@ -1010,7 +1006,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
} }
final videoWidth = isFullScreen ? maxWidth : width; final videoWidth = isFullScreen ? maxWidth : width;
final double height = width * 9 / 16; final double height = width * 9 / 16;
final videoHeight = isFullScreen ? maxHeight : height; final videoHeight = isFullScreen ? maxHeight - padding.top : height;
if (height > maxHeight) { if (height > maxHeight) {
return childSplit(16 / 9); return childSplit(16 / 9);
} }
@@ -1101,12 +1097,11 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
final isFullScreen = this.isFullScreen; final isFullScreen = this.isFullScreen;
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
appBar: isFullScreen appBar: AppBar(backgroundColor: Colors.black, toolbarHeight: 0),
? null
: AppBar(backgroundColor: Colors.black, toolbarHeight: 0),
extendBodyBehindAppBar: true,
body: Padding( body: Padding(
padding: !isFullScreen ? padding.copyWith(bottom: 0) : EdgeInsets.zero, padding: !isFullScreen
? padding.copyWith(top: 0, bottom: 0)
: EdgeInsets.zero,
child: childWhenDisabledAlmostSquareInner(isFullScreen, padding), child: childWhenDisabledAlmostSquareInner(isFullScreen, padding),
), ),
); );
@@ -1125,7 +1120,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
} }
final shouldShowSeasonPanel = _shouldShowSeasonPanel; final shouldShowSeasonPanel = _shouldShowSeasonPanel;
final double height = maxHeight / 2.5; final double height = maxHeight / 2.5;
final videoHeight = isFullScreen ? maxHeight : height; final videoHeight = isFullScreen ? maxHeight - padding.top : height;
final bottomHeight = maxHeight - height - padding.top; final bottomHeight = maxHeight - height - padding.top;
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -1376,7 +1371,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
child = plPlayer(width: maxWidth, height: maxHeight, isPipMode: true); child = plPlayer(width: maxWidth, height: maxHeight, isPipMode: true);
} else if (!videoDetailController.horizontalScreen) { } else if (!videoDetailController.horizontalScreen) {
child = childWhenDisabled; child = childWhenDisabled;
} else if (maxWidth > maxHeight * 1.25) { } else if (maxWidth > maxHeight * kScreenRatio) {
child = childWhenDisabledLandscape; child = childWhenDisabledLandscape;
} else if (maxWidth * (9 / 16) < (2 / 5) * maxHeight) { } else if (maxWidth * (9 / 16) < (2 / 5) * maxHeight) {
child = childWhenDisabled; child = childWhenDisabled;
@@ -1748,7 +1743,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
showEpisodes: showEpisodes, showEpisodes: showEpisodes,
onShowMemberPage: onShowMemberPage, onShowMemberPage: onShowMemberPage,
isPortrait: isPortrait, isPortrait: isPortrait,
isHorizontal: isHorizontal ?? width! > height! * 1.25, isHorizontal: isHorizontal ?? width! > height! * kScreenRatio,
), ),
if (needRelated && if (needRelated &&
videoDetailController videoDetailController

View File

@@ -1256,18 +1256,20 @@ class PlPlayerController {
} }
await _videoPlayerController?.setRate(speed); await _videoPlayerController?.setRate(speed);
if (danmakuController != null) {
DanmakuOption currentOption = danmakuController!.option;
double defaultDuration = currentOption.duration * lastPlaybackSpeed;
double defaultStaticDuration =
currentOption.staticDuration * lastPlaybackSpeed;
DanmakuOption updatedOption = currentOption.copyWith(
duration: defaultDuration / speed,
staticDuration: defaultStaticDuration / speed,
);
danmakuController!.updateOption(updatedOption);
}
_playbackSpeed.value = speed; _playbackSpeed.value = speed;
if (danmakuController != null) {
try {
DanmakuOption currentOption = danmakuController!.option;
double defaultDuration = currentOption.duration * lastPlaybackSpeed;
double defaultStaticDuration =
currentOption.staticDuration * lastPlaybackSpeed;
DanmakuOption updatedOption = currentOption.copyWith(
duration: defaultDuration / speed,
staticDuration: defaultStaticDuration / speed,
);
danmakuController!.updateOption(updatedOption);
} catch (_) {}
}
} }
// 还原默认速度 // 还原默认速度
@@ -1591,7 +1593,7 @@ class PlPlayerController {
if ((mode == FullScreenMode.vertical || if ((mode == FullScreenMode.vertical ||
(mode == FullScreenMode.auto && isVertical) || (mode == FullScreenMode.auto && isVertical) ||
(mode == FullScreenMode.ratio && (mode == FullScreenMode.ratio &&
(isVertical || size.height / size.width < 1.25)))) { (isVertical || size.height / size.width < kScreenRatio)))) {
await verticalScreenForTwoSeconds(); await verticalScreenForTwoSeconds();
} else { } else {
await landscape(); await landscape();
@@ -1740,10 +1742,10 @@ class PlPlayerController {
} }
return; return;
} }
_playerCount = 0;
disableAutoEnterPip(); disableAutoEnterPip();
setPlayCallBack(null); setPlayCallBack(null);
dmState.clear(); dmState.clear();
_playerCount = 0;
_clearPreview(); _clearPreview();
Utils.channel.setMethodCallHandler(null); Utils.channel.setMethodCallHandler(null);
_timer?.cancel(); _timer?.cancel();

View File

@@ -1,3 +1,5 @@
const double kScreenRatio = 1.2;
// 全屏模式 // 全屏模式
enum FullScreenMode { enum FullScreenMode {
// 根据内容自适应 // 根据内容自适应
@@ -8,8 +10,8 @@ enum FullScreenMode {
vertical('强制竖屏'), vertical('强制竖屏'),
// 始终横屏 // 始终横屏
horizontal('强制横屏'), horizontal('强制横屏'),
// 屏幕长宽比<1.25或为竖屏视频时竖屏,否则横屏 // 屏幕长宽比 < kScreenRatio 或为竖屏视频时竖屏,否则横屏
ratio('屏幕长宽比<1.25或为竖屏视频时竖屏,否则横屏'), ratio('屏幕长宽比<$kScreenRatio或为竖屏视频时竖屏,否则横屏'),
// 强制重力转屏(仅安卓) // 强制重力转屏(仅安卓)
gravity('忽略系统方向锁定,强制按重力转屏(仅安卓)'); gravity('忽略系统方向锁定,强制按重力转屏(仅安卓)');

View File

@@ -1185,7 +1185,9 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
) )
..onLongPressStart = ((_) => ..onLongPressStart = ((_) =>
plPlayerController.setLongPressStatus(true)) plPlayerController.setLongPressStatus(true))
..onLongPressEnd = (_) => plPlayerController.setLongPressStatus(false); ..onLongPressEnd = ((_) => plPlayerController.setLongPressStatus(false))
..onLongPressCancel = (() =>
plPlayerController.setLongPressStatus(false));
late final OneSequenceGestureRecognizer _tapGestureRecognizer; late final OneSequenceGestureRecognizer _tapGestureRecognizer;
late final DoubleTapGestureRecognizer _doubleTapGestureRecognizer; late final DoubleTapGestureRecognizer _doubleTapGestureRecognizer;
StreamSubscription<bool>? _danmakuListener; StreamSubscription<bool>? _danmakuListener;

View File

@@ -86,6 +86,39 @@ class BottomControl extends StatelessWidget {
); );
} }
Widget progressBar() {
final child = Obx(() {
final int value = controller.sliderPositionSeconds.value;
final int max = controller.durationSeconds.value.inSeconds;
if (value > max || max <= 0) {
return const SizedBox.shrink();
}
return ProgressBar(
progress: Duration(seconds: value),
buffered: Duration(seconds: controller.bufferedSeconds.value),
total: Duration(seconds: max),
progressBarColor: primary,
baseBarColor: const Color(0x33FFFFFF),
bufferedBarColor: bufferedBarColor,
thumbColor: primary,
thumbGlowColor: thumbGlowColor,
barHeight: 3.5,
thumbRadius: 7,
thumbGlowRadius: 25,
onDragStart: onDragStart,
onDragUpdate: (e) => onDragUpdate(e, max),
onSeek: (e) => onSeek(e, max),
);
});
if (Utils.isDesktop) {
return MouseRegion(
cursor: SystemMouseCursors.click,
child: child,
);
}
return child;
}
return Padding( return Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 12), padding: const EdgeInsets.fromLTRB(10, 0, 10, 12),
child: Column( child: Column(
@@ -98,37 +131,7 @@ class BottomControl extends StatelessWidget {
clipBehavior: Clip.none, clipBehavior: Clip.none,
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
children: [ children: [
Obx(() { progressBar(),
final int value = controller.sliderPositionSeconds.value;
final int max = controller.durationSeconds.value.inSeconds;
final int buffer = controller.bufferedSeconds.value;
if (value > max || max <= 0) {
return const SizedBox.shrink();
}
final child = ProgressBar(
progress: Duration(seconds: value),
buffered: Duration(seconds: buffer),
total: Duration(seconds: max),
progressBarColor: primary,
baseBarColor: const Color(0x33FFFFFF),
bufferedBarColor: bufferedBarColor,
thumbColor: primary,
thumbGlowColor: thumbGlowColor,
barHeight: 3.5,
thumbRadius: 7,
thumbGlowRadius: 25,
onDragStart: onDragStart,
onDragUpdate: (e) => onDragUpdate(e, max),
onSeek: (e) => onSeek(e, max),
);
if (Utils.isDesktop) {
return MouseRegion(
cursor: SystemMouseCursors.click,
child: child,
);
}
return child;
}),
if (controller.enableSponsorBlock && if (controller.enableSponsorBlock &&
videoDetailController.segmentProgressList.isNotEmpty) videoDetailController.segmentProgressList.isNotEmpty)
Positioned( Positioned(

View File

@@ -197,7 +197,7 @@ abstract class ImageUtils {
cancelToken: cancelToken, cancelToken: cancelToken,
); );
if (Utils.isMobile) { if (Platform.isAndroid) {
if (response.statusCode == 200) { if (response.statusCode == 200) {
await SaverGallery.saveFile( await SaverGallery.saveFile(
filePath: filePath, filePath: filePath,
@@ -214,7 +214,7 @@ abstract class ImageUtils {
del: true, del: true,
); );
} else { } else {
if (Utils.isMobile) { if (Platform.isAndroid) {
await SaverGallery.saveFile( await SaverGallery.saveFile(
filePath: file.path, filePath: file.path,
fileName: name, fileName: name,
@@ -227,7 +227,7 @@ abstract class ImageUtils {
} }
}); });
final result = await Future.wait(futures, eagerError: true); final result = await Future.wait(futures, eagerError: true);
if (!Utils.isMobile) { if (!Platform.isAndroid) {
for (var res in result) { for (var res in result) {
if (res.statusCode == 200) { if (res.statusCode == 200) {
await saveFileImg( await saveFileImg(

View File

@@ -166,18 +166,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build_daemon name: build_daemon
sha256: "8e928697a82be082206edb0b9c99c5a4ad6bc31c9e9b8b2f291ae65cd4a25daa" sha256: "409002f1adeea601018715d613115cfaf0e31f512cb80ae4534c79867ae2363d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.4" version: "4.1.0"
build_runner: build_runner:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
sha256: "4e54dbeefdc70691ba80b3bce3976af63b5425c8c07dface348dfee664a0edc1" sha256: "8cd45bdd6217138f4cfbaf6286c93f270ae4b3e2e281e69c904bd00cdf8aa626"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.9.0" version: "2.10.0"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
@@ -384,10 +384,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: device_info_plus name: device_info_plus
sha256: "49413c8ca514dea7633e8def233b25efdf83ec8522955cc2c0e3ad802927e7c6" sha256: dd0e8e02186b2196c7848c9d394a5fd6e5b57a43a546082c5820b1ec72317e33
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "12.1.0" version: "12.2.0"
device_info_plus_platform_interface: device_info_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -951,10 +951,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: image_picker_platform_interface name: image_picker_platform_interface
sha256: "9f143b0dba3e459553209e20cc425c9801af48e6dfa4f01a0fcf927be3f41665" sha256: "567e056716333a1647c64bb6bd873cff7622233a5c3f694be28a583d4715690c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.11.0" version: "2.11.1"
image_picker_windows: image_picker_windows:
dependency: transitive dependency: transitive
description: description:
@@ -1518,10 +1518,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: share_plus name: share_plus
sha256: "3424e9d5c22fd7f7590254ba09465febd6f8827c8b19a44350de4ac31d92d3a6" sha256: "14c8860d4de93d3a7e53af51bff479598c4e999605290756bbbe45cf65b37840"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "12.0.0" version: "12.0.1"
share_plus_platform_interface: share_plus_platform_interface:
dependency: transitive dependency: transitive
description: description: