mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-05-13 20:53:58 +08:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2890d72e5 | ||
|
|
5c029c8f64 | ||
|
|
c37a631df2 | ||
|
|
82030b8d06 | ||
|
|
e362f75dac | ||
|
|
3fecf7c0a4 | ||
|
|
801043468d | ||
|
|
1b4f588671 | ||
|
|
7ad48570f0 | ||
|
|
5b8c68303f |
@@ -6,15 +6,16 @@ import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:media_kit/media_kit.dart';
|
||||
import 'package:media_kit_video/media_kit_video.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
import 'package:status_bar_control/status_bar_control.dart';
|
||||
import 'interactive_viewer_boundary.dart';
|
||||
import 'interactive_viewer.dart' as custom;
|
||||
|
||||
@@ -142,17 +143,21 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
|
||||
_transformationController!.value = _animation?.value ?? Matrix4.identity();
|
||||
}
|
||||
|
||||
SystemUiMode? mode;
|
||||
setStatusBar() async {
|
||||
if (Platform.isIOS || Platform.isAndroid) {
|
||||
await StatusBarControl.setHidden(
|
||||
true,
|
||||
animation: StatusBarAnimation.FADE,
|
||||
SystemChrome.setEnabledSystemUIMode(
|
||||
SystemUiMode.immersiveSticky,
|
||||
);
|
||||
}
|
||||
if (Platform.isAndroid &&
|
||||
(await DeviceInfoPlugin().androidInfo).version.sdkInt < 29) {
|
||||
mode = SystemUiMode.manual;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() async {
|
||||
void dispose() {
|
||||
widget.onClose?.call(true);
|
||||
_player?.dispose();
|
||||
_pageController?.dispose();
|
||||
@@ -160,7 +165,10 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
|
||||
_animationController.dispose();
|
||||
if (widget.setStatusBar != false) {
|
||||
if (Platform.isIOS || Platform.isAndroid) {
|
||||
StatusBarControl.setHidden(false, animation: StatusBarAnimation.FADE);
|
||||
SystemChrome.setEnabledSystemUIMode(
|
||||
mode ?? SystemUiMode.edgeToEdge,
|
||||
overlays: SystemUiOverlay.values,
|
||||
);
|
||||
}
|
||||
}
|
||||
for (int index = 0; index < widget.sources.length; index++) {
|
||||
|
||||
@@ -41,134 +41,137 @@ class VideoCardH extends StatelessWidget {
|
||||
try {
|
||||
type = videoItem.type;
|
||||
} catch (_) {}
|
||||
return Stack(
|
||||
children: [
|
||||
Semantics(
|
||||
label: Utils.videoItemSemantics(videoItem),
|
||||
excludeSemantics: true,
|
||||
// customSemanticsActions: <CustomSemanticsAction, void Function()>{
|
||||
// for (var item in actions)
|
||||
// CustomSemanticsAction(
|
||||
// label: item.title.isEmpty ? 'label' : item.title): item.onTap!,
|
||||
// },
|
||||
child: InkWell(
|
||||
onLongPress: () {
|
||||
if (onLongPress != null) {
|
||||
onLongPress!();
|
||||
} else {
|
||||
imageSaveDialog(
|
||||
context: context,
|
||||
title: videoItem.title is String
|
||||
? videoItem.title
|
||||
: videoItem.title is List
|
||||
? (videoItem.title as List)
|
||||
.map((item) => item['text'])
|
||||
.join()
|
||||
: '',
|
||||
cover: videoItem.pic,
|
||||
);
|
||||
}
|
||||
},
|
||||
onTap: () async {
|
||||
if (onTap != null) {
|
||||
onTap?.call();
|
||||
return;
|
||||
}
|
||||
if (type == 'ketang') {
|
||||
SmartDialog.showToast('课堂视频暂不支持播放');
|
||||
return;
|
||||
}
|
||||
if (videoItem is HotVideoItemModel &&
|
||||
videoItem.redirectUrl?.isNotEmpty == true) {
|
||||
if (Utils.viewPgcFromUri(videoItem.redirectUrl!)) {
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: Stack(
|
||||
children: [
|
||||
Semantics(
|
||||
label: Utils.videoItemSemantics(videoItem),
|
||||
excludeSemantics: true,
|
||||
// customSemanticsActions: <CustomSemanticsAction, void Function()>{
|
||||
// for (var item in actions)
|
||||
// CustomSemanticsAction(
|
||||
// label: item.title.isEmpty ? 'label' : item.title): item.onTap!,
|
||||
// },
|
||||
child: InkWell(
|
||||
onLongPress: () {
|
||||
if (onLongPress != null) {
|
||||
onLongPress!();
|
||||
} else {
|
||||
imageSaveDialog(
|
||||
context: context,
|
||||
title: videoItem.title is String
|
||||
? videoItem.title
|
||||
: videoItem.title is List
|
||||
? (videoItem.title as List)
|
||||
.map((item) => item['text'])
|
||||
.join()
|
||||
: '',
|
||||
cover: videoItem.pic,
|
||||
);
|
||||
}
|
||||
},
|
||||
onTap: () async {
|
||||
if (onTap != null) {
|
||||
onTap?.call();
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
final int cid = videoItem.cid ??
|
||||
await SearchHttp.ab2c(aid: aid, bvid: bvid);
|
||||
Utils.toViewPage(
|
||||
'bvid=$bvid&cid=$cid',
|
||||
arguments: {
|
||||
'videoItem': videoItem,
|
||||
'heroTag': Utils.makeHeroTag(aid)
|
||||
},
|
||||
);
|
||||
} catch (err) {
|
||||
SmartDialog.showToast(err.toString());
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: StyleString.safeSpace,
|
||||
vertical: 5,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
AspectRatio(
|
||||
aspectRatio: StyleString.aspectRatio,
|
||||
child: LayoutBuilder(
|
||||
builder: (BuildContext context,
|
||||
BoxConstraints boxConstraints) {
|
||||
final double maxWidth = boxConstraints.maxWidth;
|
||||
final double maxHeight = boxConstraints.maxHeight;
|
||||
return Stack(
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
src: videoItem.pic as String,
|
||||
width: maxWidth,
|
||||
height: maxHeight,
|
||||
),
|
||||
if (videoItem is HotVideoItemModel &&
|
||||
videoItem.pgcLabel?.isNotEmpty == true)
|
||||
PBadge(
|
||||
text: videoItem.pgcLabel,
|
||||
top: 6.0,
|
||||
right: 6.0,
|
||||
if (type == 'ketang') {
|
||||
SmartDialog.showToast('课堂视频暂不支持播放');
|
||||
return;
|
||||
}
|
||||
if (videoItem is HotVideoItemModel &&
|
||||
videoItem.redirectUrl?.isNotEmpty == true) {
|
||||
if (Utils.viewPgcFromUri(videoItem.redirectUrl!)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
final int cid = videoItem.cid ??
|
||||
await SearchHttp.ab2c(aid: aid, bvid: bvid);
|
||||
Utils.toViewPage(
|
||||
'bvid=$bvid&cid=$cid',
|
||||
arguments: {
|
||||
'videoItem': videoItem,
|
||||
'heroTag': Utils.makeHeroTag(aid)
|
||||
},
|
||||
);
|
||||
} catch (err) {
|
||||
SmartDialog.showToast(err.toString());
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: StyleString.safeSpace,
|
||||
vertical: 5,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
AspectRatio(
|
||||
aspectRatio: StyleString.aspectRatio,
|
||||
child: LayoutBuilder(
|
||||
builder: (BuildContext context,
|
||||
BoxConstraints boxConstraints) {
|
||||
final double maxWidth = boxConstraints.maxWidth;
|
||||
final double maxHeight = boxConstraints.maxHeight;
|
||||
return Stack(
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
src: videoItem.pic as String,
|
||||
width: maxWidth,
|
||||
height: maxHeight,
|
||||
),
|
||||
if (videoItem.duration != 0)
|
||||
PBadge(
|
||||
text: Utils.timeFormat(videoItem.duration!),
|
||||
right: 6.0,
|
||||
bottom: 6.0,
|
||||
type: 'gray',
|
||||
),
|
||||
if (type != 'video')
|
||||
PBadge(
|
||||
text: type,
|
||||
left: 6.0,
|
||||
bottom: 6.0,
|
||||
type: 'primary',
|
||||
),
|
||||
// if (videoItem.rcmdReason != null &&
|
||||
// videoItem.rcmdReason.content != '')
|
||||
// pBadge(videoItem.rcmdReason.content, context,
|
||||
// 6.0, 6.0, null, null),
|
||||
],
|
||||
);
|
||||
},
|
||||
if (videoItem is HotVideoItemModel &&
|
||||
videoItem.pgcLabel?.isNotEmpty == true)
|
||||
PBadge(
|
||||
text: videoItem.pgcLabel,
|
||||
top: 6.0,
|
||||
right: 6.0,
|
||||
),
|
||||
if (videoItem.duration != 0)
|
||||
PBadge(
|
||||
text: Utils.timeFormat(videoItem.duration!),
|
||||
right: 6.0,
|
||||
bottom: 6.0,
|
||||
type: 'gray',
|
||||
),
|
||||
if (type != 'video')
|
||||
PBadge(
|
||||
text: type,
|
||||
left: 6.0,
|
||||
bottom: 6.0,
|
||||
type: 'primary',
|
||||
),
|
||||
// if (videoItem.rcmdReason != null &&
|
||||
// videoItem.rcmdReason.content != '')
|
||||
// pBadge(videoItem.rcmdReason.content, context,
|
||||
// 6.0, 6.0, null, null),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
videoContent(context),
|
||||
],
|
||||
const SizedBox(width: 10),
|
||||
videoContent(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (source == 'normal')
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: 12,
|
||||
child: VideoPopupMenu(
|
||||
size: 29,
|
||||
iconSize: 17,
|
||||
videoItem: videoItem,
|
||||
if (source == 'normal')
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: 12,
|
||||
child: VideoPopupMenu(
|
||||
size: 29,
|
||||
iconSize: 17,
|
||||
videoItem: videoItem,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ abstract class CommonPublishPageState<T extends CommonPublishPage>
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() async {
|
||||
void dispose() {
|
||||
focusNode.dispose();
|
||||
editController.dispose();
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
|
||||
@@ -37,7 +37,6 @@ class _HomePageState extends State<HomePage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(toolbarHeight: 0),
|
||||
body: Column(
|
||||
@@ -45,12 +44,12 @@ class _HomePageState extends State<HomePage>
|
||||
if (!_homeController.useSideBar &&
|
||||
context.orientation == Orientation.portrait)
|
||||
customAppBar,
|
||||
if (_homeController.tabs.length > 1) ...[
|
||||
const SizedBox(height: 4),
|
||||
if (_homeController.tabs.length > 1)
|
||||
Material(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: SizedBox(
|
||||
child: Container(
|
||||
height: 42,
|
||||
padding: const EdgeInsets.only(top: 4),
|
||||
child: TabBar(
|
||||
controller: _homeController.tabController,
|
||||
tabs: [
|
||||
@@ -69,8 +68,8 @@ class _HomePageState extends State<HomePage>
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
] else
|
||||
)
|
||||
else
|
||||
const SizedBox(height: 6),
|
||||
Expanded(
|
||||
child: tabBarView(
|
||||
|
||||
@@ -259,7 +259,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
return PiPSwitcher(
|
||||
getChildWhenDisabled: () =>
|
||||
childWhenDisabled(orientation == Orientation.portrait),
|
||||
getChildWhenEnabled: () => videoPlayerPanel,
|
||||
getChildWhenEnabled: () => videoPlayerPanel(),
|
||||
floating: floating,
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -157,11 +157,10 @@ class _MainAppState extends State<MainApp>
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() async {
|
||||
void dispose() {
|
||||
MainApp.routeObserver.unsubscribe(this);
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
// await GrpcClient.instance.shutdown();
|
||||
await GStorage.close();
|
||||
GStorage.close();
|
||||
EventBus().off(EventName.loginEvent);
|
||||
PiliScheme.listener?.cancel();
|
||||
super.dispose();
|
||||
|
||||
@@ -75,9 +75,9 @@ class _SearchResultPageState extends State<SearchResultPage>
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
const SizedBox(height: 4),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.only(top: 4),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: Theme(
|
||||
data: ThemeData(
|
||||
|
||||
@@ -213,7 +213,6 @@ List<SettingsModel> get styleSettings => [
|
||||
leading: Icon(Icons.fit_screen_outlined),
|
||||
setKey: SettingBoxKey.videoPlayerRemoveSafeArea,
|
||||
defaultVal: false,
|
||||
needReboot: true,
|
||||
),
|
||||
SettingsModel(
|
||||
settingsType: SettingsType.sw1tch,
|
||||
@@ -2106,7 +2105,7 @@ List<SettingsModel> get extraSettings => [
|
||||
title: '使用可折叠的播放页面',
|
||||
leading: Icon(Icons.video_settings),
|
||||
setKey: SettingBoxKey.collapsibleVideoPage,
|
||||
defaultVal: false,
|
||||
defaultVal: true,
|
||||
onChanged: (value) {
|
||||
GStorage.collapsibleVideoPage = value;
|
||||
},
|
||||
|
||||
@@ -130,7 +130,7 @@ class VideoDetailController extends GetxController
|
||||
StreamSubscription<Duration>? positionSubscription;
|
||||
|
||||
late final scrollKey = GlobalKey<ExtendedNestedScrollViewState>();
|
||||
late String _direction = 'horizontal';
|
||||
late RxString direction = 'horizontal'.obs;
|
||||
late final RxDouble scrollRatio = 0.0.obs;
|
||||
late final ScrollController scrollCtr = ScrollController()
|
||||
..addListener(scrollListener);
|
||||
@@ -140,8 +140,9 @@ class VideoDetailController extends GetxController
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
);
|
||||
late final double minVideoHeight = Get.width * 9 / 16;
|
||||
late final double maxVideoHeight = max(Get.height * 0.65, Get.width);
|
||||
late final double minVideoHeight = min(Get.height, Get.width) * 9 / 16;
|
||||
late final double maxVideoHeight =
|
||||
max(max(Get.height, Get.width) * 0.65, min(Get.height, Get.width));
|
||||
late double videoHeight = minVideoHeight;
|
||||
|
||||
void setVideoHeight() {
|
||||
@@ -150,11 +151,17 @@ class VideoDetailController extends GetxController
|
||||
? 'horizontal'
|
||||
: 'vertical'
|
||||
: 'horizontal';
|
||||
if (GStorage.collapsibleVideoPage.not || scrollCtr.hasClients.not) {
|
||||
if (GStorage.collapsibleVideoPage.not) {
|
||||
this.direction.value = direction;
|
||||
return;
|
||||
}
|
||||
if (_direction != direction) {
|
||||
_direction = direction;
|
||||
if (scrollCtr.hasClients.not) {
|
||||
videoHeight = direction == 'vertical' ? maxVideoHeight : minVideoHeight;
|
||||
this.direction.value = direction;
|
||||
return;
|
||||
}
|
||||
if (this.direction.value != direction) {
|
||||
this.direction.value = direction;
|
||||
double videoHeight =
|
||||
direction == 'vertical' ? maxVideoHeight : minVideoHeight;
|
||||
if (this.videoHeight != videoHeight) {
|
||||
@@ -1077,7 +1084,7 @@ class VideoDetailController extends GetxController
|
||||
? null
|
||||
: Duration(milliseconds: data.timeLength!),
|
||||
// 宽>高 水平 否则 垂直
|
||||
direction: _direction,
|
||||
direction: direction.value,
|
||||
bvid: bvid,
|
||||
cid: cid.value,
|
||||
enableHeart: enableHeart,
|
||||
|
||||
@@ -305,9 +305,9 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
final ThemeData t = Theme.of(context);
|
||||
return SliverLayoutBuilder(
|
||||
builder: (BuildContext context, SliverConstraints constraints) {
|
||||
// bool isHorizontal = constraints.crossAxisExtent >
|
||||
// constraints.viewportMainAxisExtent * 1.25;
|
||||
bool isHorizontal = context.orientation == Orientation.landscape;
|
||||
bool isHorizontal = context.orientation == Orientation.landscape &&
|
||||
constraints.crossAxisExtent >
|
||||
constraints.viewportMainAxisExtent * 1.25;
|
||||
return SliverPadding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: StyleString.safeSpace,
|
||||
|
||||
@@ -125,15 +125,19 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel>
|
||||
return GStorage.slideDismissReplyPage
|
||||
? GestureDetector(
|
||||
onPanDown: (event) {
|
||||
_downPos = event.localPosition;
|
||||
if (event.localPosition.dx > 30) {
|
||||
_isSliding = false;
|
||||
} else {
|
||||
_downPos = event.localPosition;
|
||||
}
|
||||
},
|
||||
onPanUpdate: (event) {
|
||||
if (_isSliding == false) {
|
||||
return;
|
||||
} else if (_isSliding == null) {
|
||||
if (_downPos != null && _downPos!.dx <= 25) {
|
||||
if (_downPos != null) {
|
||||
Offset cumulativeDelta = event.localPosition - _downPos!;
|
||||
if (cumulativeDelta.dx.abs() > 3 * cumulativeDelta.dy.abs()) {
|
||||
if (cumulativeDelta.dx.abs() >= cumulativeDelta.dy.abs()) {
|
||||
_isSliding = true;
|
||||
setState(() {
|
||||
padding.value = event.localPosition.dx;
|
||||
|
||||
@@ -193,7 +193,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
// begin: MediaQuery.of(context).orientation == Orientation.landscape
|
||||
// ? context.height
|
||||
// : ((enableVerticalExpand &&
|
||||
// plPlayerController?.direction.value == 'vertical')
|
||||
// videoDetailController.direction.value == 'vertical')
|
||||
// ? context.width * 5 / 4
|
||||
// : context.width * 9 / 16),
|
||||
// end: 0,
|
||||
@@ -568,7 +568,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
final double videoWidth = context.width;
|
||||
// debugPrint(videoDetailController.tabCtr.index);
|
||||
if (enableVerticalExpand &&
|
||||
plPlayerController?.direction.value == 'vertical') {
|
||||
videoDetailController.direction.value == 'vertical') {
|
||||
videoHeight = context.width;
|
||||
}
|
||||
if (MediaQuery.of(context).orientation ==
|
||||
@@ -648,7 +648,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
Widget get childWhenDisabledAlmostSquareInner => Obx(
|
||||
() {
|
||||
if (enableVerticalExpand &&
|
||||
plPlayerController?.direction.value == 'vertical') {
|
||||
videoDetailController.direction.value == 'vertical') {
|
||||
final double videoHeight = context.height -
|
||||
(removeSafeArea
|
||||
? 0
|
||||
@@ -743,7 +743,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
Widget get childWhenDisabledLandscapeInner => Obx(
|
||||
() {
|
||||
if (enableVerticalExpand &&
|
||||
plPlayerController?.direction.value == 'vertical') {
|
||||
videoDetailController.direction.value == 'vertical') {
|
||||
final double videoHeight = context.height -
|
||||
(removeSafeArea ? 0 : MediaQuery.of(context).padding.top);
|
||||
final double videoWidth = videoHeight * 9 / 16;
|
||||
|
||||
@@ -107,6 +107,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
StreamSubscription? _listenerDetail;
|
||||
StreamSubscription? _listenerLoadingState;
|
||||
StreamSubscription? _listenerCid;
|
||||
StreamSubscription? _listenerFS;
|
||||
|
||||
Box get setting => GStorage.setting;
|
||||
|
||||
@@ -199,6 +200,15 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
|
||||
videoDetailController.animationController.addListener(animListener);
|
||||
|
||||
if (removeSafeArea) {
|
||||
_listenerFS =
|
||||
videoDetailController.plPlayerController.isFullScreen.listen((value) {
|
||||
if (videoDetailController.direction.value == 'vertical') {
|
||||
refreshPage();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
}
|
||||
|
||||
@@ -255,14 +265,10 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
videoDetailController.scrollCtr.offset /
|
||||
videoDetailController.videoHeight);
|
||||
} else {
|
||||
if (videoDetailController.scrollKey.currentState?.mounted == true) {
|
||||
videoDetailController.scrollKey.currentState?.setState(() {});
|
||||
}
|
||||
refreshPage();
|
||||
}
|
||||
} else {
|
||||
if (videoDetailController.scrollKey.currentState?.mounted == true) {
|
||||
videoDetailController.scrollKey.currentState?.setState(() {});
|
||||
}
|
||||
refreshPage();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -378,6 +384,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
_listenerDetail?.cancel();
|
||||
_listenerLoadingState?.cancel();
|
||||
_listenerCid?.cancel();
|
||||
_listenerFS?.cancel();
|
||||
|
||||
videoDetailController.skipTimer?.cancel();
|
||||
videoDetailController.skipTimer = null;
|
||||
@@ -567,10 +574,9 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
}
|
||||
|
||||
void animListener() {
|
||||
if (videoDetailController.animationController.isForwardOrCompleted &&
|
||||
videoDetailController.scrollKey.currentState?.mounted == true) {
|
||||
if (videoDetailController.animationController.isForwardOrCompleted) {
|
||||
cal();
|
||||
videoDetailController.scrollKey.currentState?.setState(() {});
|
||||
refreshPage();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -612,6 +618,12 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
}
|
||||
}
|
||||
|
||||
void refreshPage() {
|
||||
if (videoDetailController.scrollKey.currentState?.mounted == true) {
|
||||
videoDetailController.scrollKey.currentState?.setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
Widget get childWhenDisabled => SafeArea(
|
||||
top: !removeSafeArea &&
|
||||
MediaQuery.of(context).orientation == Orientation.portrait &&
|
||||
@@ -637,7 +649,8 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
toolbarHeight: 0,
|
||||
),
|
||||
if (videoDetailController.scrollRatio.value != 0 &&
|
||||
videoDetailController.scrollCtr.offset != 0)
|
||||
videoDetailController.scrollCtr.offset != 0 &&
|
||||
context.orientation == Orientation.portrait)
|
||||
AppBar(
|
||||
backgroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
@@ -673,22 +686,14 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
videoDetailController.animationController.value == 1) {
|
||||
videoDetailController.isExpanding = false;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (videoDetailController.scrollKey.currentState?.mounted ==
|
||||
true) {
|
||||
videoDetailController.scrollRatio.value = 0;
|
||||
videoDetailController.scrollKey.currentState
|
||||
?.setState(() {});
|
||||
}
|
||||
videoDetailController.scrollRatio.value = 0;
|
||||
refreshPage();
|
||||
});
|
||||
} else if (videoDetailController.isCollapsing &&
|
||||
videoDetailController.animationController.value == 1) {
|
||||
videoDetailController.isCollapsing = false;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (videoDetailController.scrollKey.currentState?.mounted ==
|
||||
true) {
|
||||
videoDetailController.scrollKey.currentState
|
||||
?.setState(() {});
|
||||
}
|
||||
refreshPage();
|
||||
});
|
||||
}
|
||||
return height;
|
||||
@@ -697,6 +702,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
(BuildContext context, bool innerBoxIsScrolled) {
|
||||
return [
|
||||
SliverAppBar(
|
||||
primary: false,
|
||||
automaticallyImplyLeading: false,
|
||||
pinned: true,
|
||||
expandedHeight: isFullScreen ||
|
||||
@@ -740,7 +746,9 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
Orientation.landscape ||
|
||||
removeSafeArea
|
||||
? 0
|
||||
: MediaQuery.of(context).padding.top)
|
||||
: MediaQuery.of(this.context)
|
||||
.padding
|
||||
.top)
|
||||
: videoDetailController.isExpanding ||
|
||||
videoDetailController.isCollapsing
|
||||
? animHeight
|
||||
@@ -846,7 +854,8 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
),
|
||||
);
|
||||
return videoDetailController.scrollRatio.value == 0 ||
|
||||
videoDetailController.scrollCtr.offset == 0
|
||||
videoDetailController.scrollCtr.offset == 0 ||
|
||||
context.orientation != Orientation.portrait
|
||||
? const SizedBox.shrink()
|
||||
: Positioned.fill(
|
||||
bottom: -2,
|
||||
@@ -934,7 +943,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
Widget get childWhenDisabledAlmostSquareInner => Obx(
|
||||
() {
|
||||
if (enableVerticalExpand &&
|
||||
plPlayerController?.direction.value == 'vertical') {
|
||||
videoDetailController.direction.value == 'vertical') {
|
||||
final double videoHeight = context.height -
|
||||
(removeSafeArea
|
||||
? 0
|
||||
@@ -1029,7 +1038,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
Widget get childWhenDisabledLandscapeInner => Obx(
|
||||
() {
|
||||
if (enableVerticalExpand &&
|
||||
plPlayerController?.direction.value == 'vertical') {
|
||||
videoDetailController.direction.value == 'vertical') {
|
||||
final double videoHeight = context.height -
|
||||
(removeSafeArea ? 0 : MediaQuery.of(context).padding.top);
|
||||
final double videoWidth = videoHeight * 9 / 16;
|
||||
@@ -1807,6 +1816,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
|
||||
Widget videoIntro([bool needRelated = true, bool needCtr = true]) {
|
||||
Widget introPanel() => Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
backgroundColor: Colors.transparent,
|
||||
body: CustomScrollView(
|
||||
key: const PageStorageKey<String>('简介'),
|
||||
|
||||
@@ -311,10 +311,10 @@ class PlPlayerController {
|
||||
textScaleFactor: MediaQuery.textScalerOf(Get.context!).scale(1),
|
||||
);
|
||||
|
||||
late Function getPlayerKey;
|
||||
Function? getPlayerKey;
|
||||
|
||||
void updateSubtitleStyle() {
|
||||
getPlayerKey().currentState?.update(
|
||||
getPlayerKey?.call()?.currentState?.update(
|
||||
subtitleViewConfiguration: subtitleViewConfiguration,
|
||||
);
|
||||
}
|
||||
@@ -1370,49 +1370,50 @@ class PlPlayerController {
|
||||
}
|
||||
|
||||
// 全屏
|
||||
Future<void> triggerFullScreen({bool status = true}) async {
|
||||
stopScreenTimer();
|
||||
FullScreenMode mode = FullScreenModeCode.fromCode(
|
||||
setting.get(SettingBoxKey.fullScreenMode, defaultValue: 0))!;
|
||||
bool removeSafeArea = setting.get(SettingBoxKey.videoPlayerRemoveSafeArea,
|
||||
defaultValue: false);
|
||||
if (!isFullScreen.value && status) {
|
||||
// StatusBarControl.setHidden(true, animation: StatusBarAnimation.FADE);
|
||||
hideStatusBar();
|
||||
void triggerFullScreen({bool status = true, int duration = 500}) {
|
||||
EasyThrottle.throttle('fullScreen', Duration(milliseconds: duration),
|
||||
() async {
|
||||
stopScreenTimer();
|
||||
FullScreenMode mode = FullScreenModeCode.fromCode(
|
||||
setting.get(SettingBoxKey.fullScreenMode, defaultValue: 0))!;
|
||||
bool removeSafeArea = setting.get(SettingBoxKey.videoPlayerRemoveSafeArea,
|
||||
defaultValue: false);
|
||||
if (!isFullScreen.value && status) {
|
||||
hideStatusBar();
|
||||
|
||||
/// 按照视频宽高比决定全屏方向
|
||||
toggleFullScreen(true);
|
||||
/// 按照视频宽高比决定全屏方向
|
||||
toggleFullScreen(true);
|
||||
|
||||
/// 进入全屏
|
||||
if (mode == FullScreenMode.none) {
|
||||
return;
|
||||
/// 进入全屏
|
||||
if (mode == FullScreenMode.none) {
|
||||
return;
|
||||
}
|
||||
if (mode == FullScreenMode.gravity) {
|
||||
fullAutoModeForceSensor();
|
||||
return;
|
||||
}
|
||||
if (mode == FullScreenMode.vertical ||
|
||||
(mode == FullScreenMode.auto && direction.value == 'vertical') ||
|
||||
(mode == FullScreenMode.ratio &&
|
||||
(Get.height / Get.width < 1.25 ||
|
||||
direction.value == 'vertical'))) {
|
||||
await verticalScreenForTwoSeconds();
|
||||
} else {
|
||||
await landScape();
|
||||
}
|
||||
} else if (isFullScreen.value && !status) {
|
||||
if (!removeSafeArea) showStatusBar();
|
||||
toggleFullScreen(false);
|
||||
if (mode == FullScreenMode.none) {
|
||||
return;
|
||||
}
|
||||
if (!setting.get(SettingBoxKey.horizontalScreen, defaultValue: false)) {
|
||||
await verticalScreenForTwoSeconds();
|
||||
} else {
|
||||
await autoScreen();
|
||||
}
|
||||
}
|
||||
if (mode == FullScreenMode.gravity) {
|
||||
fullAutoModeForceSensor();
|
||||
return;
|
||||
}
|
||||
if (mode == FullScreenMode.vertical ||
|
||||
(mode == FullScreenMode.auto && direction.value == 'vertical') ||
|
||||
(mode == FullScreenMode.ratio &&
|
||||
(Get.height / Get.width < 1.25 ||
|
||||
direction.value == 'vertical'))) {
|
||||
await verticalScreenForTwoSeconds();
|
||||
} else {
|
||||
await landScape();
|
||||
}
|
||||
} else if (isFullScreen.value && !status) {
|
||||
// StatusBarControl.setHidden(false, animation: StatusBarAnimation.FADE);
|
||||
if (!removeSafeArea) showStatusBar();
|
||||
toggleFullScreen(false);
|
||||
if (mode == FullScreenMode.none) {
|
||||
return;
|
||||
}
|
||||
if (!setting.get(SettingBoxKey.horizontalScreen, defaultValue: false)) {
|
||||
await verticalScreenForTwoSeconds();
|
||||
} else {
|
||||
await autoScreen();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void addPositionListener(Function(Duration position) listener) =>
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:auto_orientation/auto_orientation.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:status_bar_control/status_bar_control.dart';
|
||||
|
||||
import '../../../utils/storage.dart';
|
||||
|
||||
@@ -75,7 +74,6 @@ Future<void> hideStatusBar() async {
|
||||
await SystemChrome.setEnabledSystemUIMode(
|
||||
SystemUiMode.immersiveSticky,
|
||||
);
|
||||
StatusBarControl.setHidden(true);
|
||||
}
|
||||
|
||||
//退出全屏显示
|
||||
@@ -94,7 +92,6 @@ Future<void> showStatusBar() async {
|
||||
mode,
|
||||
overlays: SystemUiOverlay.values,
|
||||
);
|
||||
StatusBarControl.setHidden(false);
|
||||
} else if (Platform.isMacOS || Platform.isWindows || Platform.isLinux) {
|
||||
await const MethodChannel('com.alexmercerind/media_kit_video')
|
||||
.invokeMethod(
|
||||
|
||||
@@ -161,6 +161,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
plPlayerController.getPlayerKey = () => key;
|
||||
animationController = AnimationController(
|
||||
vsync: this, duration: const Duration(milliseconds: 100));
|
||||
videoController = plPlayerController.videoController!;
|
||||
@@ -169,7 +170,6 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
plPlayerController.headerControl = widget.headerControl;
|
||||
plPlayerController.bottomControl = widget.bottomControl;
|
||||
plPlayerController.danmuWidget = widget.danmuWidget;
|
||||
plPlayerController.getPlayerKey = () => key;
|
||||
defaultBtmProgressBehavior = GStorage.setting.get(
|
||||
SettingBoxKey.btmProgressBehavior,
|
||||
defaultValue: BtmProgressBehavior.values.first.code);
|
||||
@@ -629,8 +629,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
size: 24,
|
||||
color: Colors.white,
|
||||
),
|
||||
fuc: () =>
|
||||
plPlayerController.triggerFullScreen(status: !isFullScreen),
|
||||
fuc: () => plPlayerController.triggerFullScreen(
|
||||
status: !isFullScreen, duration: 800),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -842,11 +842,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
details.localFocalPoint.dy - _initialFocalPoint.dy;
|
||||
|
||||
void fullScreenTrigger(bool status) {
|
||||
EasyThrottle.throttle(
|
||||
'fullScreen', const Duration(milliseconds: 800),
|
||||
() async {
|
||||
await plPlayerController.triggerFullScreen(status: status);
|
||||
});
|
||||
plPlayerController.triggerFullScreen(
|
||||
status: status, duration: 800);
|
||||
}
|
||||
|
||||
if (cumulativeDy > threshold) {
|
||||
@@ -1170,12 +1167,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
details.localPosition.dy - _initialFocalPoint.dy;
|
||||
|
||||
void fullScreenTrigger(bool status) {
|
||||
EasyThrottle.throttle(
|
||||
'fullScreen', const Duration(milliseconds: 800),
|
||||
() async {
|
||||
await plPlayerController.triggerFullScreen(
|
||||
status: status);
|
||||
});
|
||||
plPlayerController.triggerFullScreen(status: status);
|
||||
}
|
||||
|
||||
if (cumulativeDy > threshold) {
|
||||
|
||||
@@ -1741,14 +1741,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
status_bar_control:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: status_bar_control
|
||||
sha256: "7f2c1f3f7fd13b85ed284eb7ca3f74ceb8dcfdd25636d3a84186d0a687d36693"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -139,7 +139,7 @@ dependencies:
|
||||
url: https://github.com/bggRGjQaUbCoE/canvas_danmaku.git
|
||||
ref: main
|
||||
# 状态栏图标控制
|
||||
status_bar_control: ^3.2.1
|
||||
# status_bar_control: ^3.2.1
|
||||
# 代理
|
||||
system_proxy: ^0.1.0
|
||||
# pip
|
||||
|
||||
Reference in New Issue
Block a user