rfac: Changed over group info screen to use streams

This commit is contained in:
Deven Joshi
2021-01-01 15:11:22 +05:30
parent dc643c0f71
commit b11543ea7f
2 changed files with 237 additions and 254 deletions
+79 -94
View File
@@ -16,12 +16,9 @@ class GroupInfoScreen extends StatefulWidget {
} }
class _GroupInfoScreenState extends State<GroupInfoScreen> { class _GroupInfoScreenState extends State<GroupInfoScreen> {
Future _memberQueryFuture;
TextEditingController _nameController; TextEditingController _nameController;
bool _userSearchMode = false;
TextEditingController _searchController; TextEditingController _searchController;
bool _loading = false;
String _userNameQuery = ''; String _userNameQuery = '';
Timer _debounce; Timer _debounce;
@@ -29,9 +26,6 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
final FocusNode _focusNode = FocusNode(); final FocusNode _focusNode = FocusNode();
bool namedChanged = false;
String changedName = '';
int groupMemberListLength; int groupMemberListLength;
void _userNameListener() { void _userNameListener() {
@@ -52,10 +46,6 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
void initState() { void initState() {
super.initState(); super.initState();
var channel = StreamChannel.of(context); var channel = StreamChannel.of(context);
_memberQueryFuture = channel.channel.queryMembers(
filter: {},
);
_nameController = TextEditingController.fromValue( _nameController = TextEditingController.fromValue(
TextEditingValue(text: channel.channel.extraData['name'] ?? '')); TextEditingValue(text: channel.channel.extraData['name'] ?? ''));
_searchController = TextEditingController()..addListener(_userNameListener); _searchController = TextEditingController()..addListener(_userNameListener);
@@ -69,8 +59,19 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
var channel = StreamChannel.of(context); var channel = StreamChannel.of(context);
return StreamBuilder<List<Member>>(
stream: channel.channel.state.membersStream,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Container(
color: StreamChatTheme.of(context).colorTheme.greyGainsboro,
child: Center(child: CircularProgressIndicator()),
);
}
return Scaffold( return Scaffold(
backgroundColor: StreamChatTheme.of(context).colorTheme.greyGainsboro, backgroundColor:
StreamChatTheme.of(context).colorTheme.greyGainsboro,
appBar: AppBar( appBar: AppBar(
elevation: 1.0, elevation: 1.0,
toolbarHeight: 56.0, toolbarHeight: 56.0,
@@ -89,14 +90,15 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
leadingWidth: 36.0, leadingWidth: 36.0,
title: Column( title: Column(
children: [ children: [
FutureBuilder<QueryMembersResponse>( StreamBuilder<ChannelState>(
future: _memberQueryFuture, stream: channel.channelStateStream,
builder: (context, snapshot) { builder: (context, state) {
return Text( return Text(
_getChannelName(MediaQuery.of(context).size.width, _getChannelName(
members: snapshot.data?.members 2 * MediaQuery.of(context).size.width / 3,
?.map((e) => e.user) members: snapshot.data,
?.toList()), extraData: state.data.channel.extraData,
maxFontSize: 16.0),
style: TextStyle( style: TextStyle(
color: StreamChatTheme.of(context).colorTheme.black, color: StreamChatTheme.of(context).colorTheme.black,
fontSize: 16, fontSize: 16,
@@ -108,11 +110,8 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
SizedBox( SizedBox(
height: 3.0, height: 3.0,
), ),
FutureBuilder<QueryMembersResponse>( Text(
future: _memberQueryFuture, '${channel.channel.memberCount} Members, ${snapshot?.data?.where((e) => e.user.online)?.length ?? 0} Online',
builder: (context, snapshot) {
return Text(
'${channel.channel.memberCount} Members, ${snapshot?.data?.members?.where((e) => e.user.online)?.length ?? 0} Online',
style: TextStyle( style: TextStyle(
color: StreamChatTheme.of(context) color: StreamChatTheme.of(context)
.colorTheme .colorTheme
@@ -120,8 +119,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
.withOpacity(0.5), .withOpacity(0.5),
fontSize: 12.0, fontSize: 12.0,
), ),
); ),
}),
], ],
), ),
centerTitle: true, centerTitle: true,
@@ -134,7 +132,9 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: StreamSvgIcon.userAdd( child: StreamSvgIcon.userAdd(
color: StreamChatTheme.of(context).colorTheme.accentBlue), color: StreamChatTheme.of(context)
.colorTheme
.accentBlue),
), ),
), ),
), ),
@@ -142,7 +142,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
), ),
body: ListView( body: ListView(
children: [ children: [
_buildMembers(), _buildMembers(snapshot.data),
Container( Container(
height: 8.0, height: 8.0,
color: StreamChatTheme.of(context).colorTheme.greyGainsboro, color: StreamChatTheme.of(context).colorTheme.greyGainsboro,
@@ -152,24 +152,11 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
], ],
), ),
); );
});
} }
Widget _buildMembers() { Widget _buildMembers(List<Member> members) {
var channel = StreamChannel.of(context); groupMemberListLength ??= members.length > 6 ? 6 : members.length;
return FutureBuilder<QueryMembersResponse>(
builder: (context, snapshot) {
if (snapshot.data == null) {
return Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: CircularProgressIndicator(),
),
);
}
groupMemberListLength ??=
snapshot.data.members.length > 6 ? 6 : snapshot.data.members.length;
return Column( return Column(
children: [ children: [
@@ -181,10 +168,10 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
return Material( return Material(
child: InkWell( child: InkWell(
onTap: () { onTap: () {
var userMember = snapshot.data.members.firstWhere( var userMember = members.firstWhere(
(e) => e.user.id == StreamChat.of(context).user.id); (e) => e.user.id == StreamChat.of(context).user.id);
_showUserInfoModal(snapshot.data.members[position].user, _showUserInfoModal(
userMember.role == 'owner'); members[position].user, userMember.role == 'owner');
}, },
child: Container( child: Container(
height: 65.0, height: 65.0,
@@ -196,7 +183,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: 8.0, vertical: 12.0), horizontal: 8.0, vertical: 12.0),
child: UserAvatar( child: UserAvatar(
user: snapshot.data.members[position].user, user: members[position].user,
constraints: BoxConstraints( constraints: BoxConstraints(
maxHeight: 40.0, maxWidth: 40.0), maxHeight: 40.0, maxWidth: 40.0),
), ),
@@ -207,16 +194,14 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( Text(
snapshot.data.members[position].user.name, members[position].user.name,
style: TextStyle( style: TextStyle(fontWeight: FontWeight.bold),
fontWeight: FontWeight.bold),
), ),
SizedBox( SizedBox(
height: 1.0, height: 1.0,
), ),
Text( Text(
_getLastSeen( _getLastSeen(members[position].user),
snapshot.data.members[position].user),
style: TextStyle( style: TextStyle(
color: StreamChatTheme.of(context) color: StreamChatTheme.of(context)
.colorTheme .colorTheme
@@ -229,10 +214,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
Padding( Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
snapshot.data.members[position].role == members[position].role == 'owner' ? 'Owner' : '',
'owner'
? 'Owner'
: '',
style: TextStyle( style: TextStyle(
color: StreamChatTheme.of(context) color: StreamChatTheme.of(context)
.colorTheme .colorTheme
@@ -252,18 +234,19 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
), ),
), ),
), ),
color: StreamChatTheme.of(context).colorTheme.white, color: StreamChatTheme.of(context).colorTheme.whiteSnow,
); );
}, },
), ),
if (groupMemberListLength != snapshot.data.members.length) if (groupMemberListLength != members.length)
InkWell( InkWell(
onTap: () { onTap: () {
setState(() { setState(() {
groupMemberListLength = snapshot.data.members.length; groupMemberListLength = members.length;
}); });
}, },
child: Material( child: Material(
color: StreamChatTheme.of(context).colorTheme.whiteSnow,
child: Container( child: Container(
height: 65.0, height: 65.0,
child: Column( child: Column(
@@ -275,9 +258,8 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: 21.0, vertical: 12.0), horizontal: 21.0, vertical: 12.0),
child: StreamSvgIcon.down( child: StreamSvgIcon.down(
color: StreamChatTheme.of(context) color:
.colorTheme StreamChatTheme.of(context).colorTheme.white,
.grey,
), ),
), ),
Expanded( Expanded(
@@ -286,7 +268,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( Text(
'${snapshot.data.members.length - groupMemberListLength} more', '${members.length - groupMemberListLength} more',
style: TextStyle( style: TextStyle(
color: StreamChatTheme.of(context) color: StreamChatTheme.of(context)
.colorTheme .colorTheme
@@ -300,9 +282,8 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
), ),
Container( Container(
height: 1.0, height: 1.0,
color: StreamChatTheme.of(context) color:
.colorTheme StreamChatTheme.of(context).colorTheme.greyGainsboro,
.greyGainsboro,
), ),
], ],
), ),
@@ -311,9 +292,6 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
), ),
], ],
); );
},
future: _memberQueryFuture,
);
} }
Widget _buildNameTile() { Widget _buildNameTile() {
@@ -321,7 +299,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
var channelName = channel.extraData['name'] ?? ''; var channelName = channel.extraData['name'] ?? '';
return Material( return Material(
color: StreamChatTheme.of(context).colorTheme.white, color: StreamChatTheme.of(context).colorTheme.whiteSnow,
child: Container( child: Container(
height: 56.0, height: 56.0,
alignment: Alignment.center, alignment: Alignment.center,
@@ -389,12 +367,6 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
onTap: () { onTap: () {
StreamChannel.of(context).channel.update({ StreamChannel.of(context).channel.update({
'name': _nameController.text.trim(), 'name': _nameController.text.trim(),
}).then((value) {
setState(() {
_focusNode.unfocus();
namedChanged = true;
changedName = _nameController.text.trim();
});
}).catchError((err) { }).catchError((err) {
setState(() { setState(() {
_nameController.text = channelName; _nameController.text = channelName;
@@ -433,7 +405,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
stream: StreamChannel.of(context).channel.isMutedStream, stream: StreamChannel.of(context).channel.isMutedStream,
builder: (context, snapshot) { builder: (context, snapshot) {
return OptionListTile( return OptionListTile(
tileColor: StreamChatTheme.of(context).colorTheme.white, tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow,
separatorColor: separatorColor:
StreamChatTheme.of(context).colorTheme.greyGainsboro, StreamChatTheme.of(context).colorTheme.greyGainsboro,
title: 'Mute group', title: 'Mute group',
@@ -460,7 +432,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
); );
}), }),
OptionListTile( OptionListTile(
tileColor: StreamChatTheme.of(context).colorTheme.white, tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow,
separatorColor: StreamChatTheme.of(context).colorTheme.greyGainsboro, separatorColor: StreamChatTheme.of(context).colorTheme.greyGainsboro,
title: 'Photos & Videos', title: 'Photos & Videos',
leading: StreamSvgIcon.pictures( leading: StreamSvgIcon.pictures(
@@ -494,7 +466,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
}, },
), ),
OptionListTile( OptionListTile(
tileColor: StreamChatTheme.of(context).colorTheme.white, tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow,
separatorColor: StreamChatTheme.of(context).colorTheme.greyGainsboro, separatorColor: StreamChatTheme.of(context).colorTheme.greyGainsboro,
title: 'Files', title: 'Files',
leading: StreamSvgIcon.files( leading: StreamSvgIcon.files(
@@ -529,7 +501,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
), ),
if (!channel.channel.isDistinct) if (!channel.channel.isDistinct)
OptionListTile( OptionListTile(
tileColor: StreamChatTheme.of(context).colorTheme.white, tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow,
separatorColor: separatorColor:
StreamChatTheme.of(context).colorTheme.greyGainsboro, StreamChatTheme.of(context).colorTheme.greyGainsboro,
title: 'Leave Group', title: 'Leave Group',
@@ -582,9 +554,6 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
await channel.addMembers([user.id]); await channel.addMembers([user.id]);
Navigator.pop(context); Navigator.pop(context);
_memberQueryFuture = channel.queryMembers(
filter: {},
);
setState(() {}); setState(() {});
}, },
crossAxisCount: 4, crossAxisCount: 4,
@@ -852,9 +821,6 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
'Remove From Group', () async { 'Remove From Group', () async {
await channel.removeMembers([user.id]); await channel.removeMembers([user.id]);
Navigator.pop(context); Navigator.pop(context);
_memberQueryFuture = channel.queryMembers(
filter: {},
);
}, color: StreamChatTheme.of(context).colorTheme.accentRed), }, color: StreamChatTheme.of(context).colorTheme.accentRed),
_buildModalListTile( _buildModalListTile(
context, context,
@@ -971,17 +937,36 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
); );
} }
String _getChannelName(double width, {List<User> members}) { String _getChannelName(double width,
if (namedChanged) { {List<Member> members, Map extraData, double maxFontSize}) {
return changedName; String title;
var client = StreamChat.of(context);
if (extraData['name'] == null) {
final otherMembers =
members.where((member) => member.user.id != client.user.id);
if (otherMembers.isNotEmpty) {
final maxWidth = width;
final maxChars = maxWidth / maxFontSize;
var currentChars = 0;
final currentMembers = <Member>[];
otherMembers.forEach((element) {
final newLength = currentChars + element.user.name.length;
if (newLength < maxChars) {
currentChars = newLength;
currentMembers.add(element);
} }
});
if (StreamChannel.of(context).channel.extraData['name'] == null && final exceedingMembers = otherMembers.length - currentMembers.length;
members != null) { title =
return '${members[0].name} & ${members.length - 1} others'; '${currentMembers.map((e) => e.user.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}';
} else {
title = 'No title';
} }
} else {
return StreamChannel.of(context).channel.extraData['name'] ?? ''; title = extraData['name'];
}
return title;
} }
String _getLastSeen(User user) { String _getLastSeen(User user) {
-2
View File
@@ -423,8 +423,6 @@ class _ChannelListPageState extends State<ChannelListPage> {
), ),
); );
} }
// TODO: Add group screen
}, },
), ),
), ),