mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-06-28 13:20:16 +08:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4256c2b023 | ||
|
|
bbcf0dec1b | ||
|
|
da52cac2c6 |
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
);
|
],
|
||||||
},
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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('忽略系统方向锁定,强制按重力转屏(仅安卓)');
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
20
pubspec.lock
20
pubspec.lock
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user