feat: richtextfield

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-06-27 12:02:32 +08:00
parent 721bf2d59f
commit 6f2570c5be
26 changed files with 7154 additions and 870 deletions

View File

@@ -945,7 +945,7 @@ class VideoDetailController extends GetxController
bvid: bvid,
progress: plPlayerController.position.value.inMilliseconds,
initialValue: savedDanmaku,
onSave: (danmaku) => savedDanmaku = danmaku.text,
onSave: (danmaku) => savedDanmaku = danmaku,
callback: (danmakuModel) {
savedDanmaku = null;
plPlayerController.danmakuController?.addDanmaku(danmakuModel);

View File

@@ -1,13 +1,15 @@
import 'dart:async';
import 'package:PiliPlus/common/widgets/button/toolbar_icon_button.dart';
import 'package:PiliPlus/common/widgets/text_field/controller.dart'
show RichTextType;
import 'package:PiliPlus/common/widgets/text_field/text_field.dart';
import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart'
show ReplyInfo;
import 'package:PiliPlus/http/video.dart';
import 'package:PiliPlus/main.dart';
import 'package:PiliPlus/models/common/publish_panel_type.dart';
import 'package:PiliPlus/pages/common/common_publish_page.dart';
import 'package:PiliPlus/pages/common/publish/common_rich_text_pub_page.dart';
import 'package:PiliPlus/pages/dynamics_mention/controller.dart';
import 'package:PiliPlus/pages/emote/view.dart';
import 'package:PiliPlus/utils/storage_pref.dart';
@@ -15,7 +17,7 @@ import 'package:flutter/material.dart' hide TextField;
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
class ReplyPage extends CommonPublishPage {
class ReplyPage extends CommonRichTextPubPage {
final int oid;
final int root;
final int parent;
@@ -25,8 +27,7 @@ class ReplyPage extends CommonPublishPage {
const ReplyPage({
super.key,
super.initialValue,
super.mentions,
super.items,
super.imageLengthLimit,
super.onSave,
required this.oid,
@@ -41,7 +42,7 @@ class ReplyPage extends CommonPublishPage {
State<ReplyPage> createState() => _ReplyPageState();
}
class _ReplyPageState extends CommonPublishPageState<ReplyPage> {
class _ReplyPageState extends CommonRichTextPubPageState<ReplyPage> {
final RxBool _syncToDynamic = false.obs;
Widget get child => SafeArea(
@@ -137,7 +138,7 @@ class _ReplyPageState extends CommonPublishPageState<ReplyPage> {
}
},
child: Obx(
() => TextField(
() => RichTextField(
controller: editController,
minLines: 4,
maxLines: 8,
@@ -151,8 +152,6 @@ class _ReplyPageState extends CommonPublishPageState<ReplyPage> {
hintStyle: const TextStyle(fontSize: 14),
),
style: themeData.textTheme.bodyLarge,
onMention: onMention,
onDelAtUser: onDelAtUser,
),
),
),
@@ -265,8 +264,12 @@ class _ReplyPageState extends CommonPublishPageState<ReplyPage> {
}
@override
Future<void> onCustomPublish(
{required String message, List? pictures}) async {
Future<void> onCustomPublish({List? pictures}) async {
Map<String, int> atNameToMid = {
for (var e in editController.items)
if (e.type == RichTextType.at) e.rawText: int.parse(e.uid!),
};
String message = editController.rawText;
var result = await VideoHttp.replyAdd(
type: widget.replyType,
oid: widget.oid,
@@ -275,13 +278,12 @@ class _ReplyPageState extends CommonPublishPageState<ReplyPage> {
message: widget.replyItem != null && widget.replyItem!.root != 0
? ' 回复 @${widget.replyItem!.member.name} : $message'
: message,
atNameToMid: mentions?.isNotEmpty == true
? {for (var e in mentions!) e.name: e.uid}
: null,
atNameToMid: atNameToMid,
pictures: pictures,
syncToDynamic: _syncToDynamic.value,
);
if (result['status']) {
hasPub = true;
SmartDialog.showToast(result['data']['success_toast']);
Get.back(result: result['data']['reply']);
} else {

View File

@@ -149,16 +149,20 @@ class VideoReplyReplyController extends ReplyController
.push(
GetDialogRoute(
pageBuilder: (buildContext, animation, secondaryAnimation) {
final saved = savedReplies[key];
return ReplyPage(
oid: oid,
root: root,
parent: root,
replyType: this.replyType,
replyItem: replyItem,
initialValue: saved?.text,
mentions: saved?.mentions,
onSave: (reply) => savedReplies[key] = reply,
items: savedReplies[key],
onSave: (reply) {
if (reply.isEmpty) {
savedReplies.remove(key);
} else {
savedReplies[key] = reply.toList();
}
},
);
},
transitionDuration: const Duration(milliseconds: 500),

View File

@@ -5,7 +5,7 @@ import 'package:PiliPlus/http/danmaku.dart';
import 'package:PiliPlus/main.dart';
import 'package:PiliPlus/models/common/publish_panel_type.dart';
import 'package:PiliPlus/models/user/info.dart';
import 'package:PiliPlus/pages/common/common_publish_page.dart';
import 'package:PiliPlus/pages/common/publish/common_text_pub_page.dart';
import 'package:PiliPlus/pages/setting/slide_color_picker.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:canvas_danmaku/models/danmaku_content_item.dart';
@@ -14,7 +14,7 @@ import 'package:flutter/services.dart' show LengthLimitingTextInputFormatter;
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
class SendDanmakuPanel extends CommonPublishPage {
class SendDanmakuPanel extends CommonTextPubPage {
// video
final dynamic cid;
final dynamic bvid;
@@ -44,7 +44,7 @@ class SendDanmakuPanel extends CommonPublishPage {
State<SendDanmakuPanel> createState() => _SendDanmakuPanelState();
}
class _SendDanmakuPanelState extends CommonPublishPageState<SendDanmakuPanel> {
class _SendDanmakuPanelState extends CommonTextPubPageState<SendDanmakuPanel> {
late final RxInt _mode;
late final RxInt _fontsize;
late final Rx<Color> _color;
@@ -448,8 +448,7 @@ class _SendDanmakuPanelState extends CommonPublishPageState<SendDanmakuPanel> {
}
@override
Future<void> onCustomPublish(
{required String message, List? pictures}) async {
Future<void> onCustomPublish({List? pictures}) async {
SmartDialog.showLoading(msg: '发送中...');
bool isColorful = _color.value == Colors.transparent;
final res = await DanmakuHttp.shootDanmaku(
@@ -464,6 +463,7 @@ class _SendDanmakuPanelState extends CommonPublishPageState<SendDanmakuPanel> {
);
SmartDialog.dismiss();
if (res['status']) {
hasPub = true;
Get.back();
SmartDialog.showToast('发送成功');
widget.callback(