From ec8c010c96cefbe7434105e7cdc215fc886e5741 Mon Sep 17 00:00:00 2001 From: bggRGjQaUbCoE Date: Sat, 28 Dec 2024 12:32:04 +0800 Subject: [PATCH] opt: dynamicDetail/html page Closes #60 Signed-off-by: bggRGjQaUbCoE --- lib/common/widgets/html_render.dart | 4 +- lib/pages/about/index.dart | 3 +- .../bangumi/introduction/controller.dart | 4 +- lib/pages/dynamics/detail/view.dart | 282 ++++++++++-------- lib/pages/html/view.dart | 100 ++++--- .../live_room/widgets/bottom_control.dart | 5 +- lib/pages/login/view.dart | 8 +- lib/pages/member/view.dart | 5 +- lib/pages/setting/pages/logs.dart | 24 +- .../video/detail/introduction/controller.dart | 3 +- .../detail/reply/widgets/reply_item.dart | 3 +- .../detail/reply/widgets/reply_item_grpc.dart | 3 +- lib/pages/video/detail/view.dart | 19 +- .../video/detail/widgets/header_control.dart | 81 ++--- lib/utils/utils.dart | 60 ++-- 15 files changed, 304 insertions(+), 300 deletions(-) diff --git a/lib/common/widgets/html_render.dart b/lib/common/widgets/html_render.dart index dc932723..6e844128 100644 --- a/lib/common/widgets/html_render.dart +++ b/lib/common/widgets/html_render.dart @@ -69,7 +69,7 @@ Widget htmlRender({ ], style: { 'html': Style( - fontSize: FontSize(17), + fontSize: FontSize(16), lineHeight: LineHeight.percent(160), letterSpacing: 0.3, ), @@ -105,7 +105,7 @@ Widget htmlRender({ margin: Margins.only(bottom: 8), ), 'h3,h4,h5': Style( - fontSize: FontSize(17), + fontSize: FontSize(16), fontWeight: FontWeight.bold, margin: Margins.only(bottom: 4), ), diff --git a/lib/pages/about/index.dart b/lib/pages/about/index.dart index 8a5d1fa4..583d311e 100644 --- a/lib/pages/about/index.dart +++ b/lib/pages/about/index.dart @@ -310,8 +310,7 @@ class _AboutPageState extends State { onTap: () async { Get.back(); String data = await GStorage.exportAllSettings(); - Clipboard.setData(ClipboardData(text: data)); - SmartDialog.showToast('已复制到剪贴板'); + Utils.copyText(data); }, ), ListTile( diff --git a/lib/pages/bangumi/introduction/controller.dart b/lib/pages/bangumi/introduction/controller.dart index 2b7e99ab..52ac5379 100644 --- a/lib/pages/bangumi/introduction/controller.dart +++ b/lib/pages/bangumi/introduction/controller.dart @@ -7,7 +7,6 @@ import 'package:PiliPalaX/pages/common/common_controller.dart'; import 'package:PiliPalaX/pages/video/detail/introduction/controller.dart'; import 'package:PiliPalaX/utils/utils.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:get/get_navigation/src/dialog/dialog_route.dart'; @@ -325,8 +324,7 @@ class BangumiIntroController extends CommonController { ), onTap: () { Get.back(); - Clipboard.setData(ClipboardData(text: videoUrl)); - SmartDialog.showToast('已复制'); + Utils.copyText(videoUrl); }, ), ListTile( diff --git a/lib/pages/dynamics/detail/view.dart b/lib/pages/dynamics/detail/view.dart index db248646..ce8f5109 100644 --- a/lib/pages/dynamics/detail/view.dart +++ b/lib/pages/dynamics/detail/view.dart @@ -115,25 +115,39 @@ class _DynamicDetailPageState extends State } // 查看二级评论 - void replyReply(replyItem, id, isTop) { + void replyReply(context, replyItem, id, isTop) { EasyThrottle.throttle('replyReply', const Duration(milliseconds: 500), () { int oid = replyItem.oid.toInt(); int rpid = GlobalData().grpcReply ? replyItem.id.toInt() : replyItem.rpid; - Get.to( - () => Scaffold( - resizeToAvoidBottomInset: false, - appBar: AppBar(title: Text('评论详情')), - body: VideoReplyReplyPanel( - id: id, - oid: oid, - rpid: rpid, - source: 'dynamic', - replyType: ReplyType.values[replyType], - firstFloor: replyItem, - isTop: isTop ?? false, - ), - ), - ); + Widget replyReplyPage() => Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar(title: Text('评论详情')), + body: VideoReplyReplyPanel( + id: id, + oid: oid, + rpid: rpid, + source: 'dynamic', + replyType: ReplyType.values[replyType], + firstFloor: replyItem, + isTop: isTop ?? false, + ), + ); + if (this.context.orientation == Orientation.portrait) { + Get.to(replyReplyPage); + } else { + ScaffoldState? scaffoldState = Scaffold.maybeOf(context); + if (scaffoldState != null) { + scaffoldState.showBottomSheet( + (context) => MediaQuery.removePadding( + context: context, + removeLeft: true, + child: replyReplyPage(), + ), + ); + } else { + Get.to(replyReplyPage); + } + } }); } @@ -247,125 +261,137 @@ class _DynamicDetailPageState extends State }, icon: Transform.rotate( angle: pi / 2, - child: Icon(Icons.splitscreen), + child: Icon(Icons.splitscreen, size: 19), ), ), const SizedBox(width: 16), ] : null, ), - body: refreshIndicator( - onRefresh: () async { - await _dynamicDetailController.onRefresh(); - }, - child: Stack( - children: [ - OrientationBuilder( - builder: (context, orientation) { - double padding = max(context.width / 2 - Grid.maxRowWidth, 0); - if (orientation == Orientation.portrait) { - return CustomScrollView( - controller: _dynamicDetailController.scrollController, - physics: const AlwaysScrollableScrollPhysics(), - slivers: [ - SliverToBoxAdapter( - child: DynamicPanel( - item: _dynamicDetailController.item, - source: 'detail', - ), - ), - replyPersistentHeader(context), - Obx( - () => replyList( - _dynamicDetailController.loadingState.value), - ), - ] - .map((e) => SliverPadding( - padding: EdgeInsets.symmetric(horizontal: padding), - sliver: e)) - .toList(), - ); - } else { - return Row( - children: [ - Expanded( - flex: _ratio[0].toInt(), - child: CustomScrollView( - controller: ScrollController(), - physics: const AlwaysScrollableScrollPhysics(), - slivers: [ - SliverPadding( - padding: EdgeInsets.only(left: padding / 4), - sliver: SliverToBoxAdapter( - child: DynamicPanel( - item: _dynamicDetailController.item, - source: 'detail', - ), - ), - ), - ], - ), - ), - Expanded( - flex: _ratio[1].toInt(), - child: CustomScrollView( - controller: _dynamicDetailController.scrollController, - physics: const AlwaysScrollableScrollPhysics(), - slivers: [ - SliverPadding( - padding: EdgeInsets.only(right: padding / 4), - sliver: replyPersistentHeader(context), - ), - SliverPadding( - padding: EdgeInsets.only(right: padding / 4), - sliver: Obx( - () => replyList(_dynamicDetailController - .loadingState.value), - ), - ), - ], - ), - ), - ], - ); - } + body: context.orientation == Orientation.portrait + ? refreshIndicator( + onRefresh: () async { + await _dynamicDetailController.onRefresh(); }, - ), - if (_fabAnimationCtr != null) - Positioned( - bottom: MediaQuery.of(context).padding.bottom + 14, - right: 14, - child: SlideTransition( - position: Tween( - begin: const Offset(0, 2), - end: const Offset(0, 0), - ).animate(CurvedAnimation( - parent: _fabAnimationCtr!, - curve: Curves.easeInOut, - )), - child: FloatingActionButton( - heroTag: null, - onPressed: () { - feedBack(); - dynamic oid = _dynamicDetailController.oid ?? - IdUtils.bv2av(Get.parameters['bvid']!); - _dynamicDetailController.onReply( - context, - oid: oid, - replyType: ReplyType.values[replyType], - ); - }, - tooltip: '评论动态', - child: const Icon(Icons.reply), - ), - ), - ), - ], - ), - ), + child: _buildBody(context.orientation), + ) + : _buildBody(context.orientation), ); } + Widget _buildBody(Orientation orientation) => Stack( + children: [ + Builder( + builder: (context) { + double padding = max(context.width / 2 - Grid.maxRowWidth, 0); + if (orientation == Orientation.portrait) { + return CustomScrollView( + controller: _dynamicDetailController.scrollController, + physics: const AlwaysScrollableScrollPhysics(), + slivers: [ + SliverToBoxAdapter( + child: DynamicPanel( + item: _dynamicDetailController.item, + source: 'detail', + ), + ), + replyPersistentHeader(context), + Obx( + () => replyList( + _dynamicDetailController.loadingState.value), + ), + ] + .map((e) => SliverPadding( + padding: EdgeInsets.symmetric(horizontal: padding), + sliver: e)) + .toList(), + ); + } else { + return Row( + children: [ + Expanded( + flex: _ratio[0].toInt(), + child: CustomScrollView( + controller: ScrollController(), + physics: const AlwaysScrollableScrollPhysics(), + slivers: [ + SliverPadding( + padding: EdgeInsets.only(left: padding / 4), + sliver: SliverToBoxAdapter( + child: DynamicPanel( + item: _dynamicDetailController.item, + source: 'detail', + ), + ), + ), + ], + ), + ), + Expanded( + flex: _ratio[1].toInt(), + child: Scaffold( + body: refreshIndicator( + onRefresh: () async { + await _dynamicDetailController.onRefresh(); + }, + child: CustomScrollView( + controller: + _dynamicDetailController.scrollController, + physics: const AlwaysScrollableScrollPhysics(), + slivers: [ + SliverPadding( + padding: EdgeInsets.only(right: padding / 4), + sliver: replyPersistentHeader(context), + ), + SliverPadding( + padding: EdgeInsets.only(right: padding / 4), + sliver: Obx( + () => replyList(_dynamicDetailController + .loadingState.value), + ), + ), + ], + ), + ), + ), + ), + ], + ); + } + }, + ), + if (_fabAnimationCtr != null) + Positioned( + bottom: MediaQuery.of(context).padding.bottom + 14, + right: 14, + child: SlideTransition( + position: Tween( + begin: const Offset(0, 2), + end: const Offset(0, 0), + ).animate(CurvedAnimation( + parent: _fabAnimationCtr!, + curve: Curves.easeInOut, + )), + child: FloatingActionButton( + heroTag: null, + onPressed: () { + feedBack(); + dynamic oid = _dynamicDetailController.oid ?? + IdUtils.bv2av(Get.parameters['bvid']!); + _dynamicDetailController.onReply( + context, + oid: oid, + replyType: ReplyType.values[replyType], + ); + }, + tooltip: '评论动态', + child: const Icon(Icons.reply), + ), + ), + ), + ], + ); + SliverPersistentHeader replyPersistentHeader(BuildContext context) { return SliverPersistentHeader( delegate: _MySliverPersistentHeaderDelegate( @@ -454,7 +480,8 @@ class _DynamicDetailPageState extends State replyItem: loadingState.response.replies[index], showReplyRow: true, replyLevel: '1', - replyReply: replyReply, + replyReply: (replyItem, id, isTop) => + replyReply(context, replyItem, id, isTop), replyType: ReplyType.values[replyType], onReply: () { _dynamicDetailController.onReply( @@ -472,7 +499,8 @@ class _DynamicDetailPageState extends State replyItem: loadingState.response.replies[index], showReplyRow: true, replyLevel: '1', - replyReply: replyReply, + replyReply: (replyItem, id, isTop) => + replyReply(context, replyItem, id, isTop), replyType: ReplyType.values[replyType], onReply: () { _dynamicDetailController.onReply( diff --git a/lib/pages/html/view.dart b/lib/pages/html/view.dart index 1db362b9..6ccce409 100644 --- a/lib/pages/html/view.dart +++ b/lib/pages/html/view.dart @@ -8,11 +8,10 @@ import 'package:PiliPalaX/pages/video/detail/reply/widgets/reply_item_grpc.dart' import 'package:PiliPalaX/utils/extension.dart'; import 'package:PiliPalaX/utils/global_data.dart'; import 'package:PiliPalaX/utils/storage.dart'; +import 'package:PiliPalaX/utils/utils.dart'; import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:PiliPalaX/common/skeleton/video_reply.dart'; import 'package:PiliPalaX/common/widgets/html_render.dart'; @@ -106,27 +105,41 @@ class _HtmlRenderPageState extends State } } - void replyReply(replyItem, id, isTop) { + void replyReply(context, replyItem, id, isTop) { EasyThrottle.throttle('replyReply', const Duration(milliseconds: 500), () { int oid = replyItem.oid.toInt(); int rpid = GlobalData().grpcReply ? replyItem.id.toInt() : replyItem.rpid; - Get.to( - () => Scaffold( - resizeToAvoidBottomInset: false, - appBar: AppBar( - title: Text('评论详情'), - ), - body: VideoReplyReplyPanel( - id: id, - oid: oid, - rpid: rpid, - source: 'dynamic', - replyType: ReplyType.values[type], - firstFloor: replyItem, - isTop: isTop ?? false, - ), - ), - ); + Widget replyReplyPage() => Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar( + title: Text('评论详情'), + ), + body: VideoReplyReplyPanel( + id: id, + oid: oid, + rpid: rpid, + source: 'dynamic', + replyType: ReplyType.values[type], + firstFloor: replyItem, + isTop: isTop ?? false, + ), + ); + if (this.context.orientation == Orientation.portrait) { + Get.to(replyReplyPage); + } else { + ScaffoldState? scaffoldState = Scaffold.maybeOf(context); + if (scaffoldState != null) { + scaffoldState.showBottomSheet( + (context) => MediaQuery.removePadding( + context: context, + removeLeft: true, + child: replyReplyPage(), + ), + ); + } else { + Get.to(replyReplyPage); + } + } }); } @@ -178,7 +191,7 @@ class _HtmlRenderPageState extends State }, icon: Transform.rotate( angle: pi / 2, - child: Icon(Icons.splitscreen), + child: Icon(Icons.splitscreen, size: 19), ), ), IconButton( @@ -193,7 +206,7 @@ class _HtmlRenderPageState extends State icon: const Icon(Icons.open_in_browser_outlined, size: 19), ), PopupMenuButton( - icon: const Icon(Icons.more_vert), + icon: const Icon(Icons.more_vert, size: 19), itemBuilder: (BuildContext context) => [ PopupMenuItem( onTap: () => { @@ -226,10 +239,7 @@ class _HtmlRenderPageState extends State ), ), PopupMenuItem( - onTap: () => { - Clipboard.setData(ClipboardData(text: url)), - SmartDialog.showToast('已复制'), - }, + onTap: () => Utils.copyText(url), child: const Row( mainAxisSize: MainAxisSize.min, children: [ @@ -322,23 +332,25 @@ class _HtmlRenderPageState extends State Theme.of(context).dividerColor.withOpacity(0.05)), Expanded( flex: _ratio[1].toInt(), - child: CustomScrollView( - controller: _htmlRenderCtr.scrollController, - slivers: [ - SliverPadding( - padding: EdgeInsets.only(right: padding / 4), - sliver: SliverToBoxAdapter( - child: replyHeader(), + child: Scaffold( + body: CustomScrollView( + controller: _htmlRenderCtr.scrollController, + slivers: [ + SliverPadding( + padding: EdgeInsets.only(right: padding / 4), + sliver: SliverToBoxAdapter( + child: replyHeader(), + ), ), - ), - SliverPadding( - padding: EdgeInsets.only(right: padding / 4), - sliver: Obx( - () => - replyList(_htmlRenderCtr.loadingState.value), + SliverPadding( + padding: EdgeInsets.only(right: padding / 4), + sliver: Obx( + () => replyList( + _htmlRenderCtr.loadingState.value), + ), ), - ), - ], + ], + ), ), ), ], @@ -414,7 +426,8 @@ class _HtmlRenderPageState extends State replyItem: loadingState.response.replies[index], showReplyRow: true, replyLevel: '1', - replyReply: replyReply, + replyReply: (replyItem, id, isTop) => + replyReply(context, replyItem, id, isTop), replyType: ReplyType.values[type], onReply: () { _htmlRenderCtr.onReply( @@ -431,7 +444,8 @@ class _HtmlRenderPageState extends State replyItem: loadingState.response.replies[index], showReplyRow: true, replyLevel: '1', - replyReply: replyReply, + replyReply: (replyItem, id, isTop) => + replyReply(context, replyItem, id, isTop), replyType: ReplyType.values[type], onReply: () { _htmlRenderCtr.onReply( diff --git a/lib/pages/live_room/widgets/bottom_control.dart b/lib/pages/live_room/widgets/bottom_control.dart index f7d2ce8e..1c1f7843 100644 --- a/lib/pages/live_room/widgets/bottom_control.dart +++ b/lib/pages/live_room/widgets/bottom_control.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'package:floating/floating.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:PiliPalaX/models/video/play/url.dart'; import 'package:PiliPalaX/pages/live_room/index.dart'; import 'package:PiliPalaX/plugin/pl_player/index.dart'; @@ -91,9 +90,7 @@ class _BottomControlState extends State { widget.controller!.hiddenControls(false); try { canUsePiP = await widget.floating!.isPipAvailable; - } on PlatformException catch (_) { - canUsePiP = false; - } + } catch (_) {} if (canUsePiP) { await widget.floating!.enable(const EnableManual()); } else {} diff --git a/lib/pages/login/view.dart b/lib/pages/login/view.dart index d637478f..910e4d62 100644 --- a/lib/pages/login/view.dart +++ b/lib/pages/login/view.dart @@ -1,6 +1,7 @@ import 'dart:ui'; import 'package:PiliPalaX/common/constants.dart'; +import 'package:PiliPalaX/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; @@ -120,10 +121,9 @@ class _LoginPageState extends State { // _loginPageCtr.codeInfo.value['data']?['url'] ?? "", // mode: LaunchMode.externalApplication); // 复制到剪贴板 - Clipboard.setData(ClipboardData( - text: _loginPageCtr.codeInfo.value['data']?['url'] ?? "")); - SmartDialog.showToast('已复制到剪贴板,可粘贴至已登录的app私信处发送,然后点击已发送的链接打开', - displayTime: const Duration(seconds: 5)); + Utils.copyText( + _loginPageCtr.codeInfo.value['data']?['url'] ?? '', + toastText: '已复制到剪贴板,可粘贴至已登录的app私信处发送,然后点击已发送的链接打开'); }, child: Padding( padding: diff --git a/lib/pages/member/view.dart b/lib/pages/member/view.dart index b4a5a467..df2755d4 100644 --- a/lib/pages/member/view.dart +++ b/lib/pages/member/view.dart @@ -454,10 +454,7 @@ class _MemberPageState extends State const SizedBox(width: 5), GestureDetector( onTap: () { - Clipboard.setData( - ClipboardData(text: _memberController.mid.toString()), - ); - SmartDialog.showToast('已复制${_memberController.mid}至剪贴板'); + Utils.copyText(_memberController.mid.toString()); }, child: Container( padding: diff --git a/lib/pages/setting/pages/logs.dart b/lib/pages/setting/pages/logs.dart index 49b1e445..19d60aae 100644 --- a/lib/pages/setting/pages/logs.dart +++ b/lib/pages/setting/pages/logs.dart @@ -1,8 +1,7 @@ import 'dart:io'; import 'package:PiliPalaX/common/widgets/loading_widget.dart'; +import 'package:PiliPalaX/utils/utils.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:url_launcher/url_launcher.dart'; import '../../../services/loggeer.dart'; class LogsPage extends StatefulWidget { @@ -72,25 +71,17 @@ class _LogsPageState extends State { } void copyLogs() async { - await Clipboard.setData(ClipboardData(text: fileContent)); - if (context.mounted) { + await Utils.copyText(fileContent, needToast: false); + if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('复制成功')), ); } } - void feedback() { - launchUrl( - Uri.parse('https://github.com/bggRGjQaUbCoE/PiliPalaX/issues'), - // 系统自带浏览器打开 - mode: LaunchMode.externalApplication, - ); - } - void clearLogsHandle() async { if (await clearLogs()) { - if (context.mounted) { + if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('已清空')), ); @@ -114,7 +105,8 @@ class _LogsPageState extends State { copyLogs(); break; case 'feedback': - feedback(); + Utils.launchURL( + 'https://github.com/bggRGjQaUbCoE/PiliPalaX/issues'); break; case 'clear': clearLogsHandle(); @@ -160,9 +152,7 @@ class _LogsPageState extends State { ), TextButton.icon( onPressed: () async { - await Clipboard.setData( - ClipboardData(text: log['body']), - ); + await Utils.copyText(log['body'], needToast: false); if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index cd80edf3..0fa58b3b 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -434,8 +434,7 @@ class VideoIntroController extends GetxController ), onTap: () { Get.back(); - Clipboard.setData(ClipboardData(text: videoUrl)); - SmartDialog.showToast('已复制'); + Utils.copyText(videoUrl); }, ), ListTile( diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 0acc3259..7ab54e40 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -1008,9 +1008,8 @@ class MorePanel extends StatelessWidget { } break; case 'copyAll': - await Clipboard.setData(ClipboardData(text: message)); - SmartDialog.showToast('已复制'); Get.back(); + Utils.copyText(message); break; case 'copyFreedom': Get.back(); diff --git a/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart b/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart index 1d73fdf2..764003fe 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart @@ -1059,9 +1059,8 @@ class ReplyItemGrpc extends StatelessWidget { } break; case 'copyAll': - await Clipboard.setData(ClipboardData(text: message)); - SmartDialog.showToast('已复制'); Get.back(); + Utils.copyText(message); break; case 'copyFreedom': Get.back(); diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index fbcbc511..7da335e1 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -25,7 +25,6 @@ import 'package:PiliPalaX/utils/utils.dart'; import 'package:auto_orientation/auto_orientation.dart'; import 'package:easy_debounce/easy_throttle.dart'; import 'package:floating/floating.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_svg/svg.dart'; import 'package:get/get.dart'; @@ -164,15 +163,17 @@ class _VideoDetailPageState extends State appbarStreamListen(); // lifecycleListener(); autoScreen(); - Utils.channel.setMethodCallHandler((call) async { - if (call.method == 'onUserLeaveHint') { - if (autoPiP && - plPlayerController?.playerStatus.status.value == - PlayerStatus.playing) { - enterPip(); + if (Platform.isAndroid) { + Utils.channel.setMethodCallHandler((call) async { + if (call.method == 'onUserLeaveHint') { + if (autoPiP && + plPlayerController?.playerStatus.status.value == + PlayerStatus.playing) { + enterPip(); + } } - } - }); + }); + } // _animationController = AnimationController( // vsync: this, // duration: const Duration(milliseconds: 300), diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index bd2a1151..22233ed8 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -5,6 +5,7 @@ import 'dart:math'; import 'package:PiliPalaX/pages/setting/widgets/switch_item.dart'; import 'package:PiliPalaX/utils/extension.dart'; import 'package:PiliPalaX/utils/id_utils.dart'; +import 'package:PiliPalaX/utils/utils.dart'; import 'package:canvas_danmaku/canvas_danmaku.dart'; import 'package:floating/floating.dart'; import 'package:flutter/material.dart'; @@ -340,11 +341,9 @@ class _HeaderControlState extends State { subtitle: Text( '${player.state.width}x${player.state.height}'), onTap: () { - Clipboard.setData( - ClipboardData( - text: - "Resolution\n${player.state.width}x${player.state.height}", - ), + Utils.copyText( + 'Resolution\n${player.state.width}x${player.state.height}', + needToast: false, ); }, ), @@ -355,11 +354,9 @@ class _HeaderControlState extends State { .state.videoParams .toString()), onTap: () { - Clipboard.setData( - ClipboardData( - text: - "VideoParams\n${player.state.videoParams}", - ), + Utils.copyText( + 'VideoParams\n${player.state.videoParams}', + needToast: false, ); }, ), @@ -370,11 +367,9 @@ class _HeaderControlState extends State { .state.audioParams .toString()), onTap: () { - Clipboard.setData( - ClipboardData( - text: - "AudioParams\n${player.state.audioParams}", - ), + Utils.copyText( + 'AudioParams\n${player.state.audioParams}', + needToast: false, ); }, ), @@ -384,11 +379,9 @@ class _HeaderControlState extends State { subtitle: Text( player.state.playlist.toString()), onTap: () { - Clipboard.setData( - ClipboardData( - text: - "Media\n${player.state.playlist}", - ), + Utils.copyText( + 'Media\n${player.state.playlist}', + needToast: false, ); }, ), @@ -399,11 +392,9 @@ class _HeaderControlState extends State { .state.track.audio .toString()), onTap: () { - Clipboard.setData( - ClipboardData( - text: - "AudioTrack\n${player.state.track.audio}", - ), + Utils.copyText( + 'AudioTrack\n${player.state.track.audio}', + needToast: false, ); }, ), @@ -414,11 +405,9 @@ class _HeaderControlState extends State { .state.track.video .toString()), onTap: () { - Clipboard.setData( - ClipboardData( - text: - "VideoTrack\n${player.state.track.audio}", - ), + Utils.copyText( + 'VideoTrack\n${player.state.track.audio}', + needToast: false, ); }, ), @@ -428,11 +417,9 @@ class _HeaderControlState extends State { subtitle: Text( player.state.pitch.toString()), onTap: () { - Clipboard.setData( - ClipboardData( - text: - "pitch\n${player.state.pitch}", - ), + Utils.copyText( + 'pitch\n${player.state.pitch}', + needToast: false, ); }), ListTile( @@ -441,11 +428,9 @@ class _HeaderControlState extends State { subtitle: Text( player.state.rate.toString()), onTap: () { - Clipboard.setData( - ClipboardData( - text: - "rate\n${player.state.rate}", - ), + Utils.copyText( + 'rate\n${player.state.rate}', + needToast: false, ); }), ListTile( @@ -455,11 +440,9 @@ class _HeaderControlState extends State { .state.audioBitrate .toString()), onTap: () { - Clipboard.setData( - ClipboardData( - text: - "AudioBitrate\n${player.state.audioBitrate}", - ), + Utils.copyText( + 'AudioBitrate\n${player.state.audioBitrate}', + needToast: false, ); }, ), @@ -469,11 +452,9 @@ class _HeaderControlState extends State { subtitle: Text( player.state.volume.toString()), onTap: () { - Clipboard.setData( - ClipboardData( - text: - "Volume\n${player.state.volume}", - ), + Utils.copyText( + 'Volume\n${player.state.volume}', + needToast: false, ); }, ), diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index c18c058c..2f47f9fc 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -18,7 +18,6 @@ import 'package:PiliPalaX/utils/feed_back.dart'; import 'package:PiliPalaX/utils/login.dart'; import 'package:PiliPalaX/utils/storage.dart'; import 'package:crypto/crypto.dart'; -import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -437,9 +436,15 @@ class Utils { ); } - static void copyText(String text) { + static Future copyText( + String text, { + bool needToast = true, + String? toastText, + }) async { Clipboard.setData(ClipboardData(text: text)); - SmartDialog.showToast('已复制'); + if (needToast) { + SmartDialog.showToast(toastText ?? '已复制'); + } } static launchURL(String url) async { @@ -766,9 +771,9 @@ class Utils { } // 版本对比 - static bool needUpdate(localVersion, remoteVersion) { - return localVersion != remoteVersion; - } + // static bool needUpdate(localVersion, remoteVersion) { + // return localVersion != remoteVersion; + // } // 检查更新 // static Future checkUpdate() async { @@ -859,29 +864,26 @@ class Utils { // } // 下载适用于当前系统的安装包 - static Future matchVersion(data) async { - await SmartDialog.dismiss(); - // 获取设备信息 - DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); - if (Platform.isAndroid) { - AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; - // [arm64-v8a] - String abi = androidInfo.supportedAbis.first; - late String downloadUrl; - if (data.assets.isNotEmpty) { - for (var i in data.assets) { - if (i.downloadUrl.contains(abi)) { - downloadUrl = i.downloadUrl; - } - } - // 应用外下载 - launchUrl( - Uri.parse(downloadUrl), - mode: LaunchMode.externalApplication, - ); - } - } - } + // static Future matchVersion(data) async { + // await SmartDialog.dismiss(); + // // 获取设备信息 + // DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + // if (Platform.isAndroid) { + // AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; + // // [arm64-v8a] + // String abi = androidInfo.supportedAbis.first; + // late String downloadUrl; + // if (data.assets.isNotEmpty) { + // for (var i in data.assets) { + // if (i.downloadUrl.contains(abi)) { + // downloadUrl = i.downloadUrl; + // } + // } + // // 应用外下载 + // launchURL(downloadUrl); + // } + // } + // } // 时间戳转时间 static tampToSeektime(number) {