update lists
This commit is contained in:
@@ -264,6 +264,7 @@
|
||||
"${BUILT_PRODUCTS_DIR}/sqlite3/sqlite3.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/sqlite3_flutter_libs/sqlite3_flutter_libs.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/video_compress/video_compress.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/video_player_avfoundation/video_player_avfoundation.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/video_thumbnail/video_thumbnail.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/wakelock/wakelock.framework",
|
||||
@@ -292,6 +293,7 @@
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqlite3_flutter_libs.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_compress.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player_avfoundation.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_thumbnail.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/wakelock.framework",
|
||||
|
||||
@@ -20,9 +20,21 @@ class ChannelList extends StatefulWidget {
|
||||
class _ChannelList extends State<ChannelList> {
|
||||
ScrollController _scrollController = ScrollController();
|
||||
|
||||
TextEditingController? _controller;
|
||||
late StreamMessageSearchListController _messageSearchListController =
|
||||
StreamMessageSearchListController(
|
||||
client: StreamChat.of(context).client,
|
||||
filter: Filter.in_('members', [StreamChat.of(context).currentUser!.id]),
|
||||
limit: 5,
|
||||
searchQuery: '',
|
||||
sort: [
|
||||
SortOption(
|
||||
'created_at',
|
||||
direction: SortOption.ASC,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
String _channelQuery = '';
|
||||
TextEditingController? _controller;
|
||||
|
||||
bool _isSearchActive = false;
|
||||
|
||||
@@ -32,10 +44,11 @@ class _ChannelList extends State<ChannelList> {
|
||||
if (_debounce?.isActive ?? false) _debounce!.cancel();
|
||||
_debounce = Timer(const Duration(milliseconds: 350), () {
|
||||
if (mounted) {
|
||||
_messageSearchListController.searchQuery = _controller!.text;
|
||||
setState(() {
|
||||
_channelQuery = _controller!.text;
|
||||
_isSearchActive = _channelQuery.isNotEmpty;
|
||||
_isSearchActive = _controller!.text.isNotEmpty;
|
||||
});
|
||||
if (_isSearchActive) _messageSearchListController.doInitialLoad();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -61,12 +74,12 @@ class _ChannelList extends State<ChannelList> {
|
||||
_controller?.removeListener(_channelQueryListener);
|
||||
_controller?.dispose();
|
||||
_scrollController.dispose();
|
||||
_channelListController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final user = StreamChat.of(context).currentUser;
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
if (_isSearchActive) {
|
||||
@@ -98,17 +111,7 @@ class _ChannelList extends State<ChannelList> {
|
||||
],
|
||||
body: _isSearchActive
|
||||
? StreamMessageSearchListView(
|
||||
showErrorTile: true,
|
||||
messageQuery: _channelQuery,
|
||||
filters: Filter.in_('members', [user!.id]),
|
||||
sortOptions: [
|
||||
SortOption(
|
||||
'created_at',
|
||||
direction: SortOption.ASC,
|
||||
),
|
||||
],
|
||||
pullToRefresh: false,
|
||||
limit: 30,
|
||||
controller: _messageSearchListController,
|
||||
emptyBuilder: (_) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, viewportConstraints) {
|
||||
@@ -139,7 +142,15 @@ class _ChannelList extends State<ChannelList> {
|
||||
},
|
||||
);
|
||||
},
|
||||
onItemTap: (messageResponse) async {
|
||||
itemBuilder: (
|
||||
context,
|
||||
messageResponses,
|
||||
index,
|
||||
defaultWidget,
|
||||
) {
|
||||
return defaultWidget.copyWith(
|
||||
onTap: () async {
|
||||
final messageResponse = messageResponses[index];
|
||||
FocusScope.of(context).requestFocus(FocusNode());
|
||||
final client = StreamChat.of(context).client;
|
||||
final message = messageResponse.message;
|
||||
@@ -159,6 +170,8 @@ class _ChannelList extends State<ChannelList> {
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
)
|
||||
: SlidableAutoCloseBehavior(
|
||||
closeWhenOpened: true,
|
||||
@@ -166,9 +179,10 @@ class _ChannelList extends State<ChannelList> {
|
||||
onRefresh: _channelListController.refresh,
|
||||
child: StreamChannelListView(
|
||||
controller: _channelListController,
|
||||
itemBuilder: (context, channel, tile) {
|
||||
itemBuilder: (context, channels, index, defaultWidget) {
|
||||
final chatTheme = StreamChatTheme.of(context);
|
||||
final backgroundColor = chatTheme.colorTheme.inputBg;
|
||||
final channel = channels[index];
|
||||
final canDeleteChannel = channel.ownCapabilities
|
||||
.contains(PermissionType.deleteChannel);
|
||||
return Slidable(
|
||||
@@ -249,7 +263,7 @@ class _ChannelList extends State<ChannelList> {
|
||||
),
|
||||
],
|
||||
),
|
||||
child: tile,
|
||||
child: defaultWidget,
|
||||
);
|
||||
},
|
||||
onChannelTap: (channel) {
|
||||
|
||||
@@ -704,41 +704,8 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
|
||||
void _buildAddUserModal(context) {
|
||||
var channel = StreamChannel.of(context).channel;
|
||||
|
||||
showDialog(
|
||||
useRootNavigator: false,
|
||||
context: context,
|
||||
barrierColor: StreamChatTheme.of(context).colorTheme.overlay,
|
||||
builder: (context) {
|
||||
return StatefulBuilder(builder: (context, modalSetState) {
|
||||
modalSetStateCallback = modalSetState;
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 16.0, left: 8.0, right: 8.0),
|
||||
child: Material(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(16.0),
|
||||
topRight: Radius.circular(16.0),
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Scaffold(
|
||||
body: UsersBloc(
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: _buildTextInputSection(modalSetState),
|
||||
),
|
||||
Expanded(
|
||||
child: StreamUserListView(
|
||||
selectedUsers: {},
|
||||
onUserTap: (user, _) async {
|
||||
_searchController!.clear();
|
||||
|
||||
await channel.addMembers([user.id]);
|
||||
Navigator.pop(context);
|
||||
setState(() {});
|
||||
},
|
||||
crossAxisCount: 4,
|
||||
final userListController = StreamUserListController(
|
||||
client: channel.client,
|
||||
limit: 25,
|
||||
filter: Filter.and(
|
||||
[
|
||||
@@ -758,6 +725,40 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
direction: 1,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
showDialog(
|
||||
useRootNavigator: false,
|
||||
context: context,
|
||||
barrierColor: StreamChatTheme.of(context).colorTheme.overlay,
|
||||
builder: (context) {
|
||||
return StatefulBuilder(builder: (context, modalSetState) {
|
||||
modalSetStateCallback = modalSetState;
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 16.0, left: 8.0, right: 8.0),
|
||||
child: Material(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(16.0),
|
||||
topRight: Radius.circular(16.0),
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Scaffold(
|
||||
body: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: _buildTextInputSection(modalSetState),
|
||||
),
|
||||
Expanded(
|
||||
child: StreamUserListView(
|
||||
controller: userListController,
|
||||
onUserTap: (user) async {
|
||||
_searchController!.clear();
|
||||
|
||||
await channel.addMembers([user.id]);
|
||||
Navigator.pop(context);
|
||||
setState(() {});
|
||||
},
|
||||
emptyBuilder: (_) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, viewportConstraints) {
|
||||
@@ -795,11 +796,10 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
).then((_) => userListController.dispose());
|
||||
}
|
||||
|
||||
Widget _buildTextInputSection(modalSetState) {
|
||||
|
||||
@@ -19,6 +19,20 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||
|
||||
late TextEditingController _controller;
|
||||
|
||||
late final userListController = StreamUserListController(
|
||||
client: StreamChat.of(context).client,
|
||||
limit: 25,
|
||||
filter: Filter.and([
|
||||
Filter.notEqual('id', StreamChat.of(context).currentUser!.id),
|
||||
]),
|
||||
sort: [
|
||||
SortOption(
|
||||
'name',
|
||||
direction: 1,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
ChipInputTextFieldState? get _chipInputTextFieldState =>
|
||||
_chipInputTextFieldStateKey.currentState;
|
||||
|
||||
@@ -45,6 +59,12 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||
_userNameQuery = _controller.text;
|
||||
_isSearchActive = _userNameQuery.isNotEmpty;
|
||||
});
|
||||
userListController.filter = Filter.and([
|
||||
if (_userNameQuery.isNotEmpty)
|
||||
Filter.autoComplete('name', _userNameQuery),
|
||||
Filter.notEqual('id', StreamChat.of(context).currentUser!.id),
|
||||
]);
|
||||
userListController.doInitialLoad();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -112,6 +132,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||
_controller.clear();
|
||||
_controller.removeListener(_userNameListener);
|
||||
_controller.dispose();
|
||||
userListController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -289,10 +310,10 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||
onPanDown: (_) => FocusScope.of(context).unfocus(),
|
||||
child: UsersBloc(
|
||||
child: StreamUserListView(
|
||||
selectedUsers: _selectedUsers,
|
||||
groupAlphabetically:
|
||||
_isSearchActive ? false : true,
|
||||
onUserTap: (user, _) {
|
||||
controller: userListController,
|
||||
// groupAlphabetically:
|
||||
// _isSearchActive ? false : true,
|
||||
onUserTap: (user) {
|
||||
_controller.clear();
|
||||
if (!_selectedUsers.contains(user)) {
|
||||
_chipInputTextFieldState
|
||||
@@ -302,19 +323,17 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||
_chipInputTextFieldState!.removeItem(user);
|
||||
}
|
||||
},
|
||||
limit: 25,
|
||||
filter: Filter.and([
|
||||
if (_userNameQuery.isNotEmpty)
|
||||
Filter.autoComplete('name', _userNameQuery),
|
||||
Filter.notEqual('id',
|
||||
StreamChat.of(context).currentUser!.id),
|
||||
]),
|
||||
sort: [
|
||||
SortOption(
|
||||
'name',
|
||||
direction: 1,
|
||||
),
|
||||
],
|
||||
itemBuilder: (
|
||||
context,
|
||||
users,
|
||||
index,
|
||||
defaultWidget,
|
||||
) {
|
||||
return defaultWidget.copyWith(
|
||||
selected:
|
||||
_selectedUsers.contains(users[index]),
|
||||
);
|
||||
},
|
||||
emptyBuilder: (_) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, viewportConstraints) {
|
||||
|
||||
@@ -23,6 +23,20 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||
|
||||
Timer? _debounce;
|
||||
|
||||
late final userListController = StreamUserListController(
|
||||
client: StreamChat.of(context).client,
|
||||
sort: [
|
||||
SortOption(
|
||||
'name',
|
||||
direction: 1,
|
||||
),
|
||||
],
|
||||
limit: 25,
|
||||
filter: Filter.and([
|
||||
Filter.notEqual('id', StreamChat.of(context).currentUser!.id),
|
||||
]),
|
||||
);
|
||||
|
||||
void _userNameListener() {
|
||||
if (_debounce?.isActive ?? false) _debounce!.cancel();
|
||||
_debounce = Timer(const Duration(milliseconds: 350), () {
|
||||
@@ -31,6 +45,12 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||
_userNameQuery = _controller!.text;
|
||||
_isSearchActive = _userNameQuery.isNotEmpty;
|
||||
});
|
||||
userListController.filter = Filter.and([
|
||||
if (_userNameQuery.isNotEmpty)
|
||||
Filter.autoComplete('name', _userNameQuery),
|
||||
Filter.notEqual('id', StreamChat.of(context).currentUser!.id),
|
||||
]);
|
||||
userListController.doInitialLoad();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -46,6 +66,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||
_controller?.clear();
|
||||
_controller?.removeListener(_userNameListener);
|
||||
_controller?.dispose();
|
||||
userListController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -228,12 +249,15 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||
body: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onPanDown: (_) => FocusScope.of(context).unfocus(),
|
||||
child: UsersBloc(
|
||||
child: StreamUserListView(
|
||||
selectedUsers: _selectedUsers,
|
||||
pullToRefresh: false,
|
||||
groupAlphabetically: _isSearchActive ? false : true,
|
||||
onUserTap: (user, _) {
|
||||
controller: userListController,
|
||||
// groupAlphabetically: _isSearchActive ? false : true,
|
||||
itemBuilder: (context, items, index, defaultWidget) {
|
||||
return defaultWidget.copyWith(
|
||||
selected: _selectedUsers.contains(items[index]),
|
||||
);
|
||||
},
|
||||
onUserTap: (user) {
|
||||
if (!_selectedUsers.contains(user)) {
|
||||
setState(() {
|
||||
_selectedUsers.add(user);
|
||||
@@ -244,19 +268,6 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||
});
|
||||
}
|
||||
},
|
||||
limit: 25,
|
||||
filter: Filter.and([
|
||||
if (_userNameQuery.isNotEmpty)
|
||||
Filter.autoComplete('name', _userNameQuery),
|
||||
Filter.notEqual(
|
||||
'id', StreamChat.of(context).currentUser!.id),
|
||||
]),
|
||||
sort: [
|
||||
SortOption(
|
||||
'name',
|
||||
direction: 1,
|
||||
),
|
||||
],
|
||||
emptyBuilder: (_) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, viewportConstraints) {
|
||||
@@ -301,7 +312,6 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -5,26 +5,32 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
|
||||
import 'channel_page.dart';
|
||||
|
||||
class UserMentionsPage extends StatelessWidget {
|
||||
class UserMentionsPage extends StatefulWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final user = StreamChat.of(context).currentUser!;
|
||||
return MessageSearchBloc(
|
||||
child: StreamMessageSearchListView(
|
||||
filters: Filter.in_('members', [user.id]),
|
||||
messageFilters: Filter.custom(
|
||||
State<UserMentionsPage> createState() => _UserMentionsPageState();
|
||||
}
|
||||
|
||||
class _UserMentionsPageState extends State<UserMentionsPage> {
|
||||
late final controller = StreamMessageSearchListController(
|
||||
client: StreamChat.of(context).client,
|
||||
filter: Filter.in_('members', [StreamChat.of(context).currentUser!.id]),
|
||||
messageFilter: Filter.custom(
|
||||
operator: r'$contains',
|
||||
key: 'mentioned_users.id',
|
||||
value: user.id,
|
||||
value: StreamChat.of(context).currentUser!.id,
|
||||
),
|
||||
sortOptions: [
|
||||
sort: [
|
||||
SortOption(
|
||||
'created_at',
|
||||
direction: SortOption.ASC,
|
||||
),
|
||||
],
|
||||
limit: 20,
|
||||
showResultCount: false,
|
||||
);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StreamMessageSearchListView(
|
||||
controller: controller,
|
||||
emptyBuilder: (_) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, viewportConstraints) {
|
||||
@@ -47,10 +53,8 @@ class UserMentionsPage extends StatelessWidget {
|
||||
),
|
||||
Text(
|
||||
AppLocalizations.of(context).noMentionsExistYet,
|
||||
style: StreamChatTheme.of(context)
|
||||
.textTheme
|
||||
.body
|
||||
.copyWith(
|
||||
style:
|
||||
StreamChatTheme.of(context).textTheme.body.copyWith(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.textLowEmphasis,
|
||||
@@ -64,7 +68,7 @@ class UserMentionsPage extends StatelessWidget {
|
||||
},
|
||||
);
|
||||
},
|
||||
onItemTap: (messageResponse) async {
|
||||
onMessageTap: (messageResponse) async {
|
||||
final client = StreamChat.of(context).client;
|
||||
final message = messageResponse.message;
|
||||
final channel = client.channel(
|
||||
@@ -83,7 +87,12 @@ class UserMentionsPage extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user