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 bd12ed0c..bc665e33 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart @@ -47,58 +47,56 @@ class ReplyItemGrpc extends StatelessWidget { @override Widget build(BuildContext context) { - return Material( - child: InkWell( - // 点击整个评论区 评论详情/回复 - onTap: () { - feedBack(); - if (replyReply != null) { - replyReply!(replyItem, null); - } - }, - onLongPress: () { - feedBack(); - // showDialog( - // context: Get.context!, - // builder: (_) => AlertDialog( - // content: SelectableText( - // jsonEncode(replyItem.replyControl.toProto3Json())), - // ), - // ); - showModalBottomSheet( - context: context, - useRootNavigator: true, - isScrollControlled: true, - builder: (context) { - return MorePanel( - item: replyItem, - onDelete: (rpid) { - if (onDelete != null) { - onDelete!(rpid, null); - } - }, - ); - }, - ); - }, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.fromLTRB(12, 14, 8, 5), - child: content(context), - ), - if (needDivider) - Divider( - indent: 55, - endIndent: 15, - height: 0.3, - color: Theme.of(context) - .colorScheme - .onInverseSurface - .withOpacity(0.5), - ) - ], - ), + return InkWell( + // 点击整个评论区 评论详情/回复 + onTap: () { + feedBack(); + if (replyReply != null) { + replyReply!(replyItem, null); + } + }, + onLongPress: () { + feedBack(); + // showDialog( + // context: Get.context!, + // builder: (_) => AlertDialog( + // content: SelectableText( + // jsonEncode(replyItem.replyControl.toProto3Json())), + // ), + // ); + showModalBottomSheet( + context: context, + useRootNavigator: true, + isScrollControlled: true, + builder: (context) { + return MorePanel( + item: replyItem, + onDelete: (rpid) { + if (onDelete != null) { + onDelete!(rpid, null); + } + }, + ); + }, + ); + }, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(12, 14, 8, 5), + child: content(context), + ), + if (needDivider) + Divider( + indent: 55, + endIndent: 15, + height: 0.3, + color: Theme.of(context) + .colorScheme + .onInverseSurface + .withOpacity(0.5), + ) + ], ), ); } diff --git a/lib/pages/video/detail/reply_reply/controller.dart b/lib/pages/video/detail/reply_reply/controller.dart index 0a705aaf..e2e9aeae 100644 --- a/lib/pages/video/detail/reply_reply/controller.dart +++ b/lib/pages/video/detail/reply_reply/controller.dart @@ -1,12 +1,14 @@ import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart'; import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/pages/common/common_controller.dart'; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:PiliPalaX/http/reply.dart'; import 'package:PiliPalaX/models/common/reply_type.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; -class VideoReplyReplyController extends CommonController { +class VideoReplyReplyController extends CommonController + with GetTickerProviderStateMixin { VideoReplyReplyController( this.hasRoot, this.id, @@ -32,6 +34,10 @@ class VideoReplyReplyController extends CommonController { RxInt count = (-1).obs; int? upMid; + int? index; + AnimationController? controller; + Animation? colorAnimation; + @override void onInit() { super.onInit(); @@ -92,17 +98,29 @@ class VideoReplyReplyController extends CommonController { if (cursor == null) { count.value = replies.root.count.toInt(); if (id != null) { - int index = replies.root.replies + index = replies.root.replies .map((item) => item.id.toInt()) .toList() .indexOf(id); if (index != -1) { + controller = AnimationController( + duration: const Duration(milliseconds: 300), + vsync: this, + ); + colorAnimation = ColorTween( + begin: Theme.of(Get.context!).colorScheme.onInverseSurface, + end: Theme.of(Get.context!).colorScheme.surface, + ).animate(controller!); () async { await Future.delayed(const Duration(milliseconds: 200)); - itemScrollCtr.scrollTo( - index: hasRoot ? index + 3 : index + 1, + await itemScrollCtr.scrollTo( + index: hasRoot ? index! + 3 : index! + 1, duration: const Duration(milliseconds: 200), ); + await Future.delayed(const Duration(milliseconds: 800)); + controller?.forward().whenComplete(() { + index = null; + }); }(); } id = null; diff --git a/lib/pages/video/detail/reply_reply/view.dart b/lib/pages/video/detail/reply_reply/view.dart index bb7fc1c7..ef1980fd 100644 --- a/lib/pages/video/detail/reply_reply/view.dart +++ b/lib/pages/video/detail/reply_reply/view.dart @@ -57,6 +57,7 @@ class _VideoReplyReplyPanelState extends State { @override void dispose() { + _videoReplyReplyController.controller?.dispose(); Get.delete(tag: widget.rpid.toString()); super.dispose(); } @@ -256,24 +257,18 @@ class _VideoReplyReplyPanelState extends State { ), ); } else { - return ReplyItemGrpc( - replyItem: loadingState.response[index], - replyLevel: '2', - showReplyRow: false, - replyType: widget.replyType, - onReply: () { - _onReply(loadingState.response[index]); - }, - onDelete: (rpid, frpid) { - List list = - (_videoReplyReplyController.loadingState.value as Success) - .response; - list = list.where((item) => item.id != rpid).toList(); - _videoReplyReplyController.loadingState.value = - LoadingState.success(list); - }, - upMid: _videoReplyReplyController.upMid, - ); + return _videoReplyReplyController.index == index + ? AnimatedBuilder( + animation: _videoReplyReplyController.colorAnimation!, + builder: (context, child) { + return ColoredBox( + color: _videoReplyReplyController.colorAnimation?.value ?? + Theme.of(Get.context!).colorScheme.onInverseSurface, + child: _replyItem(loadingState.response[index]), + ); + }, + ) + : _replyItem(loadingState.response[index]); } } else if (loadingState is Error) { return CustomScrollView( @@ -304,6 +299,26 @@ class _VideoReplyReplyPanelState extends State { } } + Widget _replyItem(replyItem) { + return ReplyItemGrpc( + replyItem: replyItem, + replyLevel: '2', + showReplyRow: false, + replyType: widget.replyType, + onReply: () { + _onReply(replyItem); + }, + onDelete: (rpid, frpid) { + List list = + (_videoReplyReplyController.loadingState.value as Success).response; + list = list.where((item) => item.id != rpid).toList(); + _videoReplyReplyController.loadingState.value = + LoadingState.success(list); + }, + upMid: _videoReplyReplyController.upMid, + ); + } + int _itemCount(LoadingState loadingState) { int itemCount = 0; if (widget.firstFloor != null) {