chore(ui): apply review changes, minor ui improvements
Signed-off-by: xsahil03x <[email protected]>
This commit is contained in:
@@ -326,19 +326,18 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
bool _sendAsDm = false;
|
bool _sendAsDm = false;
|
||||||
bool _openFilePickerSection = false;
|
bool _openFilePickerSection = false;
|
||||||
int _filePickerIndex = 0;
|
int _filePickerIndex = 0;
|
||||||
double _filePickerSize = _kMinMediaPickerSize;
|
|
||||||
final KeyboardVisibilityController _keyboardVisibilityController =
|
final _keyboardVisibilityController = KeyboardVisibilityController();
|
||||||
KeyboardVisibilityController();
|
|
||||||
|
|
||||||
/// The editing controller passed to the input TextField
|
/// The editing controller passed to the input TextField
|
||||||
late final TextEditingController _textEditingController;
|
late final TextEditingController textEditingController;
|
||||||
|
|
||||||
late StreamChatThemeData _streamChatTheme;
|
late StreamChatThemeData _streamChatTheme;
|
||||||
late MessageInputThemeData _messageInputTheme;
|
late MessageInputThemeData _messageInputTheme;
|
||||||
|
|
||||||
bool get _hasQuotedMessage => widget.quotedMessage != null;
|
bool get _hasQuotedMessage => widget.quotedMessage != null;
|
||||||
|
|
||||||
bool get _messageIsPresent => _textEditingController.text.trim().isNotEmpty;
|
bool get _messageIsPresent => textEditingController.text.trim().isNotEmpty;
|
||||||
late DateTime? _cooldownStartedAt;
|
late DateTime? _cooldownStartedAt;
|
||||||
int? _timeOut;
|
int? _timeOut;
|
||||||
|
|
||||||
@@ -356,19 +355,19 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
_keyboardListener =
|
_keyboardListener =
|
||||||
_keyboardVisibilityController.onChange.listen((visible) {
|
_keyboardVisibilityController.onChange.listen((visible) {
|
||||||
if (_focusNode.hasFocus) {
|
if (_focusNode.hasFocus) {
|
||||||
_onChanged(context, _textEditingController.text);
|
_onChanged(context, textEditingController.text);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_textEditingController =
|
textEditingController =
|
||||||
widget.textEditingController ?? TextEditingController();
|
widget.textEditingController ?? TextEditingController();
|
||||||
if (widget.editMessage != null || widget.initialMessage != null) {
|
if (widget.editMessage != null || widget.initialMessage != null) {
|
||||||
_parseExistingMessage(widget.editMessage ?? widget.initialMessage!);
|
_parseExistingMessage(widget.editMessage ?? widget.initialMessage!);
|
||||||
}
|
}
|
||||||
|
|
||||||
_textEditingController.addListener(() {
|
textEditingController.addListener(() {
|
||||||
_onChanged(context, _textEditingController.text);
|
_onChanged(context, textEditingController.text);
|
||||||
});
|
});
|
||||||
|
|
||||||
_focusNode.addListener(() {
|
_focusNode.addListener(() {
|
||||||
@@ -660,7 +659,7 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
maxLines: null,
|
maxLines: null,
|
||||||
onSubmitted: (_) => sendMessage(),
|
onSubmitted: (_) => sendMessage(),
|
||||||
keyboardType: widget.keyboardType,
|
keyboardType: widget.keyboardType,
|
||||||
controller: _textEditingController,
|
controller: textEditingController,
|
||||||
focusNode: _focusNode,
|
focusNode: _focusNode,
|
||||||
style: _messageInputTheme.inputTextStyle,
|
style: _messageInputTheme.inputTextStyle,
|
||||||
autofocus: widget.autofocus,
|
autofocus: widget.autofocus,
|
||||||
@@ -843,15 +842,15 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
|
|
||||||
void _checkEmoji(String s, BuildContext context) {
|
void _checkEmoji(String s, BuildContext context) {
|
||||||
if (s.isNotEmpty &&
|
if (s.isNotEmpty &&
|
||||||
_textEditingController.selection.baseOffset > 0 &&
|
textEditingController.selection.baseOffset > 0 &&
|
||||||
_textEditingController.text
|
textEditingController.text
|
||||||
.substring(
|
.substring(
|
||||||
0,
|
0,
|
||||||
_textEditingController.selection.baseOffset,
|
textEditingController.selection.baseOffset,
|
||||||
)
|
)
|
||||||
.contains(':')) {
|
.contains(':')) {
|
||||||
final textToSelection = _textEditingController.text
|
final textToSelection = textEditingController.text
|
||||||
.substring(0, _textEditingController.value.selection.start);
|
.substring(0, textEditingController.value.selection.start);
|
||||||
final splits = textToSelection.split(':');
|
final splits = textToSelection.split(':');
|
||||||
final query = splits[splits.length - 2].toLowerCase();
|
final query = splits[splits.length - 2].toLowerCase();
|
||||||
final emoji = Emoji.byName(query);
|
final emoji = Emoji.byName(query);
|
||||||
@@ -870,9 +869,9 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
|
|
||||||
void _checkMentions(String s, BuildContext context) {
|
void _checkMentions(String s, BuildContext context) {
|
||||||
if (s.isNotEmpty &&
|
if (s.isNotEmpty &&
|
||||||
_textEditingController.selection.baseOffset > 0 &&
|
textEditingController.selection.baseOffset > 0 &&
|
||||||
_textEditingController.text
|
textEditingController.text
|
||||||
.substring(0, _textEditingController.selection.baseOffset)
|
.substring(0, textEditingController.selection.baseOffset)
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.last
|
.last
|
||||||
.contains('@')) {
|
.contains('@')) {
|
||||||
@@ -895,7 +894,7 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
|
|
||||||
if (matchedCommandsList.length == 1) {
|
if (matchedCommandsList.length == 1) {
|
||||||
_chosenCommand = matchedCommandsList[0];
|
_chosenCommand = matchedCommandsList[0];
|
||||||
_textEditingController.clear();
|
textEditingController.clear();
|
||||||
setState(() {
|
setState(() {
|
||||||
_commandEnabled = true;
|
_commandEnabled = true;
|
||||||
});
|
});
|
||||||
@@ -911,7 +910,7 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OverlayEntry? _buildCommandsOverlayEntry() {
|
OverlayEntry? _buildCommandsOverlayEntry() {
|
||||||
final text = _textEditingController.text.trimLeft();
|
final text = textEditingController.text.trimLeft();
|
||||||
final commands = StreamChannel.of(context)
|
final commands = StreamChannel.of(context)
|
||||||
.channel
|
.channel
|
||||||
.config
|
.config
|
||||||
@@ -1086,7 +1085,7 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
|
|
||||||
return AnimatedContainer(
|
return AnimatedContainer(
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
height: _openFilePickerSection ? _filePickerSize : 0,
|
height: _openFilePickerSection ? _kMinMediaPickerSize : 0,
|
||||||
child: Material(
|
child: Material(
|
||||||
color: _streamChatTheme.colorTheme.inputBg,
|
color: _streamChatTheme.colorTheme.inputBg,
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -1142,66 +1141,50 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
GestureDetector(
|
DecoratedBox(
|
||||||
onVerticalDragUpdate: (update) {
|
decoration: BoxDecoration(
|
||||||
setState(() {
|
color: _streamChatTheme.colorTheme.barsBg,
|
||||||
_filePickerSize = (_filePickerSize - update.delta.dy).clamp(
|
borderRadius: const BorderRadius.only(
|
||||||
_kMinMediaPickerSize,
|
topLeft: Radius.circular(16),
|
||||||
MediaQuery.of(context).size.height / 1.7,
|
topRight: Radius.circular(16),
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: DecoratedBox(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: _streamChatTheme.colorTheme.barsBg,
|
|
||||||
borderRadius: const BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(16),
|
|
||||||
topRight: Radius.circular(16),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: SizedBox(
|
),
|
||||||
width: double.infinity,
|
child: Center(
|
||||||
child: Center(
|
child: Padding(
|
||||||
child: Padding(
|
padding: const EdgeInsets.all(8),
|
||||||
padding: const EdgeInsets.all(8),
|
child: Container(
|
||||||
child: SizedBox(
|
width: 40,
|
||||||
width: 40,
|
height: 4,
|
||||||
height: 4,
|
decoration: BoxDecoration(
|
||||||
child: DecoratedBox(
|
color: _streamChatTheme.colorTheme.inputBg,
|
||||||
decoration: BoxDecoration(
|
borderRadius: BorderRadius.circular(4),
|
||||||
color: _streamChatTheme.colorTheme.inputBg,
|
|
||||||
borderRadius: BorderRadius.circular(4),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (_openFilePickerSection)
|
Expanded(
|
||||||
Expanded(
|
child: DecoratedBox(
|
||||||
child: DecoratedBox(
|
decoration: BoxDecoration(
|
||||||
decoration: BoxDecoration(
|
color: _streamChatTheme.colorTheme.barsBg,
|
||||||
color: _streamChatTheme.colorTheme.barsBg,
|
borderRadius: BorderRadius.circular(8),
|
||||||
borderRadius: BorderRadius.circular(8),
|
),
|
||||||
),
|
child: _PickerWidget(
|
||||||
child: _PickerWidget(
|
filePickerIndex: _filePickerIndex,
|
||||||
filePickerIndex: _filePickerIndex,
|
streamChatTheme: _streamChatTheme,
|
||||||
streamChatTheme: _streamChatTheme,
|
containsFile: _attachmentContainsFile,
|
||||||
containsFile: _attachmentContainsFile,
|
selectedMedias: _attachments.keys.toList(),
|
||||||
selectedMedias: _attachments.keys.toList(),
|
onAddMoreFilesClick: pickFile,
|
||||||
onAddMoreFilesClick: pickFile,
|
onMediaSelected: (media) {
|
||||||
onMediaSelected: (media) {
|
if (_attachments.containsKey(media.id)) {
|
||||||
if (_attachments.containsKey(media.id)) {
|
setState(() => _attachments.remove(media.id));
|
||||||
setState(() => _attachments.remove(media.id));
|
} else {
|
||||||
} else {
|
_addAssetAttachment(media);
|
||||||
_addAssetAttachment(media);
|
}
|
||||||
}
|
},
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1339,8 +1322,8 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OverlayEntry? _buildMentionsOverlayEntry() {
|
OverlayEntry? _buildMentionsOverlayEntry() {
|
||||||
final splits = _textEditingController.text
|
final splits = textEditingController.text
|
||||||
.substring(0, _textEditingController.value.selection.start)
|
.substring(0, textEditingController.value.selection.start)
|
||||||
.split('@');
|
.split('@');
|
||||||
final query = splits.last.toLowerCase();
|
final query = splits.last.toLowerCase();
|
||||||
|
|
||||||
@@ -1402,10 +1385,10 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
splits[splits.length - 1] = m.user!.name;
|
splits[splits.length - 1] = m.user!.name;
|
||||||
final rejoin = splits.join('@');
|
final rejoin = splits.join('@');
|
||||||
|
|
||||||
_textEditingController.value = TextEditingValue(
|
textEditingController.value = TextEditingValue(
|
||||||
text: rejoin +
|
text: rejoin +
|
||||||
_textEditingController.text.substring(
|
textEditingController.text.substring(
|
||||||
_textEditingController.selection.start),
|
textEditingController.selection.start),
|
||||||
selection: TextSelection.collapsed(
|
selection: TextSelection.collapsed(
|
||||||
offset: rejoin.length,
|
offset: rejoin.length,
|
||||||
),
|
),
|
||||||
@@ -1449,8 +1432,8 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OverlayEntry? _buildEmojiOverlay() {
|
OverlayEntry? _buildEmojiOverlay() {
|
||||||
final splits = _textEditingController.text
|
final splits = textEditingController.text
|
||||||
.substring(0, _textEditingController.value.selection.start)
|
.substring(0, textEditingController.value.selection.start)
|
||||||
.split(':');
|
.split(':');
|
||||||
final query = splits.last.toLowerCase();
|
final query = splits.last.toLowerCase();
|
||||||
|
|
||||||
@@ -1561,10 +1544,10 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
void _chooseEmoji(List<String> splits, Emoji emoji) {
|
void _chooseEmoji(List<String> splits, Emoji emoji) {
|
||||||
final rejoin = splits.sublist(0, splits.length - 1).join(':') + emoji.char!;
|
final rejoin = splits.sublist(0, splits.length - 1).join(':') + emoji.char!;
|
||||||
|
|
||||||
_textEditingController.value = TextEditingValue(
|
textEditingController.value = TextEditingValue(
|
||||||
text: rejoin +
|
text: rejoin +
|
||||||
_textEditingController.text
|
textEditingController.text
|
||||||
.substring(_textEditingController.selection.start),
|
.substring(textEditingController.selection.start),
|
||||||
selection: TextSelection.collapsed(
|
selection: TextSelection.collapsed(
|
||||||
offset: rejoin.length,
|
offset: rejoin.length,
|
||||||
),
|
),
|
||||||
@@ -1575,7 +1558,7 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _setCommand(Command c) {
|
void _setCommand(Command c) {
|
||||||
_textEditingController.clear();
|
textEditingController.clear();
|
||||||
setState(() {
|
setState(() {
|
||||||
_chosenCommand = c;
|
_chosenCommand = c;
|
||||||
_commandEnabled = true;
|
_commandEnabled = true;
|
||||||
@@ -1769,7 +1752,7 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildCommandButton(BuildContext context) {
|
Widget _buildCommandButton(BuildContext context) {
|
||||||
final s = _textEditingController.text.trim();
|
final s = textEditingController.text.trim();
|
||||||
final defaultButton = IconButton(
|
final defaultButton = IconButton(
|
||||||
icon: StreamSvgIcon.lightning(
|
icon: StreamSvgIcon.lightning(
|
||||||
color: s.isNotEmpty
|
color: s.isNotEmpty
|
||||||
@@ -1786,10 +1769,7 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
splashRadius: 24,
|
splashRadius: 24,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (_openFilePickerSection) {
|
if (_openFilePickerSection) {
|
||||||
setState(() {
|
setState(() => _openFilePickerSection = false);
|
||||||
_openFilePickerSection = false;
|
|
||||||
_filePickerSize = _kMinMediaPickerSize;
|
|
||||||
});
|
|
||||||
await Future.delayed(const Duration(milliseconds: 300));
|
await Future.delayed(const Duration(milliseconds: 300));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1835,10 +1815,7 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
_mentionsOverlay = null;
|
_mentionsOverlay = null;
|
||||||
|
|
||||||
if (_openFilePickerSection) {
|
if (_openFilePickerSection) {
|
||||||
setState(() {
|
setState(() => _openFilePickerSection = false);
|
||||||
_openFilePickerSection = false;
|
|
||||||
_filePickerSize = _kMinMediaPickerSize;
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
showAttachmentModal();
|
showAttachmentModal();
|
||||||
}
|
}
|
||||||
@@ -1930,6 +1907,14 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add an attachment to the sending message
|
||||||
|
/// Use this to add custom type attachments
|
||||||
|
///
|
||||||
|
/// Note: Only meant to be used from outside the state.
|
||||||
|
void addAttachment(Attachment attachment) {
|
||||||
|
setState(() => _addAttachments([attachment]));
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds an attachment to the [_attachments] map
|
/// Adds an attachment to the [_attachments] map
|
||||||
void _addAttachments(Iterable<Attachment> attachments) {
|
void _addAttachments(Iterable<Attachment> attachments) {
|
||||||
final limit = widget.attachmentLimit;
|
final limit = widget.attachmentLimit;
|
||||||
@@ -2110,7 +2095,7 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
|
|
||||||
/// Sends the current message
|
/// Sends the current message
|
||||||
Future<void> sendMessage() async {
|
Future<void> sendMessage() async {
|
||||||
var text = _textEditingController.text.trim();
|
var text = textEditingController.text.trim();
|
||||||
if (text.isEmpty && _attachments.isEmpty) {
|
if (text.isEmpty && _attachments.isEmpty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2123,7 +2108,7 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
|
|
||||||
final attachments = [..._attachments.values];
|
final attachments = [..._attachments.values];
|
||||||
|
|
||||||
_textEditingController.clear();
|
textEditingController.clear();
|
||||||
_attachments.clear();
|
_attachments.clear();
|
||||||
widget.onQuotedMessageCleared?.call();
|
widget.onQuotedMessageCleared?.call();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user