opt: grpc reply item

This commit is contained in:
bggRGjQaUbCoE
2024-10-11 23:05:48 +08:00
parent a762334772
commit 60e80ba160
8 changed files with 392 additions and 403 deletions

View File

@@ -1,3 +1,4 @@
import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart';
import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/http/loading_state.dart';
import 'package:PiliPalaX/models/common/reply_type.dart'; import 'package:PiliPalaX/models/common/reply_type.dart';
import 'package:PiliPalaX/pages/common/common_controller.dart'; import 'package:PiliPalaX/pages/common/common_controller.dart';
@@ -124,15 +125,15 @@ abstract class ReplyController extends CommonController {
dynamic replyItem, dynamic replyItem,
int index = 0, int index = 0,
}) { }) {
dynamic key = oid ?? replyItem.oid + replyItem.rpid; dynamic key = oid ?? replyItem.oid + replyItem.id;
Navigator.of(context) Navigator.of(context)
.push( .push(
GetDialogRoute( GetDialogRoute(
pageBuilder: (buildContext, animation, secondaryAnimation) { pageBuilder: (buildContext, animation, secondaryAnimation) {
return ReplyPage( return ReplyPage(
oid: oid ?? replyItem.oid, oid: oid ?? replyItem.oid.toInt(),
root: oid != null ? 0 : replyItem.rpid, root: oid != null ? 0 : replyItem.id.toInt(),
parent: oid != null ? 0 : replyItem.rpid, parent: oid != null ? 0 : replyItem.id.toInt(),
replyType: ReplyType.video, replyType: ReplyType.video,
replyItem: replyItem, replyItem: replyItem,
savedReply: savedReplies[key], savedReply: savedReplies[key],
@@ -159,35 +160,37 @@ abstract class ReplyController extends CommonController {
) )
.then( .then(
(value) { (value) {
if (value != null && value['data'] != null) { // TODO: data cast
if (value != null && value['data'] is ReplyInfo) {
savedReplies[key] = null; savedReplies[key] = null;
List list = loadingState.value is Success MainListReply response =
? (loadingState.value as Success).response (loadingState.value as Success?)?.response ?? MainListReply();
: [];
if (oid != null) { if (oid != null) {
list.insert(0, value['data']); response.replies.insert(0, value['data']);
} else { } else {
list[index].replies.add(value['data']); response.replies[index].replies.add(value['data']);
} }
loadingState.value = LoadingState.success(list); loadingState.value = LoadingState.success(response);
} }
}, },
); );
} }
onMDelete(rpid, frpid) { onMDelete(rpid, frpid) {
List list = (loadingState.value as Success).response; MainListReply response = (loadingState.value as Success).response;
list = frpid == null if (frpid == null) {
? list.where((item) => item.rpid != rpid).toList() response.replies.removeWhere((item) {
: list.map((item) { return item.id.toInt() == rpid;
if (item.rpid == frpid) { });
return item } else {
..replies = response.replies.map((item) {
item.replies?.where((reply) => reply.rpid != rpid).toList(); if (item.id == frpid) {
} else { return item..replies.removeWhere((reply) => reply.id.toInt() == rpid);
return item; } else {
} return item;
}).toList(); }
loadingState.value = LoadingState.success(list); }).toList();
}
loadingState.value = LoadingState.success(response);
} }
} }

View File

@@ -1,18 +1,11 @@
import 'dart:convert';
import 'dart:ffi';
import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart'; import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart';
import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/http/loading_state.dart';
import 'package:PiliPalaX/models/common/reply_sort_type.dart'; import 'package:PiliPalaX/models/common/reply_sort_type.dart';
import 'package:PiliPalaX/pages/common/reply_controller.dart'; import 'package:PiliPalaX/pages/common/reply_controller.dart';
import 'package:PiliPalaX/http/reply.dart'; import 'package:PiliPalaX/http/reply.dart';
import 'package:PiliPalaX/models/common/reply_type.dart';
import 'package:PiliPalaX/utils/feed_back.dart'; import 'package:PiliPalaX/utils/feed_back.dart';
import 'package:easy_debounce/easy_throttle.dart'; import 'package:easy_debounce/easy_throttle.dart';
import 'package:fixnum/fixnum.dart' as $fixnum; import 'package:fixnum/fixnum.dart' as $fixnum;
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
class VideoReplyController extends ReplyController { class VideoReplyController extends ReplyController {
VideoReplyController( VideoReplyController(

View File

@@ -10,7 +10,6 @@ import 'package:PiliPalaX/models/common/reply_type.dart';
import 'package:PiliPalaX/utils/feed_back.dart'; import 'package:PiliPalaX/utils/feed_back.dart';
import 'package:PiliPalaX/utils/id_utils.dart'; import 'package:PiliPalaX/utils/id_utils.dart';
import 'controller.dart'; import 'controller.dart';
import 'widgets/reply_item.dart';
class VideoReplyPanel extends StatefulWidget { class VideoReplyPanel extends StatefulWidget {
final String? bvid; final String? bvid;

View File

@@ -1,10 +1,7 @@
import 'dart:convert';
import 'package:PiliPalaX/common/widgets/badge.dart'; import 'package:PiliPalaX/common/widgets/badge.dart';
import 'package:PiliPalaX/common/widgets/imageview.dart'; import 'package:PiliPalaX/common/widgets/imageview.dart';
import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart'; import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart';
import 'package:PiliPalaX/http/video.dart'; import 'package:PiliPalaX/http/video.dart';
import 'package:PiliPalaX/pages/video/detail/reply/widgets/zan.dart';
import 'package:PiliPalaX/pages/video/detail/reply/widgets/zan_grpc.dart'; import 'package:PiliPalaX/pages/video/detail/reply/widgets/zan_grpc.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -261,8 +258,7 @@ class ReplyItemGrpc extends StatelessWidget {
String text = replyItem.content.message; String text = replyItem.content.message;
var textPainter = TextPainter( var textPainter = TextPainter(
text: TextSpan(text: text), text: TextSpan(text: text),
maxLines: 6, maxLines: replyLevel == '1' ? 6 : null,
// replyItem.content!.isText! && replyLevel == '1' ? 6 : null,
textDirection: Directionality.of(context), textDirection: Directionality.of(context),
)..layout(maxWidth: constraints.maxWidth); )..layout(maxWidth: constraints.maxWidth);
bool didExceedMaxLines = textPainter.didExceedMaxLines; bool didExceedMaxLines = textPainter.didExceedMaxLines;
@@ -322,6 +318,7 @@ class ReplyItemGrpc extends StatelessWidget {
padding: const EdgeInsets.only(top: 5, bottom: 12), padding: const EdgeInsets.only(top: 5, bottom: 12),
child: ReplyItemRow( child: ReplyItemRow(
upMid: upMid, upMid: upMid,
count: replyItem.count.toInt(),
replies: replyItem.replies, replies: replyItem.replies,
replyControl: replyItem.replyControl, replyControl: replyItem.replyControl,
// f_rpid: replyItem.rpid, // f_rpid: replyItem.rpid,
@@ -329,7 +326,7 @@ class ReplyItemGrpc extends StatelessWidget {
replyReply: replyReply, replyReply: replyReply,
onDelete: (rpid) { onDelete: (rpid) {
if (onDelete != null) { if (onDelete != null) {
onDelete!(rpid, replyItem.id); onDelete!(rpid, replyItem.id.toInt());
} }
}, },
), ),
@@ -410,6 +407,7 @@ class ReplyItemGrpc extends StatelessWidget {
class ReplyItemRow extends StatelessWidget { class ReplyItemRow extends StatelessWidget {
ReplyItemRow({ ReplyItemRow({
super.key, super.key,
required this.count,
required this.replies, required this.replies,
required this.replyControl, required this.replyControl,
// this.f_rpid, // this.f_rpid,
@@ -418,6 +416,7 @@ class ReplyItemRow extends StatelessWidget {
this.onDelete, this.onDelete,
this.upMid, this.upMid,
}); });
final int count;
final List<ReplyInfo> replies; final List<ReplyInfo> replies;
ReplyControl replyControl; ReplyControl replyControl;
// int? f_rpid; // int? f_rpid;
@@ -428,7 +427,7 @@ class ReplyItemRow extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final bool extraRow = replyControl.subReplyEntryText.isNotEmpty; final bool extraRow = replies.length < count;
return Container( return Container(
margin: const EdgeInsets.only(left: 42, right: 4, top: 0), margin: const EdgeInsets.only(left: 42, right: 4, top: 0),
child: Material( child: Material(
@@ -614,35 +613,35 @@ InlineSpan buildContent(
message = message.substring(0, endOffset); message = message.substring(0, endOffset);
} }
return TextSpan(text: message); // return TextSpan(text: message);
// 投票 // 投票
// if (content.vote.isNotEmpty) { if (content.hasVote()) {
// message.splitMapJoin(RegExp(r"\{vote:\d+?\}"), onMatch: (Match match) { message.splitMapJoin(RegExp(r"\{vote:\d+?\}"), onMatch: (Match match) {
// // String matchStr = match[0]!; // String matchStr = match[0]!;
// spanChildren.add( spanChildren.add(
// TextSpan( TextSpan(
// text: '投票: ${content.vote['title']}', text: '投票: ${content.vote.title}',
// style: TextStyle( style: TextStyle(
// color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
// ), ),
// recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()..onTap = () {}
// ..onTap = () => Get.toNamed( // Get.toNamed(
// '/webviewnew', // '/webviewnew',
// parameters: { // parameters: {
// 'url': content.vote['url'], // 'url': content.vote['url'],
// 'type': 'vote', // 'type': 'vote',
// 'pageTitle': content.vote['title'], // 'pageTitle': content.vote.title,
// }, // },
// ), // ),
// ), ),
// ); );
// return ''; return '';
// }, onNonMatch: (String str) { }, onNonMatch: (String str) {
// return str; return str;
// }); });
// message = message.replaceAll(RegExp(r"\{vote:\d+?\}"), ""); message = message.replaceAll(RegExp(r"\{vote:\d+?\}"), "");
// } }
message = message message = message
.replaceAll('&amp;', '&') .replaceAll('&amp;', '&')
.replaceAll('&lt;', '<') .replaceAll('&lt;', '<')
@@ -653,22 +652,22 @@ InlineSpan buildContent(
// 构建正则表达式 // 构建正则表达式
final List<String> specialTokens = [ final List<String> specialTokens = [
...content.emote.keys, ...content.emote.keys,
// ...content.topicsMeta?.keys?.map((e) => '#$e#') ?? [], ...content.topic.keys.map((e) => '#$e#'),
...content.atNameToMid.keys.map((e) => '@$e'), ...content.atNameToMid.keys.map((e) => '@$e'),
]; ];
// List<String> jumpUrlKeysList = content.jumpUrl.keys.map<String>((String e) { List<String> jumpUrlKeysList = content.url.keys.map<String>((String e) {
// return e.replaceAllMapped( return e.replaceAllMapped(
// RegExp(r'[?+*]'), (match) => '\\${match.group(0)}'); RegExp(r'[?+*]'), (match) => '\\${match.group(0)}');
// }).toList(); }).toList();
specialTokens.sort((a, b) => b.length.compareTo(a.length)); specialTokens.sort((a, b) => b.length.compareTo(a.length));
String patternStr = specialTokens.map(RegExp.escape).join('|'); String patternStr = specialTokens.map(RegExp.escape).join('|');
if (patternStr.isNotEmpty) { if (patternStr.isNotEmpty) {
patternStr += "|"; patternStr += "|";
} }
patternStr += r'(\b(?:\d+[:])?[0-5]?[0-9][:][0-5]?[0-9]\b)'; patternStr += r'(\b(?:\d+[:])?[0-5]?[0-9][:][0-5]?[0-9]\b)';
// if (jumpUrlKeysList.isNotEmpty) { if (jumpUrlKeysList.isNotEmpty) {
// patternStr += '|${jumpUrlKeysList.map(RegExp.escape).join('|')}'; patternStr += '|${jumpUrlKeysList.map(RegExp.escape).join('|')}';
// } }
final RegExp pattern = RegExp(patternStr); final RegExp pattern = RegExp(patternStr);
List<String> matchedStrs = []; List<String> matchedStrs = [];
void addPlainTextSpan(str) { void addPlainTextSpan(str) {
@@ -684,304 +683,302 @@ InlineSpan buildContent(
} }
// 分割文本并处理每个部分 // 分割文本并处理每个部分
// message.splitMapJoin( message.splitMapJoin(
// pattern, pattern,
// onMatch: (Match match) { onMatch: (Match match) {
// String matchStr = match[0]!; String matchStr = match[0]!;
// if (content.emote.containsKey(matchStr)) { if (content.emote.containsKey(matchStr)) {
// // 处理表情 // 处理表情
// final int size = content.emote[matchStr]['meta']['size']; final int size = content.emote[matchStr]!.size.toInt();
// spanChildren.add(WidgetSpan( spanChildren.add(WidgetSpan(
// child: ExcludeSemantics( child: ExcludeSemantics(
// child: NetworkImgLayer( child: NetworkImgLayer(
// src: content.emote[matchStr]['url'], src: content.emote[matchStr]!.url,
// type: 'emote', type: 'emote',
// width: size * 20, width: size * 20,
// height: size * 20, height: size * 20,
// semanticsLabel: matchStr, semanticsLabel: matchStr,
// )), )),
// )); ));
// } else if (matchStr.startsWith("@") && } else if (matchStr.startsWith("@") &&
// content.atNameToMid.containsKey(matchStr.substring(1))) { content.atNameToMid.containsKey(matchStr.substring(1))) {
// // 处理@用户 // 处理@用户
// final String userName = matchStr.substring(1); final String userName = matchStr.substring(1);
// final int userId = content.atNameToMid[userName]; final int userId = content.atNameToMid[userName]!.toInt();
// spanChildren.add( spanChildren.add(
// TextSpan( TextSpan(
// text: matchStr, text: matchStr,
// style: TextStyle( style: TextStyle(
// color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
// ), ),
// recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
// ..onTap = () { ..onTap = () {
// final String heroTag = Utils.makeHeroTag(userId); final String heroTag = Utils.makeHeroTag(userId);
// Get.toNamed( Get.toNamed(
// '/member?mid=$userId', '/member?mid=$userId',
// arguments: {'face': '', 'heroTag': heroTag}, arguments: {'face': '', 'heroTag': heroTag},
// ); );
// }, },
// ), ),
// ); );
// } else if (RegExp(r'^\b(?:\d+[:])?[0-5]?[0-9][:][0-5]?[0-9]\b$') } else if (RegExp(r'^\b(?:\d+[:])?[0-5]?[0-9][:][0-5]?[0-9]\b$')
// .hasMatch(matchStr)) { .hasMatch(matchStr)) {
// matchStr = matchStr.replaceAll('', ':'); matchStr = matchStr.replaceAll('', ':');
// spanChildren.add( spanChildren.add(
// TextSpan( TextSpan(
// text: ' $matchStr ', text: ' $matchStr ',
// style: isVideoPage style: isVideoPage
// ? TextStyle( ? TextStyle(
// color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
// ) )
// : null, : null,
// recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
// ..onTap = () { ..onTap = () {
// // 跳转到指定位置 // 跳转到指定位置
// if (isVideoPage) { if (isVideoPage) {
// try { try {
// SmartDialog.showToast('跳转至:$matchStr'); SmartDialog.showToast('跳转至:$matchStr');
// Get.find<VideoDetailController>( Get.find<VideoDetailController>(
// tag: Get.arguments['heroTag']) tag: Get.arguments['heroTag'])
// .plPlayerController .plPlayerController
// .seekTo(Duration(seconds: Utils.duration(matchStr)), .seekTo(Duration(seconds: Utils.duration(matchStr)),
// type: 'slider'); type: 'slider');
// } catch (e) { } catch (e) {
// SmartDialog.showToast('跳转失败: $e'); SmartDialog.showToast('跳转失败: $e');
// } }
// } }
// }, },
// ), ),
// ); );
// } else { } else {
// String appUrlSchema = ''; String appUrlSchema = '';
// final bool enableWordRe = setting.get(SettingBoxKey.enableWordRe, final bool enableWordRe = setting.get(SettingBoxKey.enableWordRe,
// defaultValue: false) as bool; defaultValue: false) as bool;
// if (content.jumpUrl[matchStr] != null && if (content.url[matchStr] != null && !matchedStrs.contains(matchStr)) {
// !matchedStrs.contains(matchStr)) { appUrlSchema = content.url[matchStr]!.appUrlSchema;
// appUrlSchema = content.jumpUrl[matchStr]['app_url_schema']; if (appUrlSchema.startsWith('bilibili://search') && !enableWordRe) {
// if (appUrlSchema.startsWith('bilibili://search') && !enableWordRe) { addPlainTextSpan(matchStr);
// addPlainTextSpan(matchStr); return "";
// return ""; }
// } spanChildren.addAll(
// spanChildren.addAll( [
// [ if (content.url[matchStr]?.hasPrefixIcon() == true) ...[
// if (content.jumpUrl[matchStr]?['prefix_icon'] != null) ...[ WidgetSpan(
// WidgetSpan( child: Image.network(
// child: Image.network( content.url[matchStr]!.prefixIcon,
// content.jumpUrl[matchStr]['prefix_icon'], height: 19,
// height: 19, color: Theme.of(context).colorScheme.primary,
// color: Theme.of(context).colorScheme.primary, ),
// ), )
// ) ],
// ], TextSpan(
// TextSpan( text: content.url[matchStr]!.title,
// text: content.jumpUrl[matchStr]['title'], style: TextStyle(
// style: TextStyle( color: Theme.of(context).colorScheme.primary,
// color: Theme.of(context).colorScheme.primary, ),
// ), recognizer: TapGestureRecognizer()
// recognizer: TapGestureRecognizer() ..onTap = () async {
// ..onTap = () async { final String title = content.url[matchStr]!.title;
// final String title = content.jumpUrl[matchStr]['title']; if (appUrlSchema == '') {
// if (appUrlSchema == '') { if (matchStr.startsWith('BV')) {
// if (matchStr.startsWith('BV')) { UrlUtils.matchUrlPush(
// UrlUtils.matchUrlPush( matchStr,
// matchStr, title,
// title, '',
// '', );
// ); } else if (RegExp(r'^[Cc][Vv][0-9]+$')
// } else if (RegExp(r'^[Cc][Vv][0-9]+$') .hasMatch(matchStr)) {
// .hasMatch(matchStr)) { Get.toNamed('/htmlRender', parameters: {
// Get.toNamed('/htmlRender', parameters: { 'url': 'https://www.bilibili.com/read/$matchStr',
// 'url': 'https://www.bilibili.com/read/$matchStr', 'title': title,
// 'title': title, 'id': matchStr,
// 'id': matchStr, 'dynamicType': 'read'
// 'dynamicType': 'read' });
// }); } else {
// } else { final String redirectUrl =
// final String redirectUrl = await UrlUtils.parseRedirectUrl(matchStr);
// await UrlUtils.parseRedirectUrl(matchStr); // if (redirectUrl == matchStr) {
// // if (redirectUrl == matchStr) { // Clipboard.setData(ClipboardData(text: matchStr));
// // Clipboard.setData(ClipboardData(text: matchStr)); // SmartDialog.showToast('地址可能有误');
// // SmartDialog.showToast('地址可能有误'); // return;
// // return; // }
// // } Uri uri = Uri.parse(redirectUrl);
// Uri uri = Uri.parse(redirectUrl); PiliScheme.routePush(uri);
// PiliScheme.routePush(uri); // final String pathSegment = Uri.parse(redirectUrl).path;
// // final String pathSegment = Uri.parse(redirectUrl).path; // final String lastPathSegment =
// // final String lastPathSegment = // pathSegment.split('/').last;
// // pathSegment.split('/').last; // if (lastPathSegment.startsWith('BV')) {
// // if (lastPathSegment.startsWith('BV')) { // UrlUtils.matchUrlPush(
// // UrlUtils.matchUrlPush( // lastPathSegment,
// // lastPathSegment, // title,
// // title, // redirectUrl,
// // redirectUrl, // );
// // ); // } else {
// // } else { // Get.toNamed(
// // Get.toNamed( // '/webviewnew',
// // '/webviewnew', // parameters: {
// // parameters: { // 'url': redirectUrl,
// // 'url': redirectUrl, // 'type': 'url',
// // 'type': 'url', // 'pageTitle': title
// // 'pageTitle': title // },
// // }, // );
// // ); // }
// // } }
// } } else {
// } else { if (appUrlSchema.startsWith('bilibili://search')) {
// if (appUrlSchema.startsWith('bilibili://search')) { Get.toNamed('/searchResult',
// Get.toNamed('/searchResult', parameters: {'keyword': title});
// parameters: {'keyword': title}); } else if (matchStr.startsWith('https://b23.tv')) {
// } else if (matchStr.startsWith('https://b23.tv')) { final String redirectUrl =
// final String redirectUrl = await UrlUtils.parseRedirectUrl(matchStr);
// await UrlUtils.parseRedirectUrl(matchStr); final String pathSegment = Uri.parse(redirectUrl).path;
// final String pathSegment = Uri.parse(redirectUrl).path; final String lastPathSegment =
// final String lastPathSegment = pathSegment.split('/').last;
// pathSegment.split('/').last; if (lastPathSegment.startsWith('BV')) {
// if (lastPathSegment.startsWith('BV')) { UrlUtils.matchUrlPush(
// UrlUtils.matchUrlPush( lastPathSegment,
// lastPathSegment, title,
// title, redirectUrl,
// redirectUrl, );
// ); } else {
// } else { Get.toNamed(
// Get.toNamed( '/webviewnew',
// '/webviewnew', parameters: {
// parameters: { 'url': redirectUrl,
// 'url': redirectUrl, 'type': 'url',
// 'type': 'url', 'pageTitle': title
// 'pageTitle': title },
// }, );
// ); }
// } } else {
// } else { Get.toNamed(
// Get.toNamed( '/webviewnew',
// '/webviewnew', parameters: {
// parameters: { 'url': matchStr,
// 'url': matchStr, 'type': 'url',
// 'type': 'url', 'pageTitle': title
// 'pageTitle': title },
// }, );
// ); }
// } }
// } },
// }, )
// ) ],
// ], );
// ); // 只显示一次
// // 只显示一次 matchedStrs.add(matchStr);
// matchedStrs.add(matchStr); } else if (matchStr.length > 1 &&
// } else if (matchStr.length > 1 && content.topic[matchStr.substring(1, matchStr.length - 1)] != null) {
// content.topicsMeta[matchStr.substring(1, matchStr.length - 1)] != spanChildren.add(
// null) { TextSpan(
// spanChildren.add( text: matchStr,
// TextSpan( style: TextStyle(
// text: matchStr, color: Theme.of(context).colorScheme.primary,
// style: TextStyle( ),
// color: Theme.of(context).colorScheme.primary, recognizer: TapGestureRecognizer()
// ), ..onTap = () {
// recognizer: TapGestureRecognizer() final String topic =
// ..onTap = () { matchStr.substring(1, matchStr.length - 1);
// final String topic = Get.toNamed('/searchResult', parameters: {'keyword': topic});
// matchStr.substring(1, matchStr.length - 1); },
// Get.toNamed('/searchResult', parameters: {'keyword': topic}); ),
// }, );
// ), } else {
// ); addPlainTextSpan(matchStr);
// } else { }
// addPlainTextSpan(matchStr); }
// } return '';
// } },
// return ''; onNonMatch: (String nonMatchStr) {
// }, addPlainTextSpan(nonMatchStr);
// onNonMatch: (String nonMatchStr) { return nonMatchStr;
// addPlainTextSpan(nonMatchStr); },
// return nonMatchStr; );
// },
// );
// if (content.jumpUrl.keys.isNotEmpty) { if (content.url.keys.isNotEmpty) {
// List<String> unmatchedItems = content.jumpUrl.keys List<String> unmatchedItems = content.url.keys
// .toList() .toList()
// .where((item) => !content.message.contains(item)) .where((item) => !content.message.contains(item))
// .toList(); .toList();
// if (unmatchedItems.isNotEmpty) { if (unmatchedItems.isNotEmpty) {
// for (int i = 0; i < unmatchedItems.length; i++) { for (int i = 0; i < unmatchedItems.length; i++) {
// String patternStr = unmatchedItems[i]; String patternStr = unmatchedItems[i];
// spanChildren.addAll( spanChildren.addAll(
// [ [
// if (content.jumpUrl[patternStr]?['prefix_icon'] != null) ...[ if (content.url[patternStr]?.hasPrefixIcon() == true) ...[
// WidgetSpan( WidgetSpan(
// child: Image.network( child: Image.network(
// content.jumpUrl[patternStr]['prefix_icon'], content.url[patternStr]!.prefixIcon,
// height: 19, height: 19,
// color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
// ), ),
// ) )
// ], ],
// TextSpan( TextSpan(
// text: content.jumpUrl[patternStr]['title'], text: content.url[patternStr]!.title,
// style: TextStyle( style: TextStyle(
// color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
// ), ),
// recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
// ..onTap = () { ..onTap = () {
// Get.toNamed( Get.toNamed(
// '/webviewnew', '/webviewnew',
// parameters: { parameters: {
// 'url': patternStr, 'url': patternStr,
// 'type': 'url', 'type': 'url',
// 'pageTitle': content.jumpUrl[patternStr]['title'] 'pageTitle': content.url[patternStr]!.title
// }, },
// ); );
// }, },
// ) )
// ], ],
// ); );
// } }
// } }
// } }
// 图片渲染 // 图片渲染
// if (content.pictures.isNotEmpty) { if (content.pictures.isNotEmpty) {
// spanChildren.add(const TextSpan(text: '\n')); spanChildren.add(const TextSpan(text: '\n'));
// spanChildren.add( spanChildren.add(
// WidgetSpan( WidgetSpan(
// child: LayoutBuilder( child: LayoutBuilder(
// builder: (_, constraints) => image( builder: (_, constraints) => image(
// constraints.maxWidth, constraints.maxWidth,
// (content.pictures as List) content.pictures
// .map( .map(
// (item) => ImageModel( (item) => ImageModel(
// width: item['img_width'], width: item.imgWidth,
// height: item['img_height'], height: item.imgHeight,
// url: item['img_src'], url: item.imgSrc,
// ), ),
// ) )
// .toList(), .toList(),
// ), ),
// ), ),
// ), ),
// ); );
// } }
// 笔记链接 // 笔记链接
// if (content.richText.isNotEmpty) { if (content.hasRichText()) {
// spanChildren.add( spanChildren.add(
// TextSpan( TextSpan(
// text: ' 笔记', text: ' 笔记',
// style: TextStyle( style: TextStyle(
// color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
// ), ),
// recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
// ..onTap = () => Get.toNamed( ..onTap = () => Get.toNamed(
// '/webviewnew', '/webviewnew',
// parameters: { parameters: {
// 'url': content.richText['note']['click_url'], 'url': content.richText.note.clickUrl,
// 'type': 'note', 'type': 'note',
// 'pageTitle': '笔记预览' 'pageTitle': '笔记预览'
// }, },
// ), ),
// ), ),
// ); );
// } }
// spanChildren.add(TextSpan(text: matchMember)); // spanChildren.add(TextSpan(text: matchMember));
return TextSpan(children: spanChildren); return TextSpan(children: spanChildren);
} }
@@ -1005,7 +1002,7 @@ class MorePanel extends StatelessWidget {
}, },
); );
if (result == true && onDelete != null) { if (result == true && onDelete != null) {
onDelete!(item.id); onDelete!(item.id.toInt());
} }
break; break;
case 'copyAll': case 'copyAll':
@@ -1015,18 +1012,18 @@ class MorePanel extends StatelessWidget {
break; break;
case 'copyFreedom': case 'copyFreedom':
Get.back(); Get.back();
// showDialog( showDialog(
// context: Get.context!, context: Get.context!,
// builder: (context) { builder: (context) {
// return Dialog( return Dialog(
// child: Padding( child: Padding(
// padding: padding:
// const EdgeInsets.symmetric(horizontal: 20, vertical: 16), const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
// child: SelectableText(message), child: SelectableText(message),
// ), ),
// ); );
// }, },
// ); );
break; break;
// case 'block': // case 'block':
// SmartDialog.showToast('加入黑名单'); // SmartDialog.showToast('加入黑名单');
@@ -1075,7 +1072,7 @@ class MorePanel extends StatelessWidget {
SmartDialog.showToast('删除成功'); SmartDialog.showToast('删除成功');
// Get.back(); // Get.back();
if (onDelete != null) { if (onDelete != null) {
onDelete!(item.id); onDelete!(item.id.toInt());
} }
} else { } else {
SmartDialog.showToast('删除失败, ${result["msg"]}'); SmartDialog.showToast('删除失败, ${result["msg"]}');

View File

@@ -4,7 +4,6 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:PiliPalaX/http/reply.dart'; import 'package:PiliPalaX/http/reply.dart';
import 'package:PiliPalaX/models/common/reply_type.dart'; import 'package:PiliPalaX/models/common/reply_type.dart';
import 'package:PiliPalaX/models/video/reply/item.dart';
import 'package:PiliPalaX/utils/feed_back.dart'; import 'package:PiliPalaX/utils/feed_back.dart';
import 'package:fixnum/fixnum.dart' as $fixnum; import 'package:fixnum/fixnum.dart' as $fixnum;

View File

@@ -2,6 +2,8 @@ import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart'
as reply;
import 'package:PiliPalaX/http/msg.dart'; import 'package:PiliPalaX/http/msg.dart';
import 'package:chat_bottom_container/chat_bottom_container.dart'; import 'package:chat_bottom_container/chat_bottom_container.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -24,7 +26,7 @@ class ReplyPage extends StatefulWidget {
final int? root; final int? root;
final int? parent; final int? parent;
final ReplyType? replyType; final ReplyType? replyType;
final ReplyItemModel? replyItem; final reply.ReplyInfo? replyItem;
final String? savedReply; final String? savedReply;
final Function(String reply)? onSaveReply; final Function(String reply)? onSaveReply;
@@ -492,7 +494,7 @@ class _ReplyPageState extends State<ReplyPage>
root: widget.root!, root: widget.root!,
parent: widget.parent!, parent: widget.parent!,
message: widget.replyItem != null && widget.replyItem!.root != 0 message: widget.replyItem != null && widget.replyItem!.root != 0
? ' 回复 @${widget.replyItem!.member!.uname!} : $message' ? ' 回复 @${widget.replyItem!.member.name} : $message'
: message, : message,
pictures: pictures, pictures: pictures,
); );

View File

@@ -4,7 +4,6 @@ import 'package:PiliPalaX/pages/common/common_controller.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:PiliPalaX/http/reply.dart'; import 'package:PiliPalaX/http/reply.dart';
import 'package:PiliPalaX/models/common/reply_type.dart'; import 'package:PiliPalaX/models/common/reply_type.dart';
import 'package:PiliPalaX/models/video/reply/item.dart';
class VideoReplyReplyController extends CommonController { class VideoReplyReplyController extends CommonController {
VideoReplyReplyController(this.aid, this.rpid, this.replyType); VideoReplyReplyController(this.aid, this.rpid, this.replyType);

View File

@@ -1,5 +1,4 @@
import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart'; import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart';
import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pbenum.dart';
import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/http/loading_state.dart';
import 'package:PiliPalaX/pages/video/detail/reply/view.dart' import 'package:PiliPalaX/pages/video/detail/reply/view.dart'
show MySliverPersistentHeaderDelegate; show MySliverPersistentHeaderDelegate;
@@ -11,8 +10,6 @@ import 'package:get/get.dart';
import 'package:PiliPalaX/common/skeleton/video_reply.dart'; import 'package:PiliPalaX/common/skeleton/video_reply.dart';
import 'package:PiliPalaX/common/widgets/http_error.dart'; import 'package:PiliPalaX/common/widgets/http_error.dart';
import 'package:PiliPalaX/models/common/reply_type.dart'; import 'package:PiliPalaX/models/common/reply_type.dart';
import 'package:PiliPalaX/models/video/reply/item.dart';
import 'package:PiliPalaX/pages/video/detail/reply/widgets/reply_item.dart';
import 'package:get/get_navigation/src/dialog/dialog_route.dart'; import 'package:get/get_navigation/src/dialog/dialog_route.dart';
import '../../../../utils/utils.dart'; import '../../../../utils/utils.dart';
@@ -122,7 +119,7 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
replyType: widget.replyType, replyType: widget.replyType,
needDivider: false, needDivider: false,
onReply: () { onReply: () {
// _onReply(widget.firstFloor!); _onReply(widget.firstFloor!);
}, },
), ),
), ),
@@ -186,10 +183,10 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
); );
} }
void _onReply(ReplyItemModel? item) { void _onReply(ReplyInfo? item) {
dynamic oid = item?.oid; dynamic oid = item?.oid.toInt();
dynamic root = item?.rpid; dynamic root = item?.id.toInt();
dynamic parent = item?.rpid; dynamic parent = item?.id.toInt();
dynamic key = oid + root + parent; dynamic key = oid + root + parent;
Navigator.of(context) Navigator.of(context)
.push( .push(
@@ -224,13 +221,14 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
), ),
) )
.then((value) { .then((value) {
// 完成评论,数据添加 // 完成评论,数据添加 // TODO: data cast
if (value != null && value['data'] != null) { if (value != null && value['data'] is ReplyInfo) {
_savedReplies[key] = null; _savedReplies[key] = null;
List list = _videoReplyReplyController.loadingState.value is Success List<ReplyInfo> list =
? (_videoReplyReplyController.loadingState.value as Success) _videoReplyReplyController.loadingState.value is Success
.response ? (_videoReplyReplyController.loadingState.value as Success)
: []; .response
: <ReplyInfo>[];
list.add(value['data']); list.add(value['data']);
_videoReplyReplyController.loadingState.value = _videoReplyReplyController.loadingState.value =
LoadingState.success(list); LoadingState.success(list);
@@ -252,7 +250,7 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
replyType: widget.replyType, replyType: widget.replyType,
needDivider: false, needDivider: false,
onReply: () { onReply: () {
// _onReply(_videoReplyReplyController.root); _onReply(_videoReplyReplyController.root);
}, },
), ),
), ),
@@ -297,8 +295,7 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
List list = (_videoReplyReplyController List list = (_videoReplyReplyController
.loadingState.value as Success) .loadingState.value as Success)
.response; .response;
list = list = list.where((item) => item.id != rpid).toList();
list.where((item) => item.rpid != rpid).toList();
_videoReplyReplyController.loadingState.value = _videoReplyReplyController.loadingState.value =
LoadingState.success(list); LoadingState.success(list);
}, },