mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
feat: at user
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -6,15 +6,12 @@ import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart'
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/pages/common/common_slide_page.dart';
|
||||
import 'package:PiliPlus/pages/video/reply/widgets/reply_item_grpc.dart';
|
||||
import 'package:PiliPlus/pages/video/reply_new/view.dart';
|
||||
import 'package:PiliPlus/pages/video/reply_reply/controller.dart';
|
||||
import 'package:PiliPlus/utils/num_util.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:PiliPlus/utils/request_utils.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_navigation/src/dialog/dialog_route.dart';
|
||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||
|
||||
class VideoReplyReplyPanel extends CommonSlidePage {
|
||||
@@ -51,27 +48,25 @@ class VideoReplyReplyPanel extends CommonSlidePage {
|
||||
|
||||
class _VideoReplyReplyPanelState
|
||||
extends CommonSlidePageState<VideoReplyReplyPanel> {
|
||||
late VideoReplyReplyController _videoReplyReplyController;
|
||||
late final _savedReplies = <int, String>{};
|
||||
late VideoReplyReplyController _controller;
|
||||
late final itemPositionsListener = ItemPositionsListener.create();
|
||||
late final _key = GlobalKey<ScaffoldState>();
|
||||
late final _listKey = GlobalKey();
|
||||
late final _tag =
|
||||
Utils.makeHeroTag('${widget.rpid}${widget.dialog}${widget.isDialogue}');
|
||||
|
||||
ReplyInfo? get firstFloor =>
|
||||
widget.firstFloor ?? _videoReplyReplyController.firstFloor;
|
||||
ReplyInfo? get firstFloor => widget.firstFloor ?? _controller.firstFloor;
|
||||
|
||||
bool get _horizontalPreview =>
|
||||
context.orientation == Orientation.landscape &&
|
||||
_videoReplyReplyController.horizontalPreview;
|
||||
_controller.horizontalPreview;
|
||||
|
||||
Animation<Color?>? colorAnimation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_videoReplyReplyController = Get.put(
|
||||
_controller = Get.put(
|
||||
VideoReplyReplyController(
|
||||
hasRoot: widget.firstFloor != null,
|
||||
id: widget.id,
|
||||
@@ -159,7 +154,7 @@ class _VideoReplyReplyPanelState
|
||||
Widget buildList(ThemeData theme) {
|
||||
return ClipRect(
|
||||
child: refreshIndicator(
|
||||
onRefresh: _videoReplyReplyController.onRefresh,
|
||||
onRefresh: _controller.onRefresh,
|
||||
child: Obx(
|
||||
() => Stack(
|
||||
clipBehavior: Clip.none,
|
||||
@@ -167,27 +162,27 @@ class _VideoReplyReplyPanelState
|
||||
ScrollablePositionedList.builder(
|
||||
key: _listKey,
|
||||
itemPositionsListener: itemPositionsListener,
|
||||
itemCount:
|
||||
_itemCount(_videoReplyReplyController.loadingState.value),
|
||||
itemScrollController: _videoReplyReplyController.itemScrollCtr,
|
||||
itemCount: _itemCount(_controller.loadingState.value),
|
||||
itemScrollController: _controller.itemScrollCtr,
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
if (widget.isDialogue) {
|
||||
return _buildBody(theme,
|
||||
_videoReplyReplyController.loadingState.value, index);
|
||||
return _buildBody(
|
||||
theme, _controller.loadingState.value, index);
|
||||
} else if (firstFloor != null) {
|
||||
if (index == 0) {
|
||||
return ReplyItemGrpc(
|
||||
replyItem: firstFloor!,
|
||||
replyLevel: 2,
|
||||
needDivider: false,
|
||||
onReply: (replyItem) => _onReply(replyItem, -1),
|
||||
upMid: _videoReplyReplyController.upMid,
|
||||
onReply: (replyItem) => _controller.onReply(context,
|
||||
replyItem: replyItem, index: -1),
|
||||
upMid: _controller.upMid,
|
||||
onViewImage: widget.onViewImage,
|
||||
onDismissed: widget.onDismissed,
|
||||
callback: _getImageCallback,
|
||||
onCheckReply: (item) => _videoReplyReplyController
|
||||
.onCheckReply(context, item, isManual: true),
|
||||
onCheckReply: (item) =>
|
||||
_controller.onCheckReply(item, isManual: true),
|
||||
);
|
||||
} else if (index == 1) {
|
||||
return Divider(
|
||||
@@ -200,7 +195,7 @@ class _VideoReplyReplyPanelState
|
||||
} else {
|
||||
return _buildBody(
|
||||
theme,
|
||||
_videoReplyReplyController.loadingState.value,
|
||||
_controller.loadingState.value,
|
||||
index - 3,
|
||||
);
|
||||
}
|
||||
@@ -210,7 +205,7 @@ class _VideoReplyReplyPanelState
|
||||
} else {
|
||||
return _buildBody(
|
||||
theme,
|
||||
_videoReplyReplyController.loadingState.value,
|
||||
_controller.loadingState.value,
|
||||
index - 1,
|
||||
);
|
||||
}
|
||||
@@ -218,7 +213,7 @@ class _VideoReplyReplyPanelState
|
||||
},
|
||||
),
|
||||
if (!widget.isDialogue &&
|
||||
_videoReplyReplyController.loadingState.value.isSuccess)
|
||||
_controller.loadingState.value.isSuccess)
|
||||
_header(theme),
|
||||
],
|
||||
),
|
||||
@@ -243,9 +238,9 @@ class _VideoReplyReplyPanelState
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Obx(
|
||||
() => _videoReplyReplyController.count.value != -1
|
||||
() => _controller.count.value != -1
|
||||
? Text(
|
||||
'相关回复共${NumUtil.numFormat(_videoReplyReplyController.count.value)}条',
|
||||
'相关回复共${NumUtil.numFormat(_controller.count.value)}条',
|
||||
style: const TextStyle(fontSize: 13),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
@@ -253,7 +248,7 @@ class _VideoReplyReplyPanelState
|
||||
SizedBox(
|
||||
height: 35,
|
||||
child: TextButton.icon(
|
||||
onPressed: () => _videoReplyReplyController.queryBySort(),
|
||||
onPressed: () => _controller.queryBySort(),
|
||||
icon: Icon(
|
||||
Icons.sort,
|
||||
size: 16,
|
||||
@@ -261,7 +256,7 @@ class _VideoReplyReplyPanelState
|
||||
),
|
||||
label: Obx(
|
||||
() => Text(
|
||||
_videoReplyReplyController.mode.value == Mode.MAIN_LIST_HOT
|
||||
_controller.mode.value == Mode.MAIN_LIST_HOT
|
||||
? '按热度'
|
||||
: '按时间',
|
||||
style: TextStyle(
|
||||
@@ -306,59 +301,6 @@ class _VideoReplyReplyPanelState
|
||||
}
|
||||
: null;
|
||||
|
||||
void _onReply(ReplyInfo item, int index) {
|
||||
final oid = item.oid.toInt();
|
||||
final root = item.id.toInt();
|
||||
final key = oid + root;
|
||||
|
||||
Navigator.of(context)
|
||||
.push(
|
||||
GetDialogRoute(
|
||||
pageBuilder: (buildContext, animation, secondaryAnimation) {
|
||||
return ReplyPage(
|
||||
oid: oid,
|
||||
root: root,
|
||||
parent: root,
|
||||
replyType: widget.replyType,
|
||||
replyItem: item,
|
||||
initialValue: _savedReplies[key],
|
||||
onSave: (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(begin: begin, end: end).chain(CurveTween(curve: curve));
|
||||
|
||||
return SlideTransition(
|
||||
position: animation.drive(tween),
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
.then((res) {
|
||||
if (res != null) {
|
||||
_savedReplies.remove(key);
|
||||
ReplyInfo replyInfo = RequestUtils.replyCast(res);
|
||||
_videoReplyReplyController
|
||||
..count.value += 1
|
||||
..loadingState.value.dataOrNull?.insert(index + 1, replyInfo)
|
||||
..loadingState.refresh();
|
||||
if (_videoReplyReplyController.enableCommAntifraud && mounted) {
|
||||
_videoReplyReplyController.onCheckReply(context, replyInfo,
|
||||
isManual: false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildBody(
|
||||
ThemeData theme, LoadingState<List<ReplyInfo>?> loadingState, int index) {
|
||||
return switch (loadingState) {
|
||||
@@ -375,14 +317,14 @@ class _VideoReplyReplyPanelState
|
||||
Success(:var response) => Builder(
|
||||
builder: (context) {
|
||||
if (index == response!.length) {
|
||||
_videoReplyReplyController.onLoadMore();
|
||||
_controller.onLoadMore();
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
margin: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom),
|
||||
height: 125,
|
||||
child: Text(
|
||||
_videoReplyReplyController.isEnd ? '没有更多了' : '加载中...',
|
||||
_controller.isEnd ? '没有更多了' : '加载中...',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: theme.colorScheme.outline,
|
||||
@@ -390,12 +332,11 @@ class _VideoReplyReplyPanelState
|
||||
),
|
||||
);
|
||||
} else {
|
||||
if (_videoReplyReplyController.index != null &&
|
||||
_videoReplyReplyController.index == index) {
|
||||
if (_controller.index != null && _controller.index == index) {
|
||||
colorAnimation ??= ColorTween(
|
||||
begin: theme.colorScheme.onInverseSurface,
|
||||
end: theme.colorScheme.surface,
|
||||
).animate(_videoReplyReplyController.controller!);
|
||||
).animate(_controller.controller!);
|
||||
return AnimatedBuilder(
|
||||
animation: colorAnimation!,
|
||||
builder: (context, child) {
|
||||
@@ -413,7 +354,7 @@ class _VideoReplyReplyPanelState
|
||||
),
|
||||
Error(:var errMsg) => errorWidget(
|
||||
errMsg: errMsg,
|
||||
onReload: _videoReplyReplyController.onReload,
|
||||
onReload: _controller.onReload,
|
||||
),
|
||||
};
|
||||
}
|
||||
@@ -422,11 +363,12 @@ class _VideoReplyReplyPanelState
|
||||
return ReplyItemGrpc(
|
||||
replyItem: replyItem,
|
||||
replyLevel: widget.isDialogue ? 3 : 2,
|
||||
onReply: (replyItem) => _onReply(replyItem, index),
|
||||
onReply: (replyItem) =>
|
||||
_controller.onReply(context, replyItem: replyItem, index: index),
|
||||
onDelete: (item, subIndex) {
|
||||
_videoReplyReplyController.onRemove(index, item, null);
|
||||
_controller.onRemove(index, item, null);
|
||||
},
|
||||
upMid: _videoReplyReplyController.upMid,
|
||||
upMid: _controller.upMid,
|
||||
showDialogue: () => _key.currentState?.showBottomSheet(
|
||||
backgroundColor: Colors.transparent,
|
||||
(context) => VideoReplyReplyPanel(
|
||||
@@ -441,8 +383,7 @@ class _VideoReplyReplyPanelState
|
||||
onViewImage: widget.onViewImage,
|
||||
onDismissed: widget.onDismissed,
|
||||
callback: _getImageCallback,
|
||||
onCheckReply: (item) => _videoReplyReplyController
|
||||
.onCheckReply(context, item, isManual: true),
|
||||
onCheckReply: (item) => _controller.onCheckReply(item, isManual: true),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user