From 54d003fdb16c6b0a331bf46f874b8e5e87cbeb5a Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 26 Jul 2023 13:38:16 +0800 Subject: [PATCH 1/3] =?UTF-8?q?mod:=20=E8=87=AA=E5=AE=9A=E4=B9=89toast?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E3=80=81=E8=AF=A6=E6=83=85=E9=A1=B5=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/widgets/custom_toast.dart | 23 ++ lib/common/widgets/stat/danmu.dart | 2 +- lib/common/widgets/stat/view.dart | 2 +- lib/main.dart | 5 +- lib/pages/video/detail/introduction/view.dart | 309 +++++++++--------- lib/pages/video/detail/reply/widgets/zan.dart | 4 +- 6 files changed, 181 insertions(+), 164 deletions(-) create mode 100644 lib/common/widgets/custom_toast.dart diff --git a/lib/common/widgets/custom_toast.dart b/lib/common/widgets/custom_toast.dart new file mode 100644 index 000000000..57b93c901 --- /dev/null +++ b/lib/common/widgets/custom_toast.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; + +class CustomToast extends StatelessWidget { + final String msg; + const CustomToast({Key? key, required this.msg}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom), + padding: const EdgeInsets.symmetric(horizontal: 17, vertical: 10), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primaryContainer.withOpacity(0.8), + borderRadius: BorderRadius.circular(20), + ), + child: Text(msg, + style: Theme.of(context) + .textTheme + .labelMedium! + .copyWith(color: Theme.of(context).colorScheme.primary)), + ); + } +} diff --git a/lib/common/widgets/stat/danmu.dart b/lib/common/widgets/stat/danmu.dart index 5ea9cb018..44f662a98 100644 --- a/lib/common/widgets/stat/danmu.dart +++ b/lib/common/widgets/stat/danmu.dart @@ -24,7 +24,7 @@ class StatDanMu extends StatelessWidget { size: 14, color: color, ), - const SizedBox(width: 3), + const SizedBox(width: 2), Text( Utils.numFormat(danmu!), style: TextStyle( diff --git a/lib/common/widgets/stat/view.dart b/lib/common/widgets/stat/view.dart index 4f2b34416..8b97b605f 100644 --- a/lib/common/widgets/stat/view.dart +++ b/lib/common/widgets/stat/view.dart @@ -24,7 +24,7 @@ class StatView extends StatelessWidget { size: 13, color: color, ), - const SizedBox(width: 3), + const SizedBox(width: 2), Text( Utils.numFormat(view!), style: TextStyle( diff --git a/lib/main.dart b/lib/main.dart index ce0793c19..af386de19 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,6 +4,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:dynamic_color/dynamic_color.dart'; +import 'package:pilipala/common/widgets/custom_toast.dart'; import 'package:pilipala/http/init.dart'; import 'package:pilipala/pages/search/index.dart'; import 'package:pilipala/pages/video/detail/index.dart'; @@ -61,7 +62,9 @@ class MyApp extends StatelessWidget { fallbackLocale: const Locale("zh", "CN"), getPages: Routes.getPages, home: const MainApp(), - builder: FlutterSmartDialog.init(), + builder: FlutterSmartDialog.init( + toastBuilder: (String msg) => CustomToast(msg: msg), + ), navigatorObservers: [ VideoDetailPage.routeObserver, SearchPage.routeObserver diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 8b1a63802..682bfda00 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -107,6 +107,7 @@ class _VideoInfoState extends State with TickerProviderStateMixin { sheetHeight = localCache.get('sheetHeight'); } + // 收藏 showFavBottomSheet() { if (videoIntroController.user.get(UserBoxKey.userMid) == null) { SmartDialog.showToast('账号未登录'); @@ -122,8 +123,20 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ); } + // 视频介绍 + showIntroDetail() { + showBottomSheet( + context: context, + enableDrag: true, + builder: (BuildContext context) { + return IntroDetail(videoDetail: widget.videoDetail!); + }, + ); + } + @override Widget build(BuildContext context) { + ThemeData t = Theme.of(context); return SliverPadding( padding: const EdgeInsets.only( left: StyleString.safeSpace, right: StyleString.safeSpace, top: 13), @@ -133,15 +146,7 @@ class _VideoInfoState extends State with TickerProviderStateMixin { crossAxisAlignment: CrossAxisAlignment.start, children: [ GestureDetector( - onTap: () { - showBottomSheet( - context: context, - enableDrag: true, - builder: (BuildContext context) { - return IntroDetail(videoDetail: widget.videoDetail!); - }, - ); - }, + onTap: () => showIntroDetail(), child: Row( children: [ Expanded( @@ -168,9 +173,7 @@ class _VideoInfoState extends State with TickerProviderStateMixin { MaterialStateProperty.all(EdgeInsets.zero), backgroundColor: MaterialStateProperty.resolveWith((states) { - return Theme.of(context) - .highlightColor - .withOpacity(0.2); + return t.highlightColor.withOpacity(0.2); }), ), onPressed: () { @@ -189,46 +192,49 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ], ), ), - const SizedBox(height: 6), - Row( - children: [ - const SizedBox(width: 2), - StatView( - theme: 'black', - view: !widget.loadingStatus - ? widget.videoDetail!.stat!.view - : videoItem['stat'].view, - size: 'medium', - ), - const SizedBox(width: 10), - StatDanMu( - theme: 'black', - danmu: !widget.loadingStatus - ? widget.videoDetail!.stat!.danmaku - : videoItem['stat'].danmaku, - size: 'medium', - ), - const SizedBox(width: 10), - Text( - Utils.dateFormat( - !widget.loadingStatus - ? widget.videoDetail!.pubdate - : videoItem['pubdate'], - formatType: 'detail'), - style: const TextStyle(fontSize: 12), - ), - ], + GestureDetector( + onTap: () => showIntroDetail(), + child: Row( + children: [ + StatView( + theme: 'gray', + view: !widget.loadingStatus + ? widget.videoDetail!.stat!.view + : videoItem['stat'].view, + size: 'medium', + ), + const SizedBox(width: 10), + StatDanMu( + theme: 'gray', + danmu: !widget.loadingStatus + ? widget.videoDetail!.stat!.danmaku + : videoItem['stat'].danmaku, + size: 'medium', + ), + const SizedBox(width: 10), + Text( + Utils.dateFormat( + !widget.loadingStatus + ? widget.videoDetail!.pubdate + : videoItem['pubdate'], + formatType: 'detail'), + style: TextStyle( + fontSize: 12, + color: t.colorScheme.outline, + ), + ), + ], + ), ), + const SizedBox(height: 6), // 点赞收藏转发 - Padding( - padding: const EdgeInsets.only(top: 15), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: actionRow( - context, - videoIntroController, - videoDetailCtr, - ), + SingleChildScrollView( + padding: const EdgeInsets.only(top: 7, bottom: 7), + scrollDirection: Axis.horizontal, + child: actionRow( + context, + videoIntroController, + videoDetailCtr, ), ), // 合集 @@ -237,122 +243,105 @@ class _VideoInfoState extends State with TickerProviderStateMixin { seasonPanel(widget.videoDetail!.ugcSeason!, widget.videoDetail!.pages!.first.cid, sheetHeight) ], - // Divider( - // height: 26, - // color: Theme.of(context).dividerColor.withOpacity(0.1), - // ), - const SizedBox(height: 20), GestureDetector( - onTap: () { - int mid = !widget.loadingStatus - ? widget.videoDetail!.owner!.mid - : videoItem['owner'].mid; - String face = !widget.loadingStatus - ? widget.videoDetail!.owner!.face - : videoItem['owner'].face; - Get.toNamed('/member?mid=$mid', arguments: { - 'face': face, - 'heroTag': (mid + 99).toString() - }); - }, - child: Row( - children: [ - const SizedBox(width: 5), - NetworkImgLayer( - type: 'avatar', - src: !widget.loadingStatus - ? widget.videoDetail!.owner!.face - : videoItem['owner'].face, - width: 34, - height: 34, - fadeInDuration: Duration.zero, - fadeOutDuration: Duration.zero, - ), - const SizedBox(width: 10), - Text( - !widget.loadingStatus - ? widget.videoDetail!.owner!.name - : videoItem['owner'].name, - style: const TextStyle(fontSize: 13), - ), - const SizedBox(width: 10), - Text( - widget.loadingStatus - ? '- 粉丝' - : Utils.numFormat( - videoIntroController.userStat['follower']), - style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .labelSmall! - .fontSize, - color: Theme.of(context).colorScheme.outline), - ), - const Spacer(), - AnimatedOpacity( - opacity: widget.loadingStatus ? 0 : 1, - duration: const Duration(milliseconds: 150), - child: SizedBox( - height: 32, - child: Obx( - () => videoIntroController.followStatus.isNotEmpty - ? TextButton( - onPressed: () => videoIntroController - .actionRelationMod(), - style: TextButton.styleFrom( - padding: const EdgeInsets.only( - left: 8, right: 8), - foregroundColor: - videoIntroController.followStatus[ - 'attribute'] != - 0 - ? Theme.of(context) - .colorScheme - .outline - : Theme.of(context) - .colorScheme - .onPrimary, - backgroundColor: + onTap: () { + int mid = !widget.loadingStatus + ? widget.videoDetail!.owner!.mid + : videoItem['owner'].mid; + String face = !widget.loadingStatus + ? widget.videoDetail!.owner!.face + : videoItem['owner'].face; + Get.toNamed('/member?mid=$mid', arguments: { + 'face': face, + 'heroTag': (mid + 99).toString() + }); + }, + child: Padding( + padding: const EdgeInsets.only( + top: 12, bottom: 12, left: 4, right: 4), + child: Row( + children: [ + NetworkImgLayer( + type: 'avatar', + src: !widget.loadingStatus + ? widget.videoDetail!.owner!.face + : videoItem['owner'].face, + width: 34, + height: 34, + fadeInDuration: Duration.zero, + fadeOutDuration: Duration.zero, + ), + const SizedBox(width: 10), + Text( + !widget.loadingStatus + ? widget.videoDetail!.owner!.name + : videoItem['owner'].name, + style: const TextStyle(fontSize: 13), + ), + const SizedBox(width: 10), + Text( + widget.loadingStatus + ? '-' + : Utils.numFormat(videoIntroController + .userStat['follower']), + style: TextStyle( + fontSize: t.textTheme.labelSmall!.fontSize, + color: t.colorScheme.outline), + ), + const Spacer(), + AnimatedOpacity( + opacity: widget.loadingStatus ? 0 : 1, + duration: const Duration(milliseconds: 150), + child: SizedBox( + height: 32, + child: Obx( + () => videoIntroController + .followStatus.isNotEmpty + ? TextButton( + onPressed: () => videoIntroController + .actionRelationMod(), + style: TextButton.styleFrom( + padding: const EdgeInsets.only( + left: 8, right: 8), + foregroundColor: + videoIntroController + .followStatus[ + 'attribute'] != + 0 + ? t.colorScheme.outline + : t.colorScheme.onPrimary, + backgroundColor: + videoIntroController + .followStatus[ + 'attribute'] != + 0 + ? t.colorScheme + .onInverseSurface + : t.colorScheme + .primary, // 设置按钮背景色 + ), + child: Text( videoIntroController.followStatus[ 'attribute'] != 0 - ? Theme.of(context) - .colorScheme - .onInverseSurface - : Theme.of(context) - .colorScheme - .primary, // 设置按钮背景色 - ), - child: Text( - videoIntroController.followStatus[ - 'attribute'] != - 0 - ? '已关注' - : '关注', - style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .labelMedium! - .fontSize), - ), - ) - : ElevatedButton( - onPressed: () => videoIntroController - .actionRelationMod(), - child: const Text('关注'), - ), + ? '已关注' + : '关注', + style: TextStyle( + fontSize: t.textTheme + .labelMedium!.fontSize), + ), + ) + : ElevatedButton( + onPressed: () => videoIntroController + .actionRelationMod(), + child: const Text('关注'), + ), + ), + ), ), - ), + ], ), - const SizedBox(width: 4) - ], - ), - ), - const SizedBox(height: 12), - // Divider( - // height: 12, - // color: Theme.of(context).dividerColor.withOpacity(0.1), - // ), + )), ], ) : const SizedBox( diff --git a/lib/pages/video/detail/reply/widgets/zan.dart b/lib/pages/video/detail/reply/widgets/zan.dart index 8e630260a..bc08e8391 100644 --- a/lib/pages/video/detail/reply/widgets/zan.dart +++ b/lib/pages/video/detail/reply/widgets/zan.dart @@ -22,6 +22,7 @@ class ZanButton extends StatefulWidget { class _ZanButtonState extends State { // 评论点赞 onLikeReply() async { + SmartDialog.showLoading(msg: 'pilipala ...'); ReplyItemModel replyItem = widget.replyItem!; int oid = replyItem.oid!; int rpid = replyItem.rpid!; @@ -29,8 +30,9 @@ class _ZanButtonState extends State { int action = replyItem.action == 0 ? 1 : 0; var res = await ReplyHttp.likeReply( type: widget.replyType!.index, oid: oid, rpid: rpid, action: action); + SmartDialog.dismiss(); if (res['status']) { - SmartDialog.showToast(replyItem.action == 0 ? '点赞成功' : '取消赞'); + SmartDialog.showToast(replyItem.action == 0 ? '点赞成功 👍' : '取消赞 💔'); if (action == 1) { replyItem.like = replyItem.like! + 1; replyItem.action = 1; From 53490157762fbfee4409e7b8967a1d0f13ee9a4a Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 26 Jul 2023 15:31:42 +0800 Subject: [PATCH 2/3] feat: vibration --- lib/pages/dynamics/controller.dart | 2 + lib/pages/dynamics/view.dart | 47 +++++++++++-------- lib/pages/dynamics/widgets/action_panel.dart | 2 + lib/pages/dynamics/widgets/author_panel.dart | 9 +++- lib/pages/dynamics/widgets/up_panel.dart | 5 +- lib/pages/follow/widgets/follow_item.dart | 8 +++- lib/pages/home/view.dart | 5 +- lib/pages/main/view.dart | 2 + lib/pages/setting/controller.dart | 12 +++++ lib/pages/setting/view.dart | 26 ++++++++++ .../video/detail/introduction/controller.dart | 3 ++ lib/pages/video/detail/introduction/view.dart | 3 ++ .../introduction/widgets/action_row_item.dart | 6 ++- .../introduction/widgets/fav_panel.dart | 2 + .../detail/introduction/widgets/menu_row.dart | 6 ++- lib/pages/video/detail/reply/controller.dart | 2 + lib/pages/video/detail/reply/view.dart | 2 + .../detail/reply/widgets/reply_item.dart | 4 ++ lib/pages/video/detail/reply/widgets/zan.dart | 2 + lib/pages/video/detail/replyNew/view.dart | 2 + lib/utils/feed_back.dart | 12 +++++ lib/utils/storage.dart | 4 ++ 22 files changed, 139 insertions(+), 27 deletions(-) create mode 100644 lib/utils/feed_back.dart diff --git a/lib/pages/dynamics/controller.dart b/lib/pages/dynamics/controller.dart index 1d0af54b5..42647f3f0 100644 --- a/lib/pages/dynamics/controller.dart +++ b/lib/pages/dynamics/controller.dart @@ -9,6 +9,7 @@ import 'package:pilipala/models/common/dynamics_type.dart'; import 'package:pilipala/models/dynamics/result.dart'; import 'package:pilipala/models/dynamics/up.dart'; import 'package:pilipala/models/live/item.dart'; +import 'package:pilipala/utils/feed_back.dart'; class DynamicsController extends GetxController { int page = 1; @@ -78,6 +79,7 @@ class DynamicsController extends GetxController { } pushDetail(item, floor, {action = 'all'}) async { + feedBack(); if (action == 'comment') { Get.toNamed('/dynamicDetail', arguments: {'item': item, 'floor': floor, 'action': action}); diff --git a/lib/pages/dynamics/view.dart b/lib/pages/dynamics/view.dart index 9330679da..0577fa29c 100644 --- a/lib/pages/dynamics/view.dart +++ b/lib/pages/dynamics/view.dart @@ -8,6 +8,7 @@ import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/models/dynamics/result.dart'; import 'package:pilipala/pages/mine/index.dart'; +import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/storage.dart'; import 'controller.dart'; @@ -143,6 +144,7 @@ class _DynamicsPageState extends State duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, onValueChanged: (v) { + feedBack(); _dynamicsController.onSelectType(v); }, ), @@ -155,7 +157,8 @@ class _DynamicsPageState extends State bottom: 0, child: IconButton( padding: EdgeInsets.zero, - onPressed: () => _dynamicsController.resetSearch(), + onPressed: () => + {feedBack(), _dynamicsController.resetSearch()}, icon: const Icon(Icons.history, size: 21), ), ), @@ -167,15 +170,18 @@ class _DynamicsPageState extends State alignment: Alignment.center, child: user.get(UserBoxKey.userLogin) ?? false ? GestureDetector( - onTap: () => showModalBottomSheet( - context: context, - builder: (_) => const SizedBox( - height: 450, - child: MinePage(), - ), - clipBehavior: Clip.hardEdge, - isScrollControlled: true, - ), + onTap: () { + feedBack(); + showModalBottomSheet( + context: context, + builder: (_) => const SizedBox( + height: 450, + child: MinePage(), + ), + clipBehavior: Clip.hardEdge, + isScrollControlled: true, + ); + }, child: NetworkImgLayer( type: 'avatar', width: 30, @@ -184,15 +190,18 @@ class _DynamicsPageState extends State ), ) : IconButton( - onPressed: () => showModalBottomSheet( - context: context, - builder: (_) => const SizedBox( - height: 450, - child: MinePage(), - ), - clipBehavior: Clip.hardEdge, - isScrollControlled: true, - ), + onPressed: () { + feedBack(); + showModalBottomSheet( + context: context, + builder: (_) => const SizedBox( + height: 450, + child: MinePage(), + ), + clipBehavior: Clip.hardEdge, + isScrollControlled: true, + ); + }, icon: const Icon(CupertinoIcons.person, size: 22), ), ), diff --git a/lib/pages/dynamics/widgets/action_panel.dart b/lib/pages/dynamics/widgets/action_panel.dart index d601c0254..34b7f6afd 100644 --- a/lib/pages/dynamics/widgets/action_panel.dart +++ b/lib/pages/dynamics/widgets/action_panel.dart @@ -6,6 +6,7 @@ import 'package:get/get.dart'; import 'package:pilipala/http/dynamics.dart'; import 'package:pilipala/models/dynamics/result.dart'; import 'package:pilipala/pages/dynamics/index.dart'; +import 'package:pilipala/utils/feed_back.dart'; class ActionPanel extends StatefulWidget { const ActionPanel({ @@ -31,6 +32,7 @@ class _ActionPanelState extends State { // 动态点赞 onLikeDynamic() async { + feedBack(); var item = widget.item!; String dynamicId = item.idStr!; // 1 已点赞 2 不喜欢 0 未操作 diff --git a/lib/pages/dynamics/widgets/author_panel.dart b/lib/pages/dynamics/widgets/author_panel.dart index a1b67a92e..0e2e51dc8 100644 --- a/lib/pages/dynamics/widgets/author_panel.dart +++ b/lib/pages/dynamics/widgets/author_panel.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; +import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/utils.dart'; Widget author(item, context) { @@ -10,12 +11,16 @@ Widget author(item, context) { child: Row( children: [ GestureDetector( - onTap: () => Get.toNamed( + onTap: () { + feedBack(); + Get.toNamed( '/member?mid=${item.modules.moduleAuthor.mid}', arguments: { 'face': item.modules.moduleAuthor.face, 'heroTag': heroTag - }), + }, + ); + }, child: Hero( tag: heroTag, child: NetworkImgLayer( diff --git a/lib/pages/dynamics/widgets/up_panel.dart b/lib/pages/dynamics/widgets/up_panel.dart index f6147de3d..e1054ba0f 100644 --- a/lib/pages/dynamics/widgets/up_panel.dart +++ b/lib/pages/dynamics/widgets/up_panel.dart @@ -5,6 +5,7 @@ import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/models/dynamics/up.dart'; import 'package:pilipala/models/live/item.dart'; import 'package:pilipala/pages/dynamics/controller.dart'; +import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/utils.dart'; @@ -81,7 +82,7 @@ class _UpPanelState extends State { ), Material( child: InkWell( - onTap: () => Get.toNamed('/follow'), + onTap: () => {feedBack(), Get.toNamed('/follow')}, child: Container( height: 100, padding: const EdgeInsets.only(left: 10, right: 10), @@ -111,6 +112,7 @@ class _UpPanelState extends State { bool isCurrent = currentMid == data.mid || currentMid == -1; return InkWell( onTap: () { + feedBack(); if (data.type == 'up') { currentMid = data.mid; Get.find().mid.value = data.mid; @@ -149,6 +151,7 @@ class _UpPanelState extends State { } }, onLongPress: () { + feedBack(); String heroTag = Utils.makeHeroTag(data.mid); Get.toNamed('/member?mid=${data.mid}', arguments: {'face': data.face, 'heroTag': heroTag}); diff --git a/lib/pages/follow/widgets/follow_item.dart b/lib/pages/follow/widgets/follow_item.dart index 301b3e84b..e9ee6e2e6 100644 --- a/lib/pages/follow/widgets/follow_item.dart +++ b/lib/pages/follow/widgets/follow_item.dart @@ -1,13 +1,17 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; +import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/utils.dart'; Widget followItem({item}) { String heroTag = Utils.makeHeroTag(item!.mid); return ListTile( - onTap: () => Get.toNamed('/member?mid=${item.mid}', - arguments: {'face': item.face, 'heroTag': heroTag}), + onTap: () { + feedBack(); + Get.toNamed('/member?mid=${item.mid}', + arguments: {'face': item.face, 'heroTag': heroTag}); + }, leading: Hero( tag: heroTag, child: NetworkImgLayer( diff --git a/lib/pages/home/view.dart b/lib/pages/home/view.dart index 3a265c84d..8230246b2 100644 --- a/lib/pages/home/view.dart +++ b/lib/pages/home/view.dart @@ -4,6 +4,7 @@ import 'package:get/get.dart'; import 'package:pilipala/pages/hot/index.dart'; import 'package:pilipala/pages/live/index.dart'; import 'package:pilipala/pages/rcmd/index.dart'; +import 'package:pilipala/utils/feed_back.dart'; import './controller.dart'; class HomePage extends StatefulWidget { @@ -92,7 +93,8 @@ class _HomePageState extends State dividerColor: Colors.transparent, unselectedLabelColor: Theme.of(context).colorScheme.outline, - onTap: (value) => {_homeController.initialIndex = value}, + onTap: (value) => + {feedBack(), _homeController.initialIndex = value}, ), ), ), @@ -103,6 +105,7 @@ class _HomePageState extends State tag: 'searchTag', child: IconButton( onPressed: () { + feedBack(); Get.toNamed('/search'); }, icon: const Icon(CupertinoIcons.search, size: 21), diff --git a/lib/pages/main/view.dart b/lib/pages/main/view.dart index 2eab8f241..738232703 100644 --- a/lib/pages/main/view.dart +++ b/lib/pages/main/view.dart @@ -3,6 +3,7 @@ import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/pages/dynamics/index.dart'; import 'package:pilipala/pages/home/index.dart'; +import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/storage.dart'; import './controller.dart'; @@ -44,6 +45,7 @@ class _MainAppState extends State with SingleTickerProviderStateMixin { } void setIndex(int value) async { + feedBack(); if (selectedIndex != value) { selectedIndex = value; _animationController!.reverse().then((_) { diff --git a/lib/pages/setting/controller.dart b/lib/pages/setting/controller.dart index 47819593a..2a394587f 100644 --- a/lib/pages/setting/controller.dart +++ b/lib/pages/setting/controller.dart @@ -2,17 +2,22 @@ import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/http/init.dart'; import 'package:pilipala/pages/mine/controller.dart'; +import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/storage.dart'; class SettingController extends GetxController { Box user = GStrorage.user; RxBool userLogin = false.obs; Box userInfoCache = GStrorage.userInfo; + Box setting = GStrorage.setting; + RxBool feedBackEnable = false.obs; @override void onInit() { super.onInit(); userLogin.value = user.get(UserBoxKey.userLogin) ?? false; + feedBackEnable.value = + setting.get(SettingBoxKey.feedBackEnable, defaultValue: false); } loginOut() async { @@ -21,4 +26,11 @@ class SettingController extends GetxController { userLogin.value = user.get(UserBoxKey.userLogin) ?? false; userInfoCache.put('userInfoCache', null); } + + // 开启关闭震动反馈 + onOpenFeedBack() { + feedBack(); + feedBackEnable.value = !feedBackEnable.value; + setting.put(SettingBoxKey.feedBackEnable, feedBackEnable.value); + } } diff --git a/lib/pages/setting/view.dart b/lib/pages/setting/view.dart index a36b55273..155eec2a4 100644 --- a/lib/pages/setting/view.dart +++ b/lib/pages/setting/view.dart @@ -7,6 +7,10 @@ class SettingPage extends StatelessWidget { @override Widget build(BuildContext context) { + TextStyle subTitleStyle = Theme.of(context) + .textTheme + .labelMedium! + .copyWith(color: Theme.of(context).colorScheme.outline); final SettingController settingController = Get.put(SettingController()); return Scaffold( appBar: AppBar( @@ -14,6 +18,28 @@ class SettingPage extends StatelessWidget { ), body: Column( children: [ + Obx( + () => ListTile( + enableFeedback: true, + onTap: () => settingController.onOpenFeedBack(), + title: const Text('震动反馈'), + subtitle: Text('请确定手机设置中已开启震动反馈', style: subTitleStyle), + trailing: Transform.scale( + scale: 0.8, + child: Switch( + thumbIcon: MaterialStateProperty.resolveWith( + (Set states) { + if (states.isNotEmpty && + states.first == MaterialState.selected) { + return const Icon(Icons.done); + } + return null; // All other states will use the default thumbIcon. + }), + value: settingController.feedBackEnable.value, + onChanged: (value) => settingController.onOpenFeedBack()), + ), + ), + ), Obx( () => Visibility( visible: settingController.userLogin.value, diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index bb208b3bc..c6cb792b8 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -8,6 +8,7 @@ import 'package:pilipala/http/video.dart'; import 'package:pilipala/models/user/fav_folder.dart'; import 'package:pilipala/models/video_detail_res.dart'; import 'package:pilipala/pages/video/detail/controller.dart'; +import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/id_utils.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:share_plus/share_plus.dart'; @@ -303,6 +304,7 @@ class VideoIntroController extends GetxController { // 选择文件夹 onChoose(bool checkValue, int index) { + feedBack(); List datalist = favFolderData.value.list!; for (var i = 0; i < datalist.length; i++) { if (i == index) { @@ -327,6 +329,7 @@ class VideoIntroController extends GetxController { // 关注/取关up Future actionRelationMod() async { + feedBack(); if (user.get(UserBoxKey.userMid) == null) { SmartDialog.showToast('账号未登录'); return; diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 682bfda00..247cf114e 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -12,6 +12,7 @@ import 'package:pilipala/common/widgets/stat/danmu.dart'; import 'package:pilipala/common/widgets/stat/view.dart'; import 'package:pilipala/models/video_detail_res.dart'; import 'package:pilipala/pages/video/detail/introduction/controller.dart'; +import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/utils.dart'; @@ -125,6 +126,7 @@ class _VideoInfoState extends State with TickerProviderStateMixin { // 视频介绍 showIntroDetail() { + feedBack(); showBottomSheet( context: context, enableDrag: true, @@ -245,6 +247,7 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ], GestureDetector( onTap: () { + feedBack(); int mid = !widget.loadingStatus ? widget.videoDetail!.owner!.mid : videoItem['owner'].mid; diff --git a/lib/pages/video/detail/introduction/widgets/action_row_item.dart b/lib/pages/video/detail/introduction/widgets/action_row_item.dart index 254d7bcd4..5b940e0b4 100644 --- a/lib/pages/video/detail/introduction/widgets/action_row_item.dart +++ b/lib/pages/video/detail/introduction/widgets/action_row_item.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:pilipala/utils/feed_back.dart'; class ActionRowItem extends StatelessWidget { final Icon? icon; @@ -27,7 +28,10 @@ class ActionRowItem extends StatelessWidget { borderRadius: const BorderRadius.all(Radius.circular(30)), clipBehavior: Clip.hardEdge, child: InkWell( - onTap: () => onTap!(), + onTap: () => { + feedBack(), + onTap!(), + }, child: Padding( padding: const EdgeInsets.fromLTRB(13, 6.5, 15, 6.3), child: Row( diff --git a/lib/pages/video/detail/introduction/widgets/fav_panel.dart b/lib/pages/video/detail/introduction/widgets/fav_panel.dart index b640242df..44502b0e5 100644 --- a/lib/pages/video/detail/introduction/widgets/fav_panel.dart +++ b/lib/pages/video/detail/introduction/widgets/fav_panel.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/common/widgets/http_error.dart'; +import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/storage.dart'; class FavPanel extends StatefulWidget { @@ -43,6 +44,7 @@ class _FavPanelState extends State { actions: [ TextButton( onPressed: () async { + feedBack(); await widget.ctr!.actionFavVideo(); }, child: const Text('完成'), diff --git a/lib/pages/video/detail/introduction/widgets/menu_row.dart b/lib/pages/video/detail/introduction/widgets/menu_row.dart index 4a9aef358..7832d7bef 100644 --- a/lib/pages/video/detail/introduction/widgets/menu_row.dart +++ b/lib/pages/video/detail/introduction/widgets/menu_row.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:pilipala/utils/feed_back.dart'; class MenuRow extends StatelessWidget { final bool? loadingStatus; @@ -62,7 +63,10 @@ class MenuRow extends StatelessWidget { borderRadius: const BorderRadius.all(Radius.circular(30)), clipBehavior: Clip.hardEdge, child: InkWell( - onTap: () => onTap!(), + onTap: () => { + feedBack(), + onTap!(), + }, child: Container( padding: const EdgeInsets.fromLTRB(13, 5.5, 13, 5.5), decoration: BoxDecoration( diff --git a/lib/pages/video/detail/reply/controller.dart b/lib/pages/video/detail/reply/controller.dart index 76fb8be66..09a910fee 100644 --- a/lib/pages/video/detail/reply/controller.dart +++ b/lib/pages/video/detail/reply/controller.dart @@ -4,6 +4,7 @@ import 'package:pilipala/http/reply.dart'; import 'package:pilipala/models/common/reply_sort_type.dart'; import 'package:pilipala/models/common/reply_type.dart'; import 'package:pilipala/models/video/reply/item.dart'; +import 'package:pilipala/utils/feed_back.dart'; class VideoReplyController extends GetxController { VideoReplyController( @@ -83,6 +84,7 @@ class VideoReplyController extends GetxController { // 排序搜索评论 queryBySort() { + feedBack(); switch (sortType) { case ReplySortType.time: sortType = ReplySortType.like; diff --git a/lib/pages/video/detail/reply/view.dart b/lib/pages/video/detail/reply/view.dart index b25214739..80c6fedf1 100644 --- a/lib/pages/video/detail/reply/view.dart +++ b/lib/pages/video/detail/reply/view.dart @@ -8,6 +8,7 @@ import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/models/common/reply_type.dart'; import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/pages/video/detail/replyNew/index.dart'; +import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/id_utils.dart'; import 'controller.dart'; import 'widgets/reply_item.dart'; @@ -262,6 +263,7 @@ class _VideoReplyPanelState extends State child: FloatingActionButton( heroTag: null, onPressed: () { + feedBack(); showModalBottomSheet( context: context, isScrollControlled: true, diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index d32d296d5..23ca42088 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -7,6 +7,7 @@ import 'package:pilipala/models/common/reply_type.dart'; import 'package:pilipala/models/video/reply/item.dart'; import 'package:pilipala/pages/video/detail/controller.dart'; import 'package:pilipala/pages/video/detail/replyNew/index.dart'; +import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/utils.dart'; import 'zan.dart'; @@ -86,6 +87,7 @@ class ReplyItem extends StatelessWidget { // 头像、昵称 GestureDetector( onTap: () { + feedBack(); Get.toNamed('/member?mid=${replyItem!.mid}', arguments: { 'face': replyItem!.member!.avatar!, 'heroTag': heroTag @@ -259,6 +261,7 @@ class ReplyItem extends StatelessWidget { .labelMedium! .copyWith(color: Theme.of(context).colorScheme.outline)), onPressed: () { + feedBack(); showModalBottomSheet( context: context, isScrollControlled: true, @@ -348,6 +351,7 @@ class ReplyItemRow extends StatelessWidget { ), recognizer: TapGestureRecognizer() ..onTap = () { + feedBack(); String heroTag = Utils.makeHeroTag(replies![i].member.mid); Get.toNamed( diff --git a/lib/pages/video/detail/reply/widgets/zan.dart b/lib/pages/video/detail/reply/widgets/zan.dart index bc08e8391..da0c1378e 100644 --- a/lib/pages/video/detail/reply/widgets/zan.dart +++ b/lib/pages/video/detail/reply/widgets/zan.dart @@ -4,6 +4,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:pilipala/http/reply.dart'; import 'package:pilipala/models/common/reply_type.dart'; import 'package:pilipala/models/video/reply/item.dart'; +import 'package:pilipala/utils/feed_back.dart'; class ZanButton extends StatefulWidget { const ZanButton({ @@ -22,6 +23,7 @@ class ZanButton extends StatefulWidget { class _ZanButtonState extends State { // 评论点赞 onLikeReply() async { + feedBack(); SmartDialog.showLoading(msg: 'pilipala ...'); ReplyItemModel replyItem = widget.replyItem!; int oid = replyItem.oid!; diff --git a/lib/pages/video/detail/replyNew/view.dart b/lib/pages/video/detail/replyNew/view.dart index 451311108..122cc6525 100644 --- a/lib/pages/video/detail/replyNew/view.dart +++ b/lib/pages/video/detail/replyNew/view.dart @@ -6,6 +6,7 @@ import 'package:hive/hive.dart'; import 'package:pilipala/http/video.dart'; import 'package:pilipala/models/common/reply_type.dart'; import 'package:pilipala/models/video/reply/item.dart'; +import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/storage.dart'; class VideoReplyNewDialog extends StatefulWidget { @@ -68,6 +69,7 @@ class _VideoReplyNewDialogState extends State } Future submitReplyAdd() async { + feedBack(); String message = _replyContentController.text; var result = await VideoHttp.replyAdd( type: widget.replyType ?? ReplyType.video, diff --git a/lib/utils/feed_back.dart b/lib/utils/feed_back.dart new file mode 100644 index 000000000..cb3a693c9 --- /dev/null +++ b/lib/utils/feed_back.dart @@ -0,0 +1,12 @@ +import 'package:flutter/services.dart'; +import 'package:hive/hive.dart'; +import 'package:pilipala/utils/storage.dart'; + +Box setting = GStrorage.setting; +void feedBack() { + // 设置中是否开启 + bool enable = setting.get(SettingBoxKey.feedBackEnable, defaultValue: false); + if (enable) { + HapticFeedback.lightImpact(); + } +} diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index bfff55d61..36bd6bec6 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -13,6 +13,7 @@ class GStrorage { static late final Box hotKeyword; static late final Box historyword; static late final Box localCache; + static late final Box setting; static Future init() async { final dir = await getApplicationDocumentsDirectory(); @@ -27,6 +28,8 @@ class GStrorage { userInfo = await Hive.openBox('userInfo'); // 本地缓存 localCache = await Hive.openBox('localCache'); + // 设置 + setting = await Hive.openBox('setting'); } static regAdapter() { @@ -61,6 +64,7 @@ class UserBoxKey { class SettingBoxKey { static const String themeMode = 'themeMode'; + static const String feedBackEnable = 'feedBackEnable'; } class LocalCacheKey { From fdbf49452365694958b181e51c031e5c4f0c1da2 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 26 Jul 2023 15:47:00 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=E7=94=A8=E6=88=B7=E6=98=B5=E7=A7=B0?= =?UTF-8?q?=E6=BA=A2=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/widgets/custom_toast.dart | 3 ++- lib/pages/follow/widgets/follow_item.dart | 2 ++ lib/pages/member/view.dart | 7 +++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/common/widgets/custom_toast.dart b/lib/common/widgets/custom_toast.dart index 57b93c901..2c6d71d1e 100644 --- a/lib/common/widgets/custom_toast.dart +++ b/lib/common/widgets/custom_toast.dart @@ -7,7 +7,8 @@ class CustomToast extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - margin: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom), + margin: + EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom + 20), padding: const EdgeInsets.symmetric(horizontal: 17, vertical: 10), decoration: BoxDecoration( color: Theme.of(context).colorScheme.primaryContainer.withOpacity(0.8), diff --git a/lib/pages/follow/widgets/follow_item.dart b/lib/pages/follow/widgets/follow_item.dart index 301b3e84b..7cede9cda 100644 --- a/lib/pages/follow/widgets/follow_item.dart +++ b/lib/pages/follow/widgets/follow_item.dart @@ -19,6 +19,8 @@ Widget followItem({item}) { ), title: Text( item.uname, + maxLines: 1, + overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 14), ), subtitle: Text( diff --git a/lib/pages/member/view.dart b/lib/pages/member/view.dart index 75d5516f3..c22d7b73b 100644 --- a/lib/pages/member/view.dart +++ b/lib/pages/member/view.dart @@ -108,16 +108,19 @@ class _MemberPageState extends State const SizedBox(height: 14), Row( children: [ - Text( + Expanded( + child: Text( _memberController .memberInfo.value.name!, + maxLines: 1, + overflow: TextOverflow.ellipsis, style: Theme.of(context) .textTheme .bodyLarge! .copyWith( fontWeight: FontWeight.bold), - ), + )), const SizedBox(width: 2), if (_memberController .memberInfo.value.sex ==