feat: 评论+关注
This commit is contained in:
@ -10,11 +10,7 @@ import 'package:pilipala/models/video/reply/data.dart';
|
||||
import 'package:pilipala/models/video/reply/item.dart';
|
||||
|
||||
class VideoReplyController extends GetxController {
|
||||
VideoReplyController(
|
||||
this.aid,
|
||||
this.rpid,
|
||||
this.level
|
||||
);
|
||||
VideoReplyController(this.aid, this.rpid, this.level);
|
||||
final ScrollController scrollController = ScrollController();
|
||||
// 视频aid 请求时使用的oid
|
||||
String? aid;
|
||||
@ -26,7 +22,7 @@ class VideoReplyController extends GetxController {
|
||||
// 当前页
|
||||
int currentPage = 0;
|
||||
bool isLoadingMore = false;
|
||||
RxBool noMore = false.obs;
|
||||
RxString noMore = ''.obs;
|
||||
RxBool autoFocus = false.obs;
|
||||
// 当前回复的回复
|
||||
ReplyItemModel? currentReplyItem;
|
||||
@ -48,17 +44,18 @@ class VideoReplyController extends GetxController {
|
||||
res['data'] = ReplyData.fromJson(res['data']);
|
||||
if (res['data'].replies.isNotEmpty) {
|
||||
currentPage = currentPage + 1;
|
||||
noMore.value = false;
|
||||
noMore.value = '加载中';
|
||||
if(res['data'].page.count == res['data'].page.acount){
|
||||
noMore.value = '没有更多了';
|
||||
}
|
||||
} else {
|
||||
if (currentPage == 0) {
|
||||
noMore.value = '还没有评论';
|
||||
} else {
|
||||
noMore.value = true;
|
||||
noMore.value = '没有更多了';
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (res['data'].replies.length >= res['data'].page.count) {
|
||||
noMore.value = true;
|
||||
}
|
||||
if (type == 'init') {
|
||||
List<ReplyItemModel> replies = res['data'].replies;
|
||||
// 添加置顶回复
|
||||
@ -96,21 +93,26 @@ class VideoReplyController extends GetxController {
|
||||
|
||||
// 发表评论
|
||||
Future submitReplyAdd() async {
|
||||
print('replyLevel: $replyLevel');
|
||||
// print('rpid: $rpid');
|
||||
// print('currentReplyItem!.rpid: ${currentReplyItem!.rpid}');
|
||||
|
||||
|
||||
var result = await VideoHttp.replyAdd(
|
||||
type: ReplyType.video,
|
||||
oid: int.parse(aid!),
|
||||
root: replyLevel == '0' ? 0 : replyLevel == '1' ? currentReplyItem!.rpid : rPid,
|
||||
parent: replyLevel == '0' ? 0 : replyLevel == '1' ? currentReplyItem!.rpid : currentReplyItem!.rpid,
|
||||
message: replyLevel == '2' ? ' 回复 @${currentReplyItem!.member!.uname!} : 2楼31' : '2楼31',
|
||||
root: replyLevel == '0'
|
||||
? 0
|
||||
: replyLevel == '1'
|
||||
? currentReplyItem!.rpid
|
||||
: rPid,
|
||||
parent: replyLevel == '0'
|
||||
? 0
|
||||
: replyLevel == '1'
|
||||
? currentReplyItem!.rpid
|
||||
: currentReplyItem!.rpid,
|
||||
message: replyLevel == '2'
|
||||
? ' 回复 @${currentReplyItem!.member!.uname!} : 2楼31'
|
||||
: '2楼31',
|
||||
);
|
||||
if(result['status']){
|
||||
if (result['status']) {
|
||||
SmartDialog.showToast(result['data']['success_toast']);
|
||||
}else{
|
||||
} else {
|
||||
SmartDialog.showToast(result['message']);
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,10 @@ import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/common/skeleton/video_card_h.dart';
|
||||
import 'package:pilipala/common/skeleton/video_reply.dart';
|
||||
import 'package:pilipala/common/widgets/http_error.dart';
|
||||
import 'package:pilipala/models/video/reply/item.dart';
|
||||
import 'package:pilipala/pages/video/detail/replyNew/index.dart';
|
||||
import 'controller.dart';
|
||||
import 'widgets/reply_item.dart';
|
||||
|
||||
@ -14,6 +14,7 @@ class VideoReplyPanel extends StatefulWidget {
|
||||
int oid;
|
||||
int rpid;
|
||||
String? level;
|
||||
Key? key;
|
||||
VideoReplyPanel({
|
||||
this.oid = 0,
|
||||
this.rpid = 0,
|
||||
@ -29,7 +30,6 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
||||
with AutomaticKeepAliveClientMixin, TickerProviderStateMixin {
|
||||
late VideoReplyController _videoReplyController;
|
||||
late AnimationController fabAnimationCtr;
|
||||
late AnimationController replyAnimationCtl;
|
||||
|
||||
// List<ReplyItemModel>? replyList;
|
||||
Future? _futureBuilderFuture;
|
||||
@ -55,16 +55,9 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
||||
VideoReplyController(Get.parameters['aid']!, '', '1'),
|
||||
tag: Get.arguments['heroTag']);
|
||||
}
|
||||
// if(replyLevel != ''){
|
||||
// _videoReplyController.replyLevel = replyLevel;
|
||||
// }
|
||||
print(
|
||||
'_videoReplyController.replyLevel: ${_videoReplyController.replyLevel}');
|
||||
|
||||
fabAnimationCtr = AnimationController(
|
||||
vsync: this, duration: const Duration(milliseconds: 300));
|
||||
replyAnimationCtl = AnimationController(
|
||||
vsync: this, duration: const Duration(milliseconds: 500));
|
||||
|
||||
_futureBuilderFuture = _videoReplyController.queryReplyList();
|
||||
_videoReplyController.scrollController.addListener(
|
||||
@ -86,6 +79,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
||||
}
|
||||
},
|
||||
);
|
||||
fabAnimationCtr.forward();
|
||||
}
|
||||
|
||||
void _showFab() {
|
||||
@ -112,14 +106,12 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
||||
_videoReplyController.replyLevel = '0';
|
||||
}
|
||||
|
||||
replyAnimationCtl.forward();
|
||||
await Future.delayed(const Duration(microseconds: 100));
|
||||
_videoReplyController.wakeUpReply();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
fabAnimationCtr.dispose();
|
||||
_videoReplyController.scrollController.dispose();
|
||||
@ -164,9 +156,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
||||
60,
|
||||
child: Center(
|
||||
child: Obx(() => Text(
|
||||
_videoReplyController.noMore.value
|
||||
? '没有更多了'
|
||||
: '加载中')),
|
||||
_videoReplyController.noMore.value)),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
@ -211,9 +201,9 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
||||
right: 14,
|
||||
child: SlideTransition(
|
||||
position: Tween<Offset>(
|
||||
// begin: const Offset(0, 2),
|
||||
begin: const Offset(0, 2),
|
||||
// 评论内容为空/不足一屏
|
||||
begin: const Offset(0, 0),
|
||||
// begin: const Offset(0, 0),
|
||||
end: const Offset(0, 0),
|
||||
).animate(CurvedAnimation(
|
||||
parent: fabAnimationCtr,
|
||||
@ -221,57 +211,25 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
||||
)),
|
||||
child: FloatingActionButton(
|
||||
heroTag: null,
|
||||
onPressed: () => _showReply('main'),
|
||||
onPressed: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder: (builder) {
|
||||
return VideoReplyNewDialog(
|
||||
replyLevel: '0',
|
||||
oid: int.parse(Get.parameters['aid']!),
|
||||
root: 0,
|
||||
parent: 0,
|
||||
);
|
||||
},
|
||||
).then((value) => {print('close ModalBottomSheet')});
|
||||
},
|
||||
tooltip: '发表评论',
|
||||
child: const Icon(Icons.reply),
|
||||
),
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => Positioned(
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: SlideTransition(
|
||||
position: Tween<Offset>(
|
||||
begin: const Offset(0, 2),
|
||||
end: const Offset(0, 0),
|
||||
).animate(CurvedAnimation(
|
||||
parent: replyAnimationCtl,
|
||||
curve: Curves.easeInOut,
|
||||
)),
|
||||
child: Container(
|
||||
height: 100 + MediaQuery.of(context).padding.bottom,
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.of(context).padding.bottom),
|
||||
color: Theme.of(context).colorScheme.surfaceVariant,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 14, right: 14),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Visibility(
|
||||
visible: _videoReplyController.autoFocus.value,
|
||||
child: const TextField(
|
||||
autofocus: true,
|
||||
maxLines: null,
|
||||
decoration: InputDecoration(
|
||||
hintText: "友善评论", border: InputBorder.none),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () =>
|
||||
_videoReplyController.submitReplyAdd(),
|
||||
child: const Text('发送'),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -4,7 +4,9 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||
import 'package:pilipala/models/video/reply/item.dart';
|
||||
import 'package:pilipala/pages/video/detail/controller.dart';
|
||||
import 'package:pilipala/pages/video/detail/reply/index.dart';
|
||||
import 'package:pilipala/pages/video/detail/replyNew/index.dart';
|
||||
import 'package:pilipala/utils/utils.dart';
|
||||
|
||||
class ReplyItem extends StatelessWidget {
|
||||
@ -176,13 +178,14 @@ class ReplyItem extends StatelessWidget {
|
||||
// 操作区域
|
||||
bottonAction(context, replyItem!.replyControl),
|
||||
const SizedBox(height: 3),
|
||||
if (replyItem!.replies!.isNotEmpty) ...[
|
||||
if (replyItem!.replies!.isNotEmpty && replyLevel != '2') ...[
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 2, bottom: 12),
|
||||
child: ReplyItemRow(
|
||||
replies: replyItem!.replies,
|
||||
replyControl: replyItem!.replyControl,
|
||||
f_rpid: replyItem!.rpid,
|
||||
replyItem: replyItem,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -225,17 +228,32 @@ class ReplyItem extends StatelessWidget {
|
||||
if (replyItem!.upAction!.like!)
|
||||
Icon(Icons.favorite, color: Colors.red[400], size: 18),
|
||||
SizedBox(
|
||||
height: 28,
|
||||
width: 42,
|
||||
child: TextButton(
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
child: Text('回复', style: Theme.of(context)
|
||||
.textTheme
|
||||
.labelMedium),
|
||||
onPressed: () => weakUpReply!(replyItem, replyLevel),
|
||||
)),
|
||||
height: 28,
|
||||
width: 42,
|
||||
child: TextButton(
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
child: Text('回复', style: Theme.of(context).textTheme.labelMedium),
|
||||
onPressed: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder: (builder) {
|
||||
print('🌹: ${replyItem!.rpid}');
|
||||
return VideoReplyNewDialog(
|
||||
replyLevel: replyLevel,
|
||||
oid: replyItem!.oid,
|
||||
root: replyItem!.rpid,
|
||||
parent: replyItem!.rpid,
|
||||
);
|
||||
},
|
||||
).then((value) => {
|
||||
print('showModalBottomSheet')
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 32,
|
||||
child: TextButton(
|
||||
@ -272,10 +290,12 @@ class ReplyItemRow extends StatelessWidget {
|
||||
this.replies,
|
||||
this.replyControl,
|
||||
this.f_rpid,
|
||||
this.replyItem
|
||||
});
|
||||
List? replies;
|
||||
ReplyControl? replyControl;
|
||||
int? f_rpid;
|
||||
ReplyItemModel? replyItem;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -297,7 +317,7 @@ class ReplyItemRow extends StatelessWidget {
|
||||
if (extraRow == 1 && index == replies!.length) {
|
||||
// 有楼中楼回复,在最后显示
|
||||
return InkWell(
|
||||
onTap: () => replyReply(context),
|
||||
onTap: () => replyReply(replyItem),
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 8, horizontal: 8),
|
||||
@ -323,7 +343,7 @@ class ReplyItemRow extends StatelessWidget {
|
||||
);
|
||||
} else {
|
||||
return InkWell(
|
||||
onTap: () {},
|
||||
onTap: () => replyReply(replyItem),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
8,
|
||||
@ -338,10 +358,6 @@ class ReplyItemRow extends StatelessWidget {
|
||||
: TextOverflow.visible,
|
||||
maxLines: extraRow == 1 ? 2 : null,
|
||||
TextSpan(
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
replyReply(context);
|
||||
},
|
||||
children: [
|
||||
TextSpan(
|
||||
text: replies![index].member.uname + ' ',
|
||||
@ -374,46 +390,15 @@ class ReplyItemRow extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
void replyReply(context) {
|
||||
Get.bottomSheet(
|
||||
barrierColor: Colors.transparent,
|
||||
useRootNavigator: true,
|
||||
isScrollControlled: true,
|
||||
Container(
|
||||
height: Get.size.height - Get.size.width * 9 / 16 - 45,
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
child: Column(
|
||||
children: [
|
||||
AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
centerTitle: false,
|
||||
elevation: 1,
|
||||
title: Text(
|
||||
'评论详情',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () async {
|
||||
Get.back();
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: VideoReplyPanel(
|
||||
oid: replies!.first.oid,
|
||||
rpid: f_rpid!,
|
||||
level: '2',
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
persistent: false,
|
||||
backgroundColor: Theme.of(context).bottomSheetTheme.backgroundColor,
|
||||
);
|
||||
void replyReply(replyItem) {
|
||||
// replyItem 楼主评论
|
||||
Get.find<VideoDetailController>(tag: Get.arguments['heroTag'])
|
||||
.oid
|
||||
.value = replies!.first.oid;
|
||||
Get.find<VideoDetailController>(tag: Get.arguments['heroTag'])
|
||||
.fRpid
|
||||
.value = f_rpid!;
|
||||
Get.find<VideoDetailController>(tag: Get.arguments['heroTag']).firstFloor = replyItem;
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,11 +408,10 @@ InlineSpan buildContent(BuildContext context, content) {
|
||||
content.jumpUrl.isEmpty &&
|
||||
content.vote.isEmpty &&
|
||||
content.pictures.isEmpty) {
|
||||
return TextSpan(text: content.message,
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = ()=> {
|
||||
print('点击')
|
||||
},);
|
||||
return TextSpan(
|
||||
text: content.message,
|
||||
// recognizer: TapGestureRecognizer()..onTap = () => {print('点击')},
|
||||
);
|
||||
}
|
||||
List<InlineSpan> spanChilds = [];
|
||||
// 匹配表情
|
||||
@ -505,10 +489,10 @@ InlineSpan buildContent(BuildContext context, content) {
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => {
|
||||
print('Url 点击'),
|
||||
},
|
||||
// recognizer: TapGestureRecognizer()
|
||||
// ..onTap = () => {
|
||||
// print('Url 点击'),
|
||||
// },
|
||||
),
|
||||
);
|
||||
spanChilds.add(
|
||||
@ -540,10 +524,10 @@ InlineSpan buildContent(BuildContext context, content) {
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => {
|
||||
print('time 点击'),
|
||||
},
|
||||
// recognizer: TapGestureRecognizer()
|
||||
// ..onTap = () => {
|
||||
// print('time 点击'),
|
||||
// },
|
||||
),
|
||||
);
|
||||
return '';
|
||||
|
Reference in New Issue
Block a user