StreamMessageInputController
This commit is contained in:
@@ -1,90 +0,0 @@
|
|||||||
---
|
|
||||||
id: channels_bloc
|
|
||||||
sidebar_position: 7
|
|
||||||
title: ChannelsBloc
|
|
||||||
---
|
|
||||||
|
|
||||||
A Widget Dedicated To The Management Of A Channel List With Pagination.
|
|
||||||
|
|
||||||
### Background
|
|
||||||
|
|
||||||
Most widgets in the Core SDK are focused on fetching a particular type of object from Stream Chat - channels,
|
|
||||||
messages, users, etc. The BLoC widgets bundle up the base functions used to fetch data as well as the current
|
|
||||||
data fetched by the respective functions. Furthermore, the Core widgets use this BLoC to fetch new or
|
|
||||||
existing data and build UI based on it.
|
|
||||||
|
|
||||||
All Core and UI widgets which focus on fetching a list of objects need to have their respective functions
|
|
||||||
above them in the widget tree. The ChannelListCore and ChannelListView require the ChannelsBloc
|
|
||||||
above them in the widget hierarchy without which they will fail.
|
|
||||||
|
|
||||||
### Understanding The Widget
|
|
||||||
|
|
||||||
`ChannelsBloc` is used together with `ChannelListCore` to manage a list of
|
|
||||||
Channels with pagination, re-ordering, querying and other operations
|
|
||||||
associated with Channels.
|
|
||||||
|
|
||||||
`ChannelsBloc` can be accessed at anytime by using the static `.of` method
|
|
||||||
using Flutter's `BuildContext`.
|
|
||||||
|
|
||||||
```dart
|
|
||||||
var _channelsBloc = ChannelsBloc.of(context);
|
|
||||||
```
|
|
||||||
|
|
||||||
The `ChannelsBloc` widget encapsulates common functionality related to channel lists such as fetching
|
|
||||||
the existing channels and querying new channels and also supplies them down the widget tree.
|
|
||||||
|
|
||||||
The widget is required for the respective core widget (`ChannelListCore`) to fetch channels and hence
|
|
||||||
must be above the core widget in the tree.
|
|
||||||
|
|
||||||
Here is a basic implementation of `ChannelsBloc`:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
ChannelsBloc(
|
|
||||||
child: // Further Widget Tree
|
|
||||||
),
|
|
||||||
```
|
|
||||||
|
|
||||||
The `ChannelsBloc` widget allows three customisations:
|
|
||||||
|
|
||||||
#### Lock Channels Order
|
|
||||||
|
|
||||||
ChannelsBloc may change the order of channels when new messages arrive. To lock this order, we can
|
|
||||||
set the `lockChannelsOrder` property to true.
|
|
||||||
|
|
||||||
```dart
|
|
||||||
ChannelsBloc(
|
|
||||||
lockChannelsOrder: true,
|
|
||||||
child: // Further Widget Tree
|
|
||||||
),
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Set custom channel order
|
|
||||||
|
|
||||||
We can decide the order of the channels in the list by supplying a comparator to the `channelsComparator`
|
|
||||||
parameter:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
ChannelsBloc(
|
|
||||||
channelsComparator: (a, b) {
|
|
||||||
return a.createdAt!.millisecondsSinceEpoch >
|
|
||||||
b.createdAt!.millisecondsSinceEpoch
|
|
||||||
? 1
|
|
||||||
: -1;
|
|
||||||
},
|
|
||||||
child: // Further Widget Tree
|
|
||||||
),
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Decide if channel should be added on new message event
|
|
||||||
|
|
||||||
When a new message arrives, a `message.new` event is received. We can decide if we want to add the channel
|
|
||||||
to the list using the `shouldAddChannel` parameter which is a callback supplying the event data:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
ChannelsBloc(
|
|
||||||
shouldAddChannel: (event) {
|
|
||||||
return event.message!.extraData['priority'] == '1';
|
|
||||||
},
|
|
||||||
child: // Further Widget Tree
|
|
||||||
),
|
|
||||||
```
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
---
|
|
||||||
id: message_search_list_block
|
|
||||||
sidebar_position: 8
|
|
||||||
title: MessageSearchListBloc
|
|
||||||
---
|
|
||||||
|
|
||||||
A Widget Used To Manage A List Of Messages With Pagination.
|
|
||||||
|
|
||||||
### Background
|
|
||||||
|
|
||||||
Most widgets in the Core SDK are focused on fetching a particular type of object from Stream Chat - channels,
|
|
||||||
messages, users etc. The BLoC widgets bundle up the base functions used to fetch data as well as the current
|
|
||||||
data fetched by the respective functions. Furthermore, the Core widgets use this BLoC to fetch new or
|
|
||||||
existing data and build UI based on it.
|
|
||||||
|
|
||||||
All Core and UI widgets which focus on fetching a list of objects need to have their respective functions
|
|
||||||
above them in the widget tree. The MessageSearchListCore and MessageSearchListView require the
|
|
||||||
MessageSearchListCore above them in the widget hierarchy without which they will fail.
|
|
||||||
|
|
||||||
### Understanding The Widget
|
|
||||||
|
|
||||||
This class can be used to load messages, perform queries, etc.
|
|
||||||
|
|
||||||
`MessageSearchBloc` can be accessed at anytime by using the static `.of` method
|
|
||||||
using Flutter's BuildContext.
|
|
||||||
|
|
||||||
```dart
|
|
||||||
var _searchBloc = MessageSearchBloc.of(context);
|
|
||||||
```
|
|
||||||
|
|
||||||
The `MessageSearchBloc` widget encapsulates common functionality related to searching for messages
|
|
||||||
across channels and also supplies them down the widget tree.
|
|
||||||
|
|
||||||
Here is a basic implementation of `ChannelsBloc`:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
MessageSearchBloc(
|
|
||||||
child: // Further Widget Tree
|
|
||||||
),
|
|
||||||
```
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
---
|
|
||||||
id: message_search_list_core
|
|
||||||
sidebar_position: 6
|
|
||||||
title: MessageSearchListCore
|
|
||||||
---
|
|
||||||
|
|
||||||
A Widget For Displaying Message Searches
|
|
||||||
|
|
||||||
### Background
|
|
||||||
|
|
||||||
The UI SDK of Stream Chat supplies a `MessageSearchListView` class that builds a list of channels fetching
|
|
||||||
according to the filters and sort order given. However, in some cases, implementing novel UI is necessary
|
|
||||||
that cannot be done using the customization approaches given in the widget.
|
|
||||||
|
|
||||||
To do this, we extracted the logic required for fetching channels into a 'Core' widget - a widget that
|
|
||||||
fetches channels in the expected way via the usual params but does not supply any UI and instead
|
|
||||||
exposes builders to build the UI in situations such as loading, empty data, errors, and on data received.
|
|
||||||
|
|
||||||
### Basic Example
|
|
||||||
|
|
||||||
`MessageSearchListCore` is a simplified class that allows searching for
|
|
||||||
messages across channels while exposing UI builders.
|
|
||||||
A `MessageSearchListController` is used to load and paginate data.
|
|
||||||
|
|
||||||
```dart
|
|
||||||
class MessageSearchPage extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
body: MessageSearchListCore(
|
|
||||||
messageQuery: _messageFilter,
|
|
||||||
filters: _channelsFilter,
|
|
||||||
limit: 20,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Make sure to have a `MessageSearchBloc` ancestor in order to provide the
|
|
||||||
information about the messages.
|
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
---
|
||||||
|
id: stream_message_input_controller
|
||||||
|
sidebar_position: 4
|
||||||
|
title: StreamMessageInputController
|
||||||
|
---
|
||||||
|
|
||||||
|
A Widget For Controlling A Message Input
|
||||||
|
|
||||||
|
### Background
|
||||||
|
|
||||||
|
The `StreamMessageInputController` is a controller class that embed the business logic to compose a message.
|
||||||
|
`StreamMessageInputController` is a parameter of the `StreamMessageInput` widget.
|
||||||
|
Check the [`StreamMessageInput` documentation](../stream_chat_flutter/stream_message_input.mdx) to read more about that.
|
||||||
|
|
||||||
|
### Basic Example
|
||||||
|
|
||||||
|
Building a custom message input is a common task. Here is an example of how to use the `StreamMessageInputController` to build a simple custom message input widget.
|
||||||
|
|
||||||
|
First of all we should create an instance of the `StreamMessageInputController`.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class MessageScreenState extends State<MessageScreen> {
|
||||||
|
final StreamMessageInputController messageInputController = StreamMessageInputController();
|
||||||
|
```
|
||||||
|
|
||||||
|
Make sure you call `messageInputController.dispose()` when the controller is no longer required.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
messageInputController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `StreamMessageInputController` is basically a `ValueNotifier` that notifies you when the message being composed has changed.
|
||||||
|
You can use a `ValueListenableBuilder` to build your UI depending on the latest message.
|
||||||
|
For a very simple message input you could even pass the `messageInputController.textEditingController` to your `TextField` and set the `onChanged` callback.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
...
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
controller: messageInputController.textEditingController,
|
||||||
|
onChanged: (s) => messageInputController.text = s,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: 'Enter your message',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Material(
|
||||||
|
type: MaterialType.circle,
|
||||||
|
color: Colors.blue,
|
||||||
|
clipBehavior: Clip.hardEdge,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
if (messageInputController.message.text?.isNotEmpty ==
|
||||||
|
true) {
|
||||||
|
await channel.sendMessage(
|
||||||
|
messageInputController.message,
|
||||||
|
);
|
||||||
|
messageInputController.clear();
|
||||||
|
if (mounted) {
|
||||||
|
_updateList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: const Padding(
|
||||||
|
padding: EdgeInsets.all(8),
|
||||||
|
child: Center(
|
||||||
|
child: Icon(
|
||||||
|
Icons.send,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
...
|
||||||
|
```
|
||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
id: stream_message_search_list_controller
|
id: stream_message_search_list_controller
|
||||||
sidebar_position: 5
|
sidebar_position: 6
|
||||||
title: StreamMessageSearchListController
|
title: StreamMessageSearchListController
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ First of all we should create an instance of the `StreamMessageSearchListControl
|
|||||||
You can also add a `Filter`, a list of `SortOption`s and other pagination-related parameters.
|
You can also add a `Filter`, a list of `SortOption`s and other pagination-related parameters.
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
class SearchListPage extends State<HomeScreen> {
|
class SearchListPageState extends State<SearchListPage> {
|
||||||
/// Controller used for loading more data and controlling pagination in
|
/// Controller used for loading more data and controlling pagination in
|
||||||
/// [StreamMessageSearchListController].
|
/// [StreamMessageSearchListController].
|
||||||
late final messageSearchListController = StreamMessageSearchListController(
|
late final messageSearchListController = StreamMessageSearchListController(
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ First of all we should create an instance of the `StreamUserListController` and
|
|||||||
You can also add a `Filter`, a list of `SortOption`s and other pagination-related parameters.
|
You can also add a `Filter`, a list of `SortOption`s and other pagination-related parameters.
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
class UserListPageState extends State<HomeScreen> {
|
class UserListPageState extends State<UserListPage> {
|
||||||
/// Controller used for loading more data and controlling pagination in
|
/// Controller used for loading more data and controlling pagination in
|
||||||
/// [StreamUserListController].
|
/// [StreamUserListController].
|
||||||
late final userListController = StreamUserListController(
|
late final userListController = StreamUserListController(
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
---
|
|
||||||
id: user_list_core
|
|
||||||
sidebar_position: 10
|
|
||||||
title: UserListCore
|
|
||||||
---
|
|
||||||
|
|
||||||
A Widget For Building A List Of Users
|
|
||||||
|
|
||||||
### Background
|
|
||||||
|
|
||||||
The UI SDK of Stream Chat supplies a `UserListView` class that builds a list of channels fetching
|
|
||||||
according to the filters and sort order given. However, in some cases, implementing novel UI is necessary
|
|
||||||
that cannot be done using the customization approaches given in the widget.
|
|
||||||
|
|
||||||
To do this, we extracted the logic required for fetching channels into a 'Core' widget - a widget that
|
|
||||||
fetches channels in the expected way via the usual params but does not supply any UI and instead
|
|
||||||
exposes builders to build the UI in situations such as loading, empty data, errors, and on data received.
|
|
||||||
|
|
||||||
### Basic Example
|
|
||||||
|
|
||||||
`UserListCore` is a simplified class that allows fetching users while
|
|
||||||
exposing UI builders.
|
|
||||||
A `UserListController` is used to load and paginate data.
|
|
||||||
|
|
||||||
```dart
|
|
||||||
class UsersListPage extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
body: UsersListCore(
|
|
||||||
sort: [SortOption('last_active')],
|
|
||||||
pagination: PaginationParams(
|
|
||||||
limit: 20,
|
|
||||||
),
|
|
||||||
errorBuilder: (err) {
|
|
||||||
return Center(
|
|
||||||
child: Text('An error has occured'),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
emptyBuilder: (context) {
|
|
||||||
return Center(
|
|
||||||
child: Text('Nothing here...'),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
emptyBuilder: (context) {
|
|
||||||
return Center(
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
listBuilder: (context, list) {
|
|
||||||
return UsersPage(list);
|
|
||||||
}
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`UsersBloc` must be the ancestor of this widget. This is necessary since
|
|
||||||
`UserListCore` depends on functionality contained within `UsersBloc`.
|
|
||||||
|
|
||||||
The parameters `listBuilder`, `loadingBuilder`, `emptyBuilder` and
|
|
||||||
`errorBuilder` must all be supplied and not null.
|
|
||||||
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
---
|
|
||||||
id: users_bloc
|
|
||||||
sidebar_position: 9
|
|
||||||
title: UsersBloc
|
|
||||||
---
|
|
||||||
|
|
||||||
A Widget Dedicated To The Management Of A Users List With Pagination.
|
|
||||||
|
|
||||||
### Background
|
|
||||||
|
|
||||||
Most widgets in the Core SDK are focused on fetching a particular type of object from Stream Chat - channels,
|
|
||||||
messages, users, etc. The BLoC widgets bundle up the base functions used to fetch data as well as the current
|
|
||||||
data fetched by the respective functions. Furthermore, the Core widgets use this BLoC to fetch new or
|
|
||||||
existing data and build UI based on it.
|
|
||||||
|
|
||||||
All Core and UI widgets which focus on fetching a list of objects need to have their respective functions
|
|
||||||
above them in the widget tree. The UserListCore and UserListView require the UserListCore
|
|
||||||
above them in the widget hierarchy without which they will fail.
|
|
||||||
|
|
||||||
### Understanding The Widget
|
|
||||||
|
|
||||||
`UsersBloc` can be accessed at anytime by using the static `.of` method
|
|
||||||
using Flutter's `BuildContext`.
|
|
||||||
|
|
||||||
```dart
|
|
||||||
var _userBloc_ = UsersBloc.of(context);
|
|
||||||
```
|
|
||||||
|
|
||||||
The `UsersBloc` widget encapsulates common functionality related to user lists and also supplies them down the widget tree.
|
|
||||||
|
|
||||||
Here is a basic implementation of `UsersBloc`:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
UsersBloc(
|
|
||||||
child: // Further Widget Tree
|
|
||||||
),
|
|
||||||
```
|
|
||||||
@@ -21,6 +21,6 @@
|
|||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>MinimumOSVersion</key>
|
<key>MinimumOSVersion</key>
|
||||||
<string>8.0</string>
|
<string>9.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -139,6 +139,7 @@
|
|||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
|
EDC4CAB19281E65D2B18E888 /* [CP] Embed Pods Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -155,7 +156,7 @@
|
|||||||
97C146E61CF9000F007C117D /* Project object */ = {
|
97C146E61CF9000F007C117D /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 1020;
|
LastUpgradeCheck = 1300;
|
||||||
ORGANIZATIONNAME = "";
|
ORGANIZATIONNAME = "";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
97C146ED1CF9000F007C117D = {
|
97C146ED1CF9000F007C117D = {
|
||||||
@@ -247,6 +248,23 @@
|
|||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||||
};
|
};
|
||||||
|
EDC4CAB19281E65D2B18E888 /* [CP] Embed Pods Frameworks */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
|||||||
+1
-1
@@ -2,6 +2,6 @@
|
|||||||
<Workspace
|
<Workspace
|
||||||
version = "1.0">
|
version = "1.0">
|
||||||
<FileRef
|
<FileRef
|
||||||
location = "group:Runner.xcodeproj">
|
location = "self:">
|
||||||
</FileRef>
|
</FileRef>
|
||||||
</Workspace>
|
</Workspace>
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1020"
|
LastUpgradeVersion = "1300"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
|||||||
@@ -205,20 +205,20 @@ class MessageScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MessageScreenState extends State<MessageScreen> {
|
class _MessageScreenState extends State<MessageScreen> {
|
||||||
late final TextEditingController _controller;
|
final StreamMessageInputController messageInputController =
|
||||||
|
StreamMessageInputController();
|
||||||
late final ScrollController _scrollController;
|
late final ScrollController _scrollController;
|
||||||
final messageListController = MessageListController();
|
final messageListController = MessageListController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_controller = TextEditingController();
|
|
||||||
_scrollController = ScrollController();
|
_scrollController = ScrollController();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_controller.dispose();
|
messageInputController.dispose();
|
||||||
_scrollController.dispose();
|
_scrollController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
@@ -319,7 +319,8 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: _controller,
|
controller: messageInputController.textEditingController,
|
||||||
|
onChanged: (s) => messageInputController.text = s,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
hintText: 'Enter your message',
|
hintText: 'Enter your message',
|
||||||
),
|
),
|
||||||
@@ -331,12 +332,13 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
if (_controller.value.text.isNotEmpty) {
|
if (messageInputController.message.text?.isNotEmpty ==
|
||||||
|
true) {
|
||||||
await channel.sendMessage(
|
await channel.sendMessage(
|
||||||
Message(text: _controller.value.text),
|
messageInputController.message,
|
||||||
);
|
);
|
||||||
|
messageInputController.clear();
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
_controller.clear();
|
|
||||||
_updateList();
|
_updateList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user