feat(ui, core): handle ogAttachment modification via message_input_controller.dart.
Signed-off-by: xsahil03x <[email protected]>
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_flutter_core/src/message_text_field_controller.dart';
|
||||
|
||||
/// A value listenable builder related to a [Message].
|
||||
///
|
||||
@@ -17,33 +18,46 @@ class MessageInputController extends ValueNotifier<Message> {
|
||||
/// message.
|
||||
factory MessageInputController({
|
||||
Message? message,
|
||||
Map<RegExp, TextStyle>? textPatternStyle,
|
||||
}) =>
|
||||
MessageInputController._(
|
||||
initialMessage: message ?? Message(),
|
||||
textPatternStyle: textPatternStyle,
|
||||
);
|
||||
|
||||
/// Creates a controller for an editable text field from an initial [text].
|
||||
factory MessageInputController.fromText(String? text) =>
|
||||
factory MessageInputController.fromText(
|
||||
String? text, {
|
||||
Map<RegExp, TextStyle>? textPatternStyle,
|
||||
}) =>
|
||||
MessageInputController._(
|
||||
initialMessage: Message(text: text),
|
||||
textPatternStyle: textPatternStyle,
|
||||
);
|
||||
|
||||
/// Creates a controller for an editable text field from initial
|
||||
/// [attachments].
|
||||
factory MessageInputController.fromAttachments(
|
||||
List<Attachment> attachments,
|
||||
) =>
|
||||
List<Attachment> attachments, {
|
||||
Map<RegExp, TextStyle>? textPatternStyle,
|
||||
}) =>
|
||||
MessageInputController._(
|
||||
initialMessage: Message(attachments: attachments),
|
||||
textPatternStyle: textPatternStyle,
|
||||
);
|
||||
|
||||
MessageInputController._({
|
||||
required Message initialMessage,
|
||||
}) : _textEditingController =
|
||||
TextEditingController.fromValue(TextEditingValue(
|
||||
text: initialMessage.text ?? '',
|
||||
composing: TextRange.collapsed(initialMessage.text?.length ?? 0),
|
||||
)),
|
||||
Map<RegExp, TextStyle>? textPatternStyle,
|
||||
}) : _textEditingController = MessageTextFieldController.fromValue(
|
||||
initialMessage.text == null
|
||||
? const TextEditingValue()
|
||||
: TextEditingValue(
|
||||
text: initialMessage.text!,
|
||||
composing: TextRange.collapsed(initialMessage.text!.length),
|
||||
),
|
||||
textPatternStyle: textPatternStyle,
|
||||
),
|
||||
_initialMessage = initialMessage,
|
||||
super(initialMessage) {
|
||||
addListener(_textEditingSyncer);
|
||||
@@ -73,8 +87,9 @@ class MessageInputController extends ValueNotifier<Message> {
|
||||
Message get message => value;
|
||||
|
||||
/// Returns the controller of the text field linked to this controller.
|
||||
TextEditingController get textEditingController => _textEditingController;
|
||||
final TextEditingController _textEditingController;
|
||||
MessageTextFieldController get textEditingController =>
|
||||
_textEditingController;
|
||||
final MessageTextFieldController _textEditingController;
|
||||
|
||||
/// Returns the text of the message.
|
||||
String get text => _textEditingController.text;
|
||||
@@ -174,6 +189,28 @@ class MessageInputController extends ValueNotifier<Message> {
|
||||
attachments = [];
|
||||
}
|
||||
|
||||
// Only used to store the value locally in order to remove it if we call
|
||||
// [clearOGAttachment] or [setOGAttachment] again.
|
||||
Attachment? _ogAttachment;
|
||||
|
||||
/// Returns the og attachment of the message if set
|
||||
Attachment? get ogAttachment =>
|
||||
attachments.firstWhereOrNull((it) => it.id == _ogAttachment?.id);
|
||||
|
||||
/// Sets the og attachment in the message.
|
||||
void setOGAttachment(Attachment attachment) {
|
||||
attachments = [...attachments]
|
||||
..remove(_ogAttachment)
|
||||
..insert(0, attachment);
|
||||
_ogAttachment = attachment;
|
||||
}
|
||||
|
||||
/// Removes the og attachment.
|
||||
void clearOGAttachment() {
|
||||
attachments = [...attachments]..remove(_ogAttachment);
|
||||
_ogAttachment = null;
|
||||
}
|
||||
|
||||
/// Returns the list of mentioned users in the message.
|
||||
List<User> get mentionedUsers => value.mentionedUsers;
|
||||
|
||||
@@ -220,9 +257,8 @@ class MessageInputController extends ValueNotifier<Message> {
|
||||
/// Sets the [value] to the initial [Message] value.
|
||||
void reset({bool resetId = true}) {
|
||||
if (resetId) {
|
||||
_initialMessage = _initialMessage.copyWith(
|
||||
id: const Uuid().v4(),
|
||||
);
|
||||
final newId = const Uuid().v4();
|
||||
_initialMessage = _initialMessage.copyWith(id: newId);
|
||||
}
|
||||
value = _initialMessage;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MessageTextFieldController extends TextEditingController {
|
||||
MessageTextFieldController({
|
||||
String? text,
|
||||
this.textPatternStyle,
|
||||
}) : super(text: text);
|
||||
|
||||
MessageTextFieldController.fromValue(
|
||||
TextEditingValue? value, {
|
||||
this.textPatternStyle,
|
||||
}) : super.fromValue(value);
|
||||
|
||||
final Map<RegExp, TextStyle>? textPatternStyle;
|
||||
|
||||
///
|
||||
@override
|
||||
TextSpan buildTextSpan({
|
||||
required BuildContext context,
|
||||
TextStyle? style,
|
||||
required bool withComposing,
|
||||
}) {
|
||||
final pattern = textPatternStyle;
|
||||
if (pattern == null) {
|
||||
return super.buildTextSpan(
|
||||
context: context,
|
||||
style: style,
|
||||
withComposing: withComposing,
|
||||
);
|
||||
}
|
||||
|
||||
return TextSpan(text: text, style: style).splitMapJoin(
|
||||
RegExp(pattern.keys.map((it) => it.pattern).join('|')),
|
||||
onMatch: (match) {
|
||||
final text = match[0]!;
|
||||
final key = pattern.keys.firstWhere((it) => it.hasMatch(text));
|
||||
return TextSpan(
|
||||
text: text,
|
||||
style: pattern[key],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension _TextSpanX on TextSpan {
|
||||
TextSpan splitMapJoin(
|
||||
Pattern pattern, {
|
||||
TextSpan Function(Match)? onMatch,
|
||||
TextSpan Function(TextSpan)? onNonMatch,
|
||||
}) {
|
||||
final children = <TextSpan>[];
|
||||
|
||||
toPlainText().splitMapJoin(
|
||||
pattern,
|
||||
onMatch: (match) {
|
||||
final span = TextSpan(text: match.group(0), style: style);
|
||||
final updated = onMatch?.call(match);
|
||||
children.add(updated ?? span);
|
||||
return span.toPlainText();
|
||||
},
|
||||
onNonMatch: (text) {
|
||||
final span = TextSpan(text: text, style: style);
|
||||
final updatedSpan = onNonMatch?.call(span);
|
||||
children.add(updatedSpan ?? span);
|
||||
return span.toPlainText();
|
||||
},
|
||||
);
|
||||
|
||||
return TextSpan(style: style, children: children);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user