del at user

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-06-24 23:23:21 +08:00
parent 7be3774675
commit 4b067c5ed2
10 changed files with 40 additions and 53 deletions

View File

@@ -3287,6 +3287,7 @@ class EditableTextState extends State<EditableText>
composing: e.composing,
).apply(value);
widget.onChanged?.call(_value.text);
widget.onDelAtUser?.call(match.group(0)!.trim());
return;
}
}

View File

@@ -14,7 +14,6 @@ import 'package:PiliPlus/pages/dynamics_mention/view.dart';
import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/feed_back.dart';
import 'package:chat_bottom_container/chat_bottom_container.dart';
import 'package:collection/collection.dart';
import 'package:dio/dio.dart';
import 'package:easy_debounce/easy_throttle.dart';
import 'package:flutter/material.dart';
@@ -34,9 +33,9 @@ abstract class CommonPublishPage extends StatefulWidget {
});
final String? initialValue;
final Set<MentionItem>? mentions;
final List<MentionItem>? mentions;
final int? imageLengthLimit;
final ValueChanged<({String text, Set<MentionItem>? mentions})>? onSave;
final ValueChanged<({String text, List<MentionItem>? mentions})>? onSave;
final bool autofocus;
}
@@ -54,7 +53,7 @@ abstract class CommonPublishPageState<T extends CommonPublishPage>
late final RxList<String> pathList = <String>[].obs;
int get limit => widget.imageLengthLimit ?? 9;
Set<MentionItem>? mentions;
List<MentionItem>? mentions;
@override
void initState() {
@@ -409,8 +408,8 @@ abstract class CommonPublishPageState<T extends CommonPublishPage>
});
}
final pattern =
RegExp(mentions!.map((e) => RegExp.escape('@${e.name!}')).join('|'));
final pattern = RegExp(
mentions!.toSet().map((e) => RegExp.escape('@${e.name!}')).join('|'));
editController.text.splitMapJoin(
pattern,
@@ -448,7 +447,7 @@ abstract class CommonPublishPageState<T extends CommonPublishPage>
if (res != null) {
enablePublish.value = true;
(mentions ??= <MentionItem>{}).add(res);
(mentions ??= <MentionItem>[]).add(res);
String atName = '${fromClick ? '@' : ''}${res.name} ';
final int cursorPosition = editController.selection.baseOffset;
@@ -464,4 +463,18 @@ abstract class CommonPublishPageState<T extends CommonPublishPage>
}
});
}
void onDelAtUser(String name) {
mentions!.removeFirstWhere((e) => e.name == name);
}
void onChanged(String value) {
bool isEmpty = value.trim().isEmpty;
if (!isEmpty && !enablePublish.value) {
enablePublish.value = true;
} else if (isEmpty && enablePublish.value) {
enablePublish.value = false;
}
widget.onSave?.call((text: value, mentions: mentions));
}
}

View File

@@ -26,7 +26,7 @@ abstract class ReplyController<R> extends CommonListController<R, ReplyInfo> {
late Rx<Mode> mode;
late final savedReplies =
<Object, ({String text, Set<MentionItem>? mentions})?>{};
<Object, ({String text, List<MentionItem>? mentions})?>{};
AccountService accountService = Get.find<AccountService>();

View File

@@ -569,16 +569,8 @@ class _CreateDynPanelState extends CommonPublishPageState<CreateDynPanel> {
maxLines: null,
focusNode: focusNode,
readOnly: readOnly.value,
onDelAtUser: (name) =>
mentions?.removeWhere((e) => e.name == name),
onChanged: (value) {
bool isEmpty = value.trim().isEmpty && pathList.isEmpty;
if (!isEmpty && !enablePublish.value) {
enablePublish.value = true;
} else if (isEmpty && enablePublish.value) {
enablePublish.value = false;
}
},
onDelAtUser: onDelAtUser,
onChanged: onChanged,
decoration: InputDecoration(
hintText: '说点什么吧',
hintStyle: TextStyle(color: theme.colorScheme.outline),

View File

@@ -242,6 +242,7 @@ class _RepostPanelState extends CommonPublishPageState<RepostPanel> {
),
inputFormatters: [LengthLimitingTextInputFormatter(1000)],
onMention: onMention,
onDelAtUser: onDelAtUser,
),
),
),

View File

@@ -107,15 +107,7 @@ class _ReplyPageState extends CommonPublishPageState<LiveSendDmPanel> {
maxLines: 2,
autofocus: false,
readOnly: readOnly.value,
onChanged: (value) {
bool isEmpty = value.trim().isEmpty;
if (!isEmpty && !enablePublish.value) {
enablePublish.value = true;
} else if (isEmpty && enablePublish.value) {
enablePublish.value = false;
}
liveRoomController.savedDanmaku = value;
},
onChanged: onChanged,
focusNode: focusNode,
decoration: const InputDecoration(
hintText: "输入弹幕内容",

View File

@@ -143,15 +143,7 @@ class _ReplyPageState extends CommonPublishPageState<ReplyPage> {
maxLines: 8,
autofocus: false,
readOnly: readOnly.value,
onChanged: (value) {
bool isEmpty = value.trim().isEmpty;
if (!isEmpty && !enablePublish.value) {
enablePublish.value = true;
} else if (isEmpty && enablePublish.value) {
enablePublish.value = false;
}
widget.onSave?.call((text: value, mentions: mentions));
},
onChanged: onChanged,
focusNode: focusNode,
decoration: InputDecoration(
hintText: widget.hint ?? "输入回复内容",
@@ -160,6 +152,7 @@ class _ReplyPageState extends CommonPublishPageState<ReplyPage> {
),
style: themeData.textTheme.bodyLarge,
onMention: onMention,
onDelAtUser: onDelAtUser,
),
),
),

View File

@@ -370,15 +370,7 @@ class _SendDanmakuPanelState extends CommonPublishPageState<SendDanmakuPanel> {
inputFormatters: [
LengthLimitingTextInputFormatter(100),
],
onChanged: (value) {
bool isEmpty = value.trim().isEmpty;
if (!isEmpty && !enablePublish.value) {
enablePublish.value = true;
} else if (isEmpty && enablePublish.value) {
enablePublish.value = false;
}
widget.onSave?.call((text: value, mentions: null));
},
onChanged: onChanged,
textInputAction: TextInputAction.send,
onSubmitted: (value) {
if (value.trim().isNotEmpty) {

View File

@@ -245,14 +245,7 @@ class _WhisperDetailPageState
controller: editController,
minLines: 1,
maxLines: 4,
onChanged: (value) {
bool isNotEmpty = value.trim().isNotEmpty;
if (isNotEmpty && !enablePublish.value) {
enablePublish.value = true;
} else if (!isNotEmpty && enablePublish.value) {
enablePublish.value = false;
}
},
onChanged: onChanged,
textInputAction: TextInputAction.newline,
decoration: InputDecoration(
filled: true,

View File

@@ -58,6 +58,16 @@ extension ListExt<T> on List<T>? {
T getOrElse(int index, {required T Function() orElse}) {
return getOrNull(index) ?? orElse();
}
bool removeFirstWhere(bool Function(T) test) {
if (this == null) return false;
final index = this!.indexWhere(test);
if (index != -1) {
this!.removeAt(index);
return true;
}
return false;
}
}
final _regExp = RegExp("^(http:)?//", caseSensitive: false);