mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt: save unsent replies
This commit is contained in:
@@ -37,6 +37,8 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
|||||||
late VideoReplyController _videoReplyController;
|
late VideoReplyController _videoReplyController;
|
||||||
late AnimationController fabAnimationCtr;
|
late AnimationController fabAnimationCtr;
|
||||||
|
|
||||||
|
late final _savedReplies = {};
|
||||||
|
|
||||||
bool _isFabVisible = true;
|
bool _isFabVisible = true;
|
||||||
String replyLevel = '1';
|
String replyLevel = '1';
|
||||||
late String heroTag;
|
late String heroTag;
|
||||||
@@ -218,6 +220,59 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
|||||||
replyReply: (replyItem) =>
|
replyReply: (replyItem) =>
|
||||||
replyReply(replyItem),
|
replyReply(replyItem),
|
||||||
replyType: ReplyType.video,
|
replyType: ReplyType.video,
|
||||||
|
onReply: () {
|
||||||
|
dynamic oid = _videoReplyController
|
||||||
|
.replyList[index].oid;
|
||||||
|
dynamic root = _videoReplyController
|
||||||
|
.replyList[index].rpid;
|
||||||
|
dynamic parent = _videoReplyController
|
||||||
|
.replyList[index].rpid;
|
||||||
|
dynamic key = oid + root + parent;
|
||||||
|
Navigator.of(context)
|
||||||
|
.push(
|
||||||
|
GetDialogRoute(
|
||||||
|
pageBuilder: (buildContext, animation,
|
||||||
|
secondaryAnimation) {
|
||||||
|
return ReplyPage(
|
||||||
|
oid: oid,
|
||||||
|
root: root,
|
||||||
|
parent: parent,
|
||||||
|
replyType: ReplyType.video,
|
||||||
|
replyItem: _videoReplyController
|
||||||
|
.replyList[index],
|
||||||
|
savedReply: _savedReplies[key],
|
||||||
|
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(
|
||||||
|
begin: begin, end: end)
|
||||||
|
.chain(CurveTween(curve: curve));
|
||||||
|
|
||||||
|
return SlideTransition(
|
||||||
|
position: animation.drive(tween),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.then((value) {
|
||||||
|
// 完成评论,数据添加
|
||||||
|
if (value != null &&
|
||||||
|
value['data'] != null) {
|
||||||
|
_savedReplies[key] = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -243,46 +298,51 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
|||||||
heroTag: null,
|
heroTag: null,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
feedBack();
|
feedBack();
|
||||||
|
dynamic oid = _videoReplyController.aid ??
|
||||||
|
IdUtils.bv2av(Get.parameters['bvid']!);
|
||||||
Navigator.of(context)
|
Navigator.of(context)
|
||||||
.push(
|
.push(
|
||||||
GetDialogRoute(
|
GetDialogRoute(
|
||||||
pageBuilder:
|
pageBuilder:
|
||||||
(buildContext, animation, secondaryAnimation) {
|
(buildContext, animation, secondaryAnimation) {
|
||||||
return ReplyPage(
|
return ReplyPage(
|
||||||
oid: _videoReplyController.aid ??
|
oid: oid,
|
||||||
IdUtils.bv2av(Get.parameters['bvid']!),
|
root: 0,
|
||||||
root: 0,
|
parent: 0,
|
||||||
parent: 0,
|
replyType: ReplyType.video,
|
||||||
replyType: ReplyType.video,
|
savedReply: _savedReplies[oid],
|
||||||
);
|
onSaveReply: (reply) {
|
||||||
|
_savedReplies[oid] = reply;
|
||||||
},
|
},
|
||||||
transitionDuration: const Duration(milliseconds: 500),
|
);
|
||||||
transitionBuilder:
|
},
|
||||||
(context, animation, secondaryAnimation, child) {
|
transitionDuration: const Duration(milliseconds: 500),
|
||||||
const begin = Offset(0.0, 1.0);
|
transitionBuilder:
|
||||||
const end = Offset.zero;
|
(context, animation, secondaryAnimation, child) {
|
||||||
const curve = Curves.linear;
|
const begin = Offset(0.0, 1.0);
|
||||||
|
const end = Offset.zero;
|
||||||
|
const curve = Curves.linear;
|
||||||
|
|
||||||
var tween = Tween(begin: begin, end: end)
|
var tween = Tween(begin: begin, end: end)
|
||||||
.chain(CurveTween(curve: curve));
|
.chain(CurveTween(curve: curve));
|
||||||
|
|
||||||
return SlideTransition(
|
return SlideTransition(
|
||||||
position: animation.drive(tween),
|
position: animation.drive(tween),
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.then(
|
.then(
|
||||||
(value) => {
|
(value) {
|
||||||
// 完成评论,数据添加
|
// 完成评论,数据添加
|
||||||
if (value != null && value['data'] != null)
|
if (value != null && value['data'] != null) {
|
||||||
{
|
_savedReplies[oid] = null;
|
||||||
_videoReplyController.replyList
|
_videoReplyController.replyList
|
||||||
.insert(0, value['data'])
|
.insert(0, value['data']);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// showModalBottomSheet(
|
// showModalBottomSheet(
|
||||||
// context: context,
|
// context: context,
|
||||||
// isScrollControlled: true,
|
// isScrollControlled: true,
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ class ReplyItem extends StatelessWidget {
|
|||||||
this.replyReply,
|
this.replyReply,
|
||||||
this.replyType,
|
this.replyType,
|
||||||
this.needDivider = true,
|
this.needDivider = true,
|
||||||
|
this.onReply,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
final ReplyItemModel? replyItem;
|
final ReplyItemModel? replyItem;
|
||||||
@@ -40,6 +41,7 @@ class ReplyItem extends StatelessWidget {
|
|||||||
final Function? replyReply;
|
final Function? replyReply;
|
||||||
final ReplyType? replyType;
|
final ReplyType? replyType;
|
||||||
final bool needDivider;
|
final bool needDivider;
|
||||||
|
final Function()? onReply;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -303,6 +305,10 @@ class ReplyItem extends StatelessWidget {
|
|||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
feedBack();
|
feedBack();
|
||||||
|
if (onReply != null) {
|
||||||
|
onReply!();
|
||||||
|
return;
|
||||||
|
}
|
||||||
Navigator.of(context)
|
Navigator.of(context)
|
||||||
.push(
|
.push(
|
||||||
GetDialogRoute(
|
GetDialogRoute(
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ class ReplyPage extends StatefulWidget {
|
|||||||
final int? parent;
|
final int? parent;
|
||||||
final ReplyType? replyType;
|
final ReplyType? replyType;
|
||||||
final ReplyItemModel? replyItem;
|
final ReplyItemModel? replyItem;
|
||||||
|
final String? savedReply;
|
||||||
|
final Function(String reply)? onSaveReply;
|
||||||
|
|
||||||
const ReplyPage({
|
const ReplyPage({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -31,6 +33,8 @@ class ReplyPage extends StatefulWidget {
|
|||||||
this.parent,
|
this.parent,
|
||||||
this.replyType,
|
this.replyType,
|
||||||
this.replyItem,
|
this.replyItem,
|
||||||
|
this.savedReply,
|
||||||
|
this.onSaveReply,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -41,7 +45,8 @@ class _ReplyPageState extends State<ReplyPage>
|
|||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin {
|
||||||
late final _focusNode = FocusNode();
|
late final _focusNode = FocusNode();
|
||||||
late final _controller = ChatBottomPanelContainerController<PanelType>();
|
late final _controller = ChatBottomPanelContainerController<PanelType>();
|
||||||
final TextEditingController _replyContentController = TextEditingController();
|
late final TextEditingController _replyContentController =
|
||||||
|
TextEditingController(text: widget.savedReply);
|
||||||
PanelType _currentPanelType = PanelType.none;
|
PanelType _currentPanelType = PanelType.none;
|
||||||
bool _readOnly = false;
|
bool _readOnly = false;
|
||||||
final _readOnlyStream = StreamController<bool>();
|
final _readOnlyStream = StreamController<bool>();
|
||||||
@@ -54,6 +59,11 @@ class _ReplyPageState extends State<ReplyPage>
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
if (widget.savedReply != null && widget.savedReply!.isNotEmpty) {
|
||||||
|
_enablePublish = true;
|
||||||
|
}
|
||||||
|
|
||||||
() async {
|
() async {
|
||||||
await Future.delayed(const Duration(milliseconds: 300));
|
await Future.delayed(const Duration(milliseconds: 300));
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
@@ -194,6 +204,9 @@ class _ReplyPageState extends State<ReplyPage>
|
|||||||
_enablePublish = false;
|
_enablePublish = false;
|
||||||
_publishStream.add(false);
|
_publishStream.add(false);
|
||||||
}
|
}
|
||||||
|
if (widget.onSaveReply != null) {
|
||||||
|
widget.onSaveReply!(value);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
focusNode: _focusNode,
|
focusNode: _focusNode,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
@@ -255,7 +268,7 @@ class _ReplyPageState extends State<ReplyPage>
|
|||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
StreamBuilder(
|
StreamBuilder(
|
||||||
initialData: false,
|
initialData: _enablePublish,
|
||||||
stream: _publishStream.stream,
|
stream: _publishStream.stream,
|
||||||
builder: (_, snapshot) => FilledButton.tonal(
|
builder: (_, snapshot) => FilledButton.tonal(
|
||||||
onPressed: snapshot.data == true ? submitReplyAdd : null,
|
onPressed: snapshot.data == true ? submitReplyAdd : null,
|
||||||
|
|||||||
Reference in New Issue
Block a user