add actions parameter to messageinput
This commit is contained in:
+41
-20
@@ -18,6 +18,11 @@ import 'stream_channel.dart';
|
|||||||
|
|
||||||
typedef FileUploader = Future<String> Function(File, Channel);
|
typedef FileUploader = Future<String> Function(File, Channel);
|
||||||
|
|
||||||
|
enum ActionsLocation {
|
||||||
|
LEFT,
|
||||||
|
RIGHT,
|
||||||
|
}
|
||||||
|
|
||||||
/// Inactive state
|
/// Inactive state
|
||||||
/// 
|
/// 
|
||||||
/// 
|
/// 
|
||||||
@@ -73,6 +78,9 @@ class MessageInput extends StatefulWidget {
|
|||||||
this.doImageUploadRequest,
|
this.doImageUploadRequest,
|
||||||
this.doFileUploadRequest,
|
this.doFileUploadRequest,
|
||||||
this.initialMessage,
|
this.initialMessage,
|
||||||
|
this.textEditingController,
|
||||||
|
this.actions,
|
||||||
|
this.actionsLocation = ActionsLocation.LEFT,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// Message to edit
|
/// Message to edit
|
||||||
@@ -102,6 +110,15 @@ class MessageInput extends StatefulWidget {
|
|||||||
/// Override file upload request
|
/// Override file upload request
|
||||||
final FileUploader doFileUploadRequest;
|
final FileUploader doFileUploadRequest;
|
||||||
|
|
||||||
|
/// The text controller of the TextField
|
||||||
|
final TextEditingController textEditingController;
|
||||||
|
|
||||||
|
/// List of action widgets
|
||||||
|
final List<Widget> actions;
|
||||||
|
|
||||||
|
/// The location of the custom actions
|
||||||
|
final ActionsLocation actionsLocation;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MessageInputState createState() => _MessageInputState(
|
_MessageInputState createState() => _MessageInputState(
|
||||||
doFileUploadRequest: doFileUploadRequest,
|
doFileUploadRequest: doFileUploadRequest,
|
||||||
@@ -116,7 +133,7 @@ class _MessageInputState extends State<MessageInput> {
|
|||||||
FileUploader doImageUploadRequest;
|
FileUploader doImageUploadRequest;
|
||||||
FileUploader doFileUploadRequest;
|
FileUploader doFileUploadRequest;
|
||||||
|
|
||||||
TextEditingController _textController;
|
TextEditingController textEditingController;
|
||||||
bool _inputEnabled = true;
|
bool _inputEnabled = true;
|
||||||
bool _messageIsPresent = false;
|
bool _messageIsPresent = false;
|
||||||
bool _typingStarted = false;
|
bool _typingStarted = false;
|
||||||
@@ -165,8 +182,12 @@ class _MessageInputState extends State<MessageInput> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
if (!widget.disableAttachments) _buildAttachmentButton(),
|
if (!widget.disableAttachments) _buildAttachmentButton(),
|
||||||
|
if (widget.actionsLocation == ActionsLocation.LEFT)
|
||||||
|
...widget.actions ?? [],
|
||||||
_buildTextInput(context),
|
_buildTextInput(context),
|
||||||
_animateSendButton(context),
|
_animateSendButton(context),
|
||||||
|
if (widget.actionsLocation == ActionsLocation.RIGHT)
|
||||||
|
...widget.actions ?? [],
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -197,7 +218,7 @@ class _MessageInputState extends State<MessageInput> {
|
|||||||
_sendMessage(context);
|
_sendMessage(context);
|
||||||
},
|
},
|
||||||
keyboardType: widget.keyboardType,
|
keyboardType: widget.keyboardType,
|
||||||
controller: _textController,
|
controller: textEditingController,
|
||||||
focusNode: _focusNode,
|
focusNode: _focusNode,
|
||||||
onChanged: (s) {
|
onChanged: (s) {
|
||||||
StreamChannel.of(context).channel.keyStroke();
|
StreamChannel.of(context).channel.keyStroke();
|
||||||
@@ -216,10 +237,10 @@ class _MessageInputState extends State<MessageInput> {
|
|||||||
Overlay.of(context).insert(_commandsOverlay);
|
Overlay.of(context).insert(_commandsOverlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_textController.selection.isCollapsed &&
|
if (textEditingController.selection.isCollapsed &&
|
||||||
(s[_textController.selection.start - 1] == '@' ||
|
(s[textEditingController.selection.start - 1] == '@' ||
|
||||||
_textController.text
|
textEditingController.text
|
||||||
.substring(0, _textController.selection.start)
|
.substring(0, textEditingController.selection.start)
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.last
|
.last
|
||||||
.contains('@'))) {
|
.contains('@'))) {
|
||||||
@@ -279,7 +300,7 @@ class _MessageInputState extends State<MessageInput> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OverlayEntry _buildCommandsOverlayEntry() {
|
OverlayEntry _buildCommandsOverlayEntry() {
|
||||||
final text = _textController.text;
|
final text = textEditingController.text;
|
||||||
final commands = StreamChannel.of(context)
|
final commands = StreamChannel.of(context)
|
||||||
.channel
|
.channel
|
||||||
.config
|
.config
|
||||||
@@ -344,8 +365,8 @@ class _MessageInputState extends State<MessageInput> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OverlayEntry _buildMentionsOverlayEntry() {
|
OverlayEntry _buildMentionsOverlayEntry() {
|
||||||
final splits = _textController.text
|
final splits = textEditingController.text
|
||||||
.substring(0, _textController.value.selection.start)
|
.substring(0, textEditingController.value.selection.start)
|
||||||
.split('@');
|
.split('@');
|
||||||
final query = splits.last.toLowerCase();
|
final query = splits.last.toLowerCase();
|
||||||
|
|
||||||
@@ -391,10 +412,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('@');
|
||||||
|
|
||||||
_textController.value = TextEditingValue(
|
textEditingController.value = TextEditingValue(
|
||||||
text: rejoin +
|
text: rejoin +
|
||||||
_textController.text
|
textEditingController.text.substring(
|
||||||
.substring(_textController.selection.start),
|
textEditingController.selection.start),
|
||||||
selection: TextSelection.collapsed(
|
selection: TextSelection.collapsed(
|
||||||
offset: rejoin.length,
|
offset: rejoin.length,
|
||||||
),
|
),
|
||||||
@@ -413,7 +434,7 @@ class _MessageInputState extends State<MessageInput> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _setCommand(Command c) {
|
void _setCommand(Command c) {
|
||||||
_textController.value = TextEditingValue(
|
textEditingController.value = TextEditingValue(
|
||||||
text: '/${c.name} ',
|
text: '/${c.name} ',
|
||||||
selection: TextSelection.collapsed(
|
selection: TextSelection.collapsed(
|
||||||
offset: c.name.length + 2,
|
offset: c.name.length + 2,
|
||||||
@@ -726,14 +747,14 @@ class _MessageInputState extends State<MessageInput> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _sendMessage(BuildContext context) {
|
void _sendMessage(BuildContext context) {
|
||||||
final text = _textController.text.trim();
|
final text = textEditingController.text.trim();
|
||||||
if (text.isEmpty && _attachments.isEmpty) {
|
if (text.isEmpty && _attachments.isEmpty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final attachments = List<_SendingAttachment>.from(_attachments);
|
final attachments = List<_SendingAttachment>.from(_attachments);
|
||||||
|
|
||||||
_textController.clear();
|
textEditingController.clear();
|
||||||
_attachments.clear();
|
_attachments.clear();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -821,7 +842,7 @@ class _MessageInputState extends State<MessageInput> {
|
|||||||
_keyboardListener = KeyboardVisibility.onChange.listen((visible) {
|
_keyboardListener = KeyboardVisibility.onChange.listen((visible) {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
if (_commandsOverlay != null) {
|
if (_commandsOverlay != null) {
|
||||||
if (_textController.text.startsWith('/')) {
|
if (textEditingController.text.startsWith('/')) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
_commandsOverlay = _buildCommandsOverlayEntry();
|
_commandsOverlay = _buildCommandsOverlayEntry();
|
||||||
Overlay.of(context).insert(_commandsOverlay);
|
Overlay.of(context).insert(_commandsOverlay);
|
||||||
@@ -830,7 +851,7 @@ class _MessageInputState extends State<MessageInput> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_mentionsOverlay != null) {
|
if (_mentionsOverlay != null) {
|
||||||
if (_textController.text.contains('@')) {
|
if (textEditingController.text.contains('@')) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
_mentionsOverlay = _buildCommandsOverlayEntry();
|
_mentionsOverlay = _buildCommandsOverlayEntry();
|
||||||
Overlay.of(context).insert(_mentionsOverlay);
|
Overlay.of(context).insert(_mentionsOverlay);
|
||||||
@@ -847,17 +868,17 @@ class _MessageInputState extends State<MessageInput> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
textEditingController =
|
||||||
|
widget.textEditingController ?? TextEditingController();
|
||||||
if (widget.editMessage != null) {
|
if (widget.editMessage != null) {
|
||||||
_parseExistingMessage(widget.editMessage);
|
_parseExistingMessage(widget.editMessage);
|
||||||
} else if (widget.initialMessage != null) {
|
} else if (widget.initialMessage != null) {
|
||||||
_parseExistingMessage(widget.initialMessage);
|
_parseExistingMessage(widget.initialMessage);
|
||||||
} else {
|
|
||||||
_textController = TextEditingController();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _parseExistingMessage(Message message) {
|
void _parseExistingMessage(Message message) {
|
||||||
_textController = TextEditingController(text: message.text);
|
textEditingController.text = message.text;
|
||||||
|
|
||||||
_typingStarted = true;
|
_typingStarted = true;
|
||||||
_messageIsPresent = true;
|
_messageIsPresent = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user