Added an option to pass InlineSpan builders for full control of message input

This commit is contained in:
Ayush Shekhar
2022-04-05 13:46:57 +05:30
parent 5e820c9ff9
commit 67c094b12b
2 changed files with 21 additions and 24 deletions
@@ -19,37 +19,37 @@ class MessageInputController extends ValueNotifier<Message> {
/// message. /// message.
factory MessageInputController({ factory MessageInputController({
Message? message, Message? message,
Map<RegExp, TextStyleBuilder>? textPatternStyle, Map<RegExp, InlineSpanBuilder>? textPatternSpan,
}) => }) =>
MessageInputController._( MessageInputController._(
initialMessage: message ?? Message(), initialMessage: message ?? Message(),
textPatternStyle: textPatternStyle, textPatternSpan: textPatternSpan,
); );
/// Creates a controller for an editable text field from an initial [text]. /// Creates a controller for an editable text field from an initial [text].
factory MessageInputController.fromText( factory MessageInputController.fromText(
String? text, { String? text, {
Map<RegExp, TextStyleBuilder>? textPatternStyle, Map<RegExp, InlineSpanBuilder>? textPatternSpan,
}) => }) =>
MessageInputController._( MessageInputController._(
initialMessage: Message(text: text), initialMessage: Message(text: text),
textPatternStyle: textPatternStyle, textPatternSpan: textPatternSpan,
); );
/// Creates a controller for an editable text field from initial /// Creates a controller for an editable text field from initial
/// [attachments]. /// [attachments].
factory MessageInputController.fromAttachments( factory MessageInputController.fromAttachments(
List<Attachment> attachments, { List<Attachment> attachments, {
Map<RegExp, TextStyleBuilder>? textPatternStyle, Map<RegExp, InlineSpanBuilder>? textPatternSpan,
}) => }) =>
MessageInputController._( MessageInputController._(
initialMessage: Message(attachments: attachments), initialMessage: Message(attachments: attachments),
textPatternStyle: textPatternStyle, textPatternSpan: textPatternSpan,
); );
MessageInputController._({ MessageInputController._({
required Message initialMessage, required Message initialMessage,
Map<RegExp, TextStyleBuilder>? textPatternStyle, Map<RegExp, InlineSpanBuilder>? textPatternSpan,
}) : _textEditingController = MessageTextFieldController.fromValue( }) : _textEditingController = MessageTextFieldController.fromValue(
initialMessage.text == null initialMessage.text == null
? const TextEditingValue() ? const TextEditingValue()
@@ -57,7 +57,7 @@ class MessageInputController extends ValueNotifier<Message> {
text: initialMessage.text!, text: initialMessage.text!,
composing: TextRange.collapsed(initialMessage.text!.length), composing: TextRange.collapsed(initialMessage.text!.length),
), ),
textPatternStyle: textPatternStyle, textPatternSpan: textPatternSpan,
), ),
_initialMessage = initialMessage, _initialMessage = initialMessage,
super(initialMessage) { super(initialMessage) {
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
/// A function that takes a [BuildContext] and returns a [TextStyle]. /// A function that takes a [BuildContext] and returns an [InlineSpan].
typedef TextStyleBuilder = TextStyle? Function( typedef InlineSpanBuilder = InlineSpan Function(
BuildContext context, BuildContext context,
String text, String text,
); );
@@ -11,17 +11,17 @@ class MessageTextFieldController extends TextEditingController {
/// Returns a new MessageTextFieldController /// Returns a new MessageTextFieldController
MessageTextFieldController({ MessageTextFieldController({
String? text, String? text,
this.textPatternStyle, this.textPatternSpan,
}) : super(text: text); }) : super(text: text);
/// Returns a new MessageTextFieldController with the given text [value]. /// Returns a new MessageTextFieldController with the given text [value].
MessageTextFieldController.fromValue( MessageTextFieldController.fromValue(
TextEditingValue? value, { TextEditingValue? value, {
this.textPatternStyle, this.textPatternSpan,
}) : super.fromValue(value); }) : super.fromValue(value);
/// A map of style to apply to the text matching the RegExp patterns. /// A map of style to apply to the text matching the RegExp patterns.
final Map<RegExp, TextStyleBuilder>? textPatternStyle; final Map<RegExp, InlineSpanBuilder>? textPatternSpan;
/// Builds a [TextSpan] from the current text, /// Builds a [TextSpan] from the current text,
/// highlighting the matches for [textPatternStyle]. /// highlighting the matches for [textPatternStyle].
@@ -31,7 +31,7 @@ class MessageTextFieldController extends TextEditingController {
TextStyle? style, TextStyle? style,
required bool withComposing, required bool withComposing,
}) { }) {
final pattern = textPatternStyle; final pattern = textPatternSpan;
if (pattern == null || pattern.isEmpty) { if (pattern == null || pattern.isEmpty) {
return super.buildTextSpan( return super.buildTextSpan(
context: context, context: context,
@@ -45,13 +45,10 @@ class MessageTextFieldController extends TextEditingController {
onMatch: (match) { onMatch: (match) {
final text = match[0]!; final text = match[0]!;
final key = pattern.keys.firstWhere((it) => it.hasMatch(text)); final key = pattern.keys.firstWhere((it) => it.hasMatch(text));
return TextSpan( return pattern[key]?.call(context, text) ??
text: text, TextSpan(
style: pattern[key]?.call( text: text,
context, );
text,
),
);
}, },
); );
} }
@@ -60,10 +57,10 @@ class MessageTextFieldController extends TextEditingController {
extension _TextSpanX on TextSpan { extension _TextSpanX on TextSpan {
TextSpan splitMapJoin( TextSpan splitMapJoin(
Pattern pattern, { Pattern pattern, {
TextSpan Function(Match)? onMatch, InlineSpan Function(Match)? onMatch,
TextSpan Function(TextSpan)? onNonMatch, InlineSpan Function(InlineSpan)? onNonMatch,
}) { }) {
final children = <TextSpan>[]; final children = <InlineSpan>[];
toPlainText().splitMapJoin( toPlainText().splitMapJoin(
pattern, pattern,