diff --git a/lib/pages/search/view.dart b/lib/pages/search/view.dart index ea902365..c78dfea9 100644 --- a/lib/pages/search/view.dart +++ b/lib/pages/search/view.dart @@ -160,26 +160,25 @@ class _SearchPageState extends State with RouteAware { } Widget _searchSuggest() { + SSearchController _ssCtr = _searchController; return Obx( - () => _searchController.searchSuggestList.isNotEmpty && - _searchController.searchSuggestList.first.term != null + () => _ssCtr.searchSuggestList.isNotEmpty && + _ssCtr.searchSuggestList.first.term != null && + _ssCtr.controller.value.text != '' ? ListView.builder( physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, - itemCount: _searchController.searchSuggestList.length, + itemCount: _ssCtr.searchSuggestList.length, itemBuilder: (context, index) { return InkWell( customBorder: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4), ), - onTap: () => _searchController.onClickKeyword( - _searchController.searchSuggestList[index].term!), + onTap: () => _ssCtr + .onClickKeyword(_ssCtr.searchSuggestList[index].term!), child: Padding( padding: const EdgeInsets.only(left: 20, top: 9, bottom: 9), - // child: Text( - // _searchController.searchSuggestList[index].term!, - // ), - child: _searchController.searchSuggestList[index].textRich, + child: _ssCtr.searchSuggestList[index].textRich, ), ); }, diff --git a/lib/pages/setting/extra_setting.dart b/lib/pages/setting/extra_setting.dart index bb262b57..f9d30f41 100644 --- a/lib/pages/setting/extra_setting.dart +++ b/lib/pages/setting/extra_setting.dart @@ -61,6 +61,12 @@ class _ExtraSettingState extends State { setKey: SettingBoxKey.enableQuickFav, defaultVal: false, ), + const SetSwitchItem( + title: '评论区搜索关键词', + subTitle: '展示评论区搜索关键词', + setKey: SettingBoxKey.enableWordRe, + defaultVal: false, + ), ListTile( dense: false, title: Text('评论展示', style: titleStyle), diff --git a/lib/pages/video/detail/reply/controller.dart b/lib/pages/video/detail/reply/controller.dart index 16c7838f..207eb856 100644 --- a/lib/pages/video/detail/reply/controller.dart +++ b/lib/pages/video/detail/reply/controller.dart @@ -69,7 +69,7 @@ class VideoReplyController extends GetxController { noMore.value = '加载中...'; /// 第一页回复数小于20 - if (currentPage == 0 && replies.length < 20) { + if (currentPage == 0 && replies.length < 18) { noMore.value = '没有更多了'; } currentPage++; diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 8b47dde6..df51b118 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -2,6 +2,7 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; +import 'package:hive/hive.dart'; import 'package:pilipala/common/widgets/badge.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/models/common/reply_type.dart'; @@ -9,10 +10,13 @@ import 'package:pilipala/models/video/reply/item.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/storage.dart'; import 'package:pilipala/utils/utils.dart'; import 'zan.dart'; +Box setting = GStrorage.setting; + class ReplyItem extends StatelessWidget { const ReplyItem({ this.replyItem, @@ -41,63 +45,73 @@ class ReplyItem extends StatelessWidget { replyReply!(replyItem); } }, - child: Padding( - padding: const EdgeInsets.fromLTRB(12, 4, 8, 2), - child: content(context), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(12, 14, 8, 5), + child: content(context), + ), + Divider( + indent: 55, + endIndent: 15, + height: 0.3, + color: Theme.of(context) + .colorScheme + .onInverseSurface + .withOpacity(0.5), + ) + ], ), ), ); } Widget lfAvtar(context, heroTag) { - return Container( - margin: const EdgeInsets.only(top: 5), - child: Stack( - children: [ - Hero( - tag: heroTag, - child: NetworkImgLayer( - src: replyItem!.member!.avatar, - width: 34, - height: 34, - type: 'avatar', + return Stack( + children: [ + Hero( + tag: heroTag, + child: NetworkImgLayer( + src: replyItem!.member!.avatar, + width: 34, + height: 34, + type: 'avatar', + ), + ), + if (replyItem!.member!.officialVerify != null && + replyItem!.member!.officialVerify!['type'] == 0) + Positioned( + right: 0, + bottom: 0, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(7), + color: Theme.of(context).colorScheme.background, + ), + child: Icon( + Icons.offline_bolt, + color: Theme.of(context).colorScheme.primary, + size: 16, + ), ), ), - if (replyItem!.member!.officialVerify != null && - replyItem!.member!.officialVerify!['type'] == 0) - Positioned( - right: 0, - bottom: 0, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(7), - color: Theme.of(context).colorScheme.background, - ), - child: Icon( - Icons.offline_bolt, - color: Theme.of(context).colorScheme.primary, - size: 16, - ), + if (replyItem!.member!.vip!['vipStatus'] > 0 && + replyItem!.member!.vip!['vipType'] == 2) + Positioned( + right: 0, + bottom: 0, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(7), + color: Theme.of(context).colorScheme.background, + ), + child: Image.asset( + 'assets/images/big-vip.png', + height: 14, ), ), - if (replyItem!.member!.vip!['vipStatus'] > 0 && - replyItem!.member!.vip!['vipType'] == 2) - Positioned( - right: 0, - bottom: 0, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(7), - color: Theme.of(context).colorScheme.background, - ), - child: Image.asset( - 'assets/images/big-vip.png', - height: 14, - ), - ), - ), - ], - ), + ), + ], ); } @@ -107,7 +121,100 @@ class ReplyItem extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ // 头像、昵称 + // SizedBox( + // width: double.infinity, + // child: Stack( + // children: [ + // GestureDetector( + // behavior: HitTestBehavior.opaque, + // onTap: () { + // feedBack(); + // Get.toNamed('/member?mid=${replyItem!.mid}', arguments: { + // 'face': replyItem!.member!.avatar!, + // 'heroTag': heroTag + // }); + // }, + // child: Row( + // crossAxisAlignment: CrossAxisAlignment.center, + // mainAxisSize: MainAxisSize.min, + // children: [ + // lfAvtar(context, heroTag), + // const SizedBox(width: 12), + // Text( + // replyItem!.member!.uname!, + // style: TextStyle( + // color: replyItem!.member!.vip!['vipStatus'] > 0 + // ? const Color.fromARGB(255, 251, 100, 163) + // : Theme.of(context).colorScheme.outline, + // fontSize: 13, + // ), + // ), + // const SizedBox(width: 6), + // Image.asset( + // 'assets/images/lv/lv${replyItem!.member!.level}.png', + // height: 11, + // ), + // const SizedBox(width: 6), + // if (replyItem!.isUp!) + // const PBadge( + // text: 'UP', + // size: 'small', + // stack: 'normal', + // fs: 9, + // ), + // ], + // ), + // ), + // Positioned( + // top: 0, + // left: 0, + // right: 0, + // child: Container( + // width: double.infinity, + // height: 45, + // decoration: BoxDecoration( + // image: replyItem!.member!.userSailing!.cardbg != null + // ? DecorationImage( + // alignment: Alignment.centerRight, + // fit: BoxFit.fitHeight, + // image: NetworkImage( + // replyItem!.member!.userSailing!.cardbg!['image'], + // ), + // ) + // : null, + // ), + // ), + // ), + // if (replyItem!.member!.userSailing!.cardbg != null && + // replyItem!.member!.userSailing!.cardbg!['fan']['number'] > 0) + // Positioned( + // top: 10, + // left: Get.size.width / 7 * 5.8, + // child: DefaultTextStyle( + // style: TextStyle( + // fontFamily: 'fansCard', + // fontSize: 9, + // color: Theme.of(context).colorScheme.primary, + // ), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // const Text('NO.'), + // Text( + // replyItem!.member!.userSailing!.cardbg!['fan'] + // ['num_desc'], + // ), + // ], + // ), + // ), + // ), + // ], + // ), + // ), + /// fix Stack内GestureDetector onTap无效 GestureDetector( + behavior: HitTestBehavior.opaque, onTap: () { feedBack(); Get.toNamed('/member?mid=${replyItem!.mid}', arguments: { @@ -115,93 +222,72 @@ class ReplyItem extends StatelessWidget { 'heroTag': heroTag }); }, - child: SizedBox( - width: double.infinity, - child: Stack( - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - lfAvtar(context, heroTag), - const SizedBox(width: 12), - Text( - replyItem!.member!.uname!, - style: TextStyle( - color: replyItem!.member!.vip!['vipStatus'] > 0 - ? const Color.fromARGB(255, 251, 100, 163) - : Theme.of(context).colorScheme.outline, - fontSize: 13, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + lfAvtar(context, heroTag), + const SizedBox(width: 12), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + replyItem!.member!.uname!, + style: TextStyle( + color: replyItem!.member!.vip!['vipStatus'] > 0 + ? const Color.fromARGB(255, 251, 100, 163) + : Theme.of(context).colorScheme.outline, + fontSize: 13, + ), ), - ), - const SizedBox(width: 6), - Image.asset( - 'assets/images/lv/lv${replyItem!.member!.level}.png', - height: 11, - ), - const SizedBox(width: 6), - if (replyItem!.isUp!) - const PBadge( - text: 'UP', - size: 'small', - stack: 'normal', - fs: 9, + const SizedBox(width: 6), + Image.asset( + 'assets/images/lv/lv${replyItem!.member!.level}.png', + height: 11, ), - ], - ), - Positioned( - top: 0, - left: 0, - right: 0, - child: Container( - width: double.infinity, - height: 45, - decoration: BoxDecoration( - image: replyItem!.member!.userSailing!.cardbg != null - ? DecorationImage( - alignment: Alignment.centerRight, - fit: BoxFit.fitHeight, - image: NetworkImage( - replyItem! - .member!.userSailing!.cardbg!['image'], - ), - ) - : null, - ), + const SizedBox(width: 6), + if (replyItem!.isUp!) + const PBadge( + text: 'UP', + size: 'small', + stack: 'normal', + fs: 9, + ), + ], ), - ), - if (replyItem!.member!.userSailing!.cardbg != null && - replyItem!.member!.userSailing!.cardbg!['fan']['number'] > - 0) - Positioned( - top: 10, - left: Get.size.width / 7 * 5.8, - child: DefaultTextStyle( - style: TextStyle( - fontFamily: 'fansCard', - fontSize: 9, - color: Theme.of(context).colorScheme.primary, + Row( + children: [ + Text( + Utils.dateFormat(replyItem!.ctime), + style: TextStyle( + fontSize: + Theme.of(context).textTheme.labelSmall!.fontSize, + color: Theme.of(context).colorScheme.outline, + ), ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text('NO.'), - Text( - replyItem!.member!.userSailing!.cardbg!['fan'] - ['num_desc'], - ), - ], - ), - ), - ), - ], - ), + if (replyItem!.replyControl != null && + replyItem!.replyControl!.location != '') + Text( + ' • ${replyItem!.replyControl!.location!}', + style: TextStyle( + fontSize: Theme.of(context) + .textTheme + .labelSmall! + .fontSize, + color: Theme.of(context).colorScheme.outline), + ), + ], + ) + ], + ), + ], ), ), // title Container( - margin: const EdgeInsets.only(top: 0, left: 45, right: 6, bottom: 6), + margin: const EdgeInsets.only(top: 10, left: 45, right: 6, bottom: 4), child: SelectableRegion( magnifierConfiguration: const TextMagnifierConfiguration(), focusNode: FocusNode(), @@ -255,52 +341,10 @@ class ReplyItem extends StatelessWidget { Widget bottonAction(context, replyControl) { return Row( children: [ - const SizedBox(width: 48), - if (replyItem!.cardLabel!.isNotEmpty && - replyItem!.cardLabel!.contains('热评')) - Text( - '热评 • ', - style: Theme.of(context) - .textTheme - .labelMedium! - .copyWith(color: Theme.of(context).colorScheme.primary), - ), - Text( - Utils.dateFormat(replyItem!.ctime), - style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, - ), - ), - if (replyItem!.replyControl != null && - replyItem!.replyControl!.location != '') - Text( - ' • ${replyItem!.replyControl!.location!}', - style: Theme.of(context) - .textTheme - .labelMedium! - .copyWith(color: Theme.of(context).colorScheme.outline), - ), - const Spacer(), - if (replyItem!.upAction!.like!) - Icon(Icons.favorite, color: Colors.red[400], size: 18), + const SizedBox(width: 32), SizedBox( - height: 28, - width: 28, - child: IconButton( - style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), - ), - icon: Icon( - Icons.reply_outlined, - size: 18, - color: Theme.of(context).colorScheme.outline, - ), - // child: Text('回复', - // style: Theme.of(context) - // .textTheme - // .labelMedium! - // .copyWith(color: Theme.of(context).colorScheme.outline)), + height: 32, + child: TextButton( onPressed: () { feedBack(); showModalBottomSheet( @@ -324,8 +368,41 @@ class ReplyItem extends StatelessWidget { } }); }, + child: Row(children: [ + Icon(Icons.reply, + size: 18, + color: + Theme.of(context).colorScheme.outline.withOpacity(0.8)), + const SizedBox(width: 3), + Text( + '回复', + style: TextStyle( + fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, + color: Theme.of(context).colorScheme.outline, + ), + ), + ]), ), ), + const SizedBox(width: 2), + if (replyItem!.upAction!.like!) ...[ + Text( + 'up主觉得很赞', + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + fontSize: Theme.of(context).textTheme.labelMedium!.fontSize), + ), + const SizedBox(width: 2), + ], + if (replyItem!.cardLabel!.isNotEmpty && + replyItem!.cardLabel!.contains('热评')) + Text( + '热评', + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + fontSize: Theme.of(context).textTheme.labelMedium!.fontSize), + ), + const Spacer(), ZanButton(replyItem: replyItem, replyType: replyType), const SizedBox(width: 5) ], @@ -595,16 +672,20 @@ InlineSpan buildContent( RegExp(RegExp.escape(urlKeys.join("|"))), onMatch: (Match match) { String matchStr = match[0]!; + String appUrlSchema = content.jumpUrl[matchStr]['app_url_schema']; + // 默认不显示关键词 + bool enableWordRe = + setting.get(SettingBoxKey.enableWordRe, defaultValue: false); spanChilds.add( TextSpan( text: content.jumpUrl[matchStr]['title'], style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: enableWordRe + ? Theme.of(context).colorScheme.primary + : null, ), recognizer: TapGestureRecognizer() ..onTap = () { - String appUrlSchema = - content.jumpUrl[matchStr]['app_url_schema']; if (appUrlSchema == '') { Get.toNamed( '/webview', @@ -615,7 +696,8 @@ InlineSpan buildContent( }, ); } else { - if (appUrlSchema.startsWith('bilibili://search')) { + if (appUrlSchema.startsWith('bilibili://search') && + enableWordRe) { Get.toNamed('/searchResult', parameters: { 'keyword': content.jumpUrl[matchStr]['title'] }); @@ -624,16 +706,18 @@ InlineSpan buildContent( }, ), ); - spanChilds.add( - WidgetSpan( - child: Icon( - FontAwesomeIcons.magnifyingGlass, - size: 9, - color: Theme.of(context).colorScheme.primary, + if (appUrlSchema.startsWith('bilibili://search') && enableWordRe) { + spanChilds.add( + WidgetSpan( + child: Icon( + FontAwesomeIcons.magnifyingGlass, + size: 9, + color: Theme.of(context).colorScheme.primary, + ), + alignment: PlaceholderAlignment.top, ), - alignment: PlaceholderAlignment.top, - ), - ); + ); + } return ''; }, onNonMatch: (String str) { @@ -647,7 +731,7 @@ InlineSpan buildContent( ); } str = matchUrl.splitMapJoin( - RegExp(r"\d{1,2}:\d{1,2}"), + RegExp(r'\b\d{2}:\d{2}\b'), onMatch: (Match match) { String matchStr = match[0]!; spanChilds.add( diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index de7ffd04..3355ddfa 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -111,6 +111,7 @@ class SettingBoxKey { static const String defaultDynamicType = 'defaultDynamicType'; static const String enableHotKey = 'enableHotKey'; static const String enableQuickFav = 'enableQuickFav'; + static const String enableWordRe = 'enableWordRe'; /// 外观 static const String themeMode = 'themeMode';