opt: reply page

This commit is contained in:
bggRGjQaUbCoE
2024-09-06 11:36:03 +08:00
parent c37f6835f8
commit 6029d409e7
3 changed files with 171 additions and 122 deletions

View File

@@ -37,6 +37,8 @@ class VideoReplyController extends GetxController {
Box setting = GStorage.setting; Box setting = GStorage.setting;
Future? futureBuilderFuture;
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
@@ -98,6 +100,7 @@ class VideoReplyController extends GetxController {
replyList.addAll(replies); replyList.addAll(replies);
} }
} }
return res;
} }
// 上拉加载 // 上拉加载

View File

@@ -1,3 +1,4 @@
import 'package:PiliPalaX/common/widgets/http_error.dart';
import 'package:PiliPalaX/pages/video/detail/reply_new/reply_page.dart'; import 'package:PiliPalaX/pages/video/detail/reply_new/reply_page.dart';
import 'package:easy_debounce/easy_throttle.dart'; import 'package:easy_debounce/easy_throttle.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -180,130 +181,174 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
), ),
), ),
), ),
Obx( FutureBuilder(
() => _videoReplyController.isLoadingMore && future: _videoReplyController.futureBuilderFuture,
_videoReplyController.replyList.isEmpty && builder: (BuildContext context, snapshot) {
(_videoReplyController.noMore.value == '' || if (snapshot.connectionState == ConnectionState.done) {
_videoReplyController.noMore.value == '加载中...') var data = snapshot.data;
? SliverList( if (data['status']) {
delegate: SliverChildBuilderDelegate( // 请求成功
(BuildContext context, index) { return Obx(
return const VideoReplySkeleton(); () => _videoReplyController.isLoadingMore &&
}, childCount: 5), _videoReplyController.replyList.isEmpty
) ? SliverList(
: SliverList( delegate: SliverChildBuilderDelegate(
delegate: SliverChildBuilderDelegate( (BuildContext context, index) {
(BuildContext context, index) { return const VideoReplySkeleton();
double bottom = }, childCount: 5),
MediaQuery.of(context).padding.bottom; )
if (index == : SliverList(
_videoReplyController.replyList.length) { delegate: SliverChildBuilderDelegate(
return Container( (BuildContext context, index) {
padding: EdgeInsets.only(bottom: bottom), double bottom =
height: bottom + 100, MediaQuery.of(context).padding.bottom;
child: Center( if (index ==
child: Obx( _videoReplyController
() => Text( .replyList.length) {
_videoReplyController.noMore.value, return Container(
style: TextStyle( padding:
fontSize: 12, EdgeInsets.only(bottom: bottom),
color: Theme.of(context) height: bottom + 100,
.colorScheme child: Center(
.outline, child: Obx(
), () => Text(
), _videoReplyController
), .noMore.value,
), style: TextStyle(
); fontSize: 12,
} else { color: Theme.of(context)
return ReplyItem( .colorScheme
replyItem: .outline,
_videoReplyController.replyList[index], ),
showReplyRow: true, ),
replyLevel: replyLevel, ),
replyReply: (replyItem) => ),
replyReply(replyItem), );
replyType: ReplyType.video, } else {
onReply: () { return ReplyItem(
dynamic oid = _videoReplyController replyItem: _videoReplyController
.replyList[index].oid; .replyList[index],
dynamic root = _videoReplyController showReplyRow: true,
.replyList[index].rpid; replyLevel: replyLevel,
dynamic parent = _videoReplyController replyReply: (replyItem) =>
.replyList[index].rpid; replyReply(replyItem),
dynamic key = oid + root + parent; replyType: ReplyType.video,
Navigator.of(context) onReply: () {
.push( dynamic oid = _videoReplyController
GetDialogRoute( .replyList[index].oid;
pageBuilder: (buildContext, animation, dynamic root = _videoReplyController
secondaryAnimation) { .replyList[index].rpid;
return ReplyPage( dynamic parent = _videoReplyController
oid: oid, .replyList[index].rpid;
root: root, dynamic key = oid + root + parent;
parent: parent, Navigator.of(context)
replyType: ReplyType.video, .push(
replyItem: _videoReplyController GetDialogRoute(
.replyList[index], pageBuilder: (buildContext,
savedReply: _savedReplies[key], animation,
onSaveReply: (reply) { secondaryAnimation) {
_savedReplies[key] = reply; return ReplyPage(
}, oid: oid,
); root: root,
}, parent: parent,
transitionDuration: replyType: ReplyType.video,
const Duration(milliseconds: 500), replyItem:
transitionBuilder: (context, animation, _videoReplyController
secondaryAnimation, child) { .replyList[index],
const begin = Offset(0.0, 1.0); savedReply:
const end = Offset.zero; _savedReplies[key],
const curve = Curves.linear; onSaveReply: (reply) {
_savedReplies[key] = reply;
},
);
},
transitionDuration:
const Duration(
milliseconds: 500),
transitionBuilder: (context,
animation,
secondaryAnimation,
child) {
const begin = Offset(0.0, 1.0);
const end = Offset.zero;
const curve = Curves.linear;
var tween = Tween( var tween = Tween(
begin: begin, end: end) begin: begin, end: end)
.chain(CurveTween(curve: curve)); .chain(CurveTween(
curve: curve));
return SlideTransition( return SlideTransition(
position: animation.drive(tween), position:
child: child, animation.drive(tween),
); child: child,
}, );
), },
) ),
.then((value) { )
// 完成评论,数据添加 .then((value) {
if (value != null && // 完成评论,数据添加
value['data'] != null) { if (value != null &&
_savedReplies[key] = null; value['data'] != null) {
_savedReplies[key] = null;
}
});
},
onDelete: (rpid, frpid) {
_videoReplyController.replyList.value =
frpid == null
? _videoReplyController
.replyList
.where((item) =>
item.rpid != rpid)
.toList()
: _videoReplyController
.replyList
.map((item) {
if (item.rpid == frpid) {
return item
..replies = item
.replies
?.where((reply) =>
reply.rpid !=
rpid)
.toList();
} else {
return item;
}
}).toList();
},
);
} }
}); },
}, childCount:
onDelete: (rpid, frpid) { _videoReplyController.replyList.length +
frpid == null 1,
? _videoReplyController.replyList.value = ),
_videoReplyController.replyList ),
.where( );
(item) => item.rpid != rpid) } else {
.toList() // 请求错误
: _videoReplyController.replyList return HttpError(
.map((item) { errMsg: data['msg'],
if (item.rpid == frpid) { fn: () {
return item setState(() {
..replies = item.replies _videoReplyController.futureBuilderFuture =
?.where((reply) => _videoReplyController.queryReplyList();
reply.rpid != rpid) });
.toList(); },
} else { );
return item; }
} } else {
}).toList(); // 骨架屏
}, return SliverList(
); delegate: SliverChildBuilderDelegate(
} (BuildContext context, index) {
}, return const VideoReplySkeleton();
childCount: }, childCount: 5),
_videoReplyController.replyList.length + 1, );
), }
), },
), ),
], ],
), ),

View File

@@ -148,7 +148,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
// 获取视频资源,初始化播放器 // 获取视频资源,初始化播放器
Future<void> videoSourceInit() async { Future<void> videoSourceInit() async {
_futureBuilderFuture = videoDetailController.queryVideoUrl(); _futureBuilderFuture = videoDetailController.queryVideoUrl();
_videoReplyController.queryReplyList(type: 'init'); _videoReplyController.futureBuilderFuture =
_videoReplyController.queryReplyList(type: 'init');
if (videoDetailController.autoPlay.value) { if (videoDetailController.autoPlay.value) {
plPlayerController = videoDetailController.plPlayerController; plPlayerController = videoDetailController.plPlayerController;
plPlayerController!.addStatusLister(playerListener); plPlayerController!.addStatusLister(playerListener);