feat: Added info tile to group screens

This commit is contained in:
Deven Joshi
2021-01-13 16:09:23 +05:30
parent f3ff758894
commit 1fd81adbf4
2 changed files with 315 additions and 253 deletions
+105 -74
View File
@@ -150,85 +150,116 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
), ),
], ],
), ),
body: Column( body: ValueListenableBuilder<ConnectionStatus>(
children: [ valueListenable: StreamChat.of(context).client.wsConnectionStatus,
Container( builder: (context, status, _) {
width: double.maxFinite, String statusString = '';
decoration: BoxDecoration( bool showStatus = true;
gradient: StreamChatTheme.of(context).colorTheme.bgGradient,
), switch (status) {
child: Padding( case ConnectionStatus.connected:
padding: const EdgeInsets.symmetric( statusString = 'Connected';
vertical: 8, showStatus = false;
horizontal: 8, break;
), case ConnectionStatus.connecting:
child: Text( statusString = 'Reconnecting...';
'$_totalUsers ${_totalUsers > 1 ? 'Members' : 'Member'}', break;
style: TextStyle( case ConnectionStatus.disconnected:
color: StreamChatTheme.of(context).colorTheme.grey, statusString = 'Disconnected';
), break;
), }
), return InfoTile(
), showMessage: showStatus,
Expanded( tileAnchor: Alignment.topCenter,
child: GestureDetector( childAnchor: Alignment.topCenter,
behavior: HitTestBehavior.opaque, message: statusString,
onPanDown: (_) => FocusScope.of(context).unfocus(), child: Column(
child: ListView.separated( children: [
itemCount: _selectedUsers.length + 1, Container(
separatorBuilder: (_, __) => Container( width: double.maxFinite,
height: 1, decoration: BoxDecoration(
color: StreamChatTheme.of(context).colorTheme.greyWhisper, gradient:
), StreamChatTheme.of(context).colorTheme.bgGradient,
itemBuilder: (_, index) { ),
if (index == _selectedUsers.length) { child: Padding(
return Container( padding: const EdgeInsets.symmetric(
height: 1, vertical: 8,
color: horizontal: 8,
StreamChatTheme.of(context).colorTheme.greyWhisper, ),
); child: Text(
} '$_totalUsers ${_totalUsers > 1 ? 'Members' : 'Member'}',
final user = _selectedUsers[index]; style: TextStyle(
return ListTile( color: StreamChatTheme.of(context).colorTheme.grey,
key: ObjectKey(user), ),
leading: UserAvatar(
user: user,
constraints: BoxConstraints.tightFor(
width: 40,
height: 40,
), ),
), ),
title: Text( ),
user.name, Expanded(
style: TextStyle(fontWeight: FontWeight.bold), child: GestureDetector(
), behavior: HitTestBehavior.opaque,
contentPadding: const EdgeInsets.symmetric( onPanDown: (_) => FocusScope.of(context).unfocus(),
horizontal: 12, child: ListView.separated(
vertical: 8, itemCount: _selectedUsers.length + 1,
), separatorBuilder: (_, __) => Container(
trailing: IconButton( height: 1,
icon: Icon( color: StreamChatTheme.of(context)
Icons.clear_rounded, .colorTheme
color: StreamChatTheme.of(context).colorTheme.black, .greyWhisper,
),
itemBuilder: (_, index) {
if (index == _selectedUsers.length) {
return Container(
height: 1,
color: StreamChatTheme.of(context)
.colorTheme
.greyWhisper,
);
}
final user = _selectedUsers[index];
return ListTile(
key: ObjectKey(user),
leading: UserAvatar(
user: user,
constraints: BoxConstraints.tightFor(
width: 40,
height: 40,
),
),
title: Text(
user.name,
style: TextStyle(fontWeight: FontWeight.bold),
),
contentPadding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 8,
),
trailing: IconButton(
icon: Icon(
Icons.clear_rounded,
color: StreamChatTheme.of(context)
.colorTheme
.black,
),
padding: const EdgeInsets.all(0),
splashRadius: 24,
onPressed: () {
setState(() {
_selectedUsers.remove(user);
});
if (_selectedUsers.isEmpty) {
Navigator.pop(context, _selectedUsers);
}
},
),
);
},
), ),
padding: const EdgeInsets.all(0),
splashRadius: 24,
onPressed: () {
setState(() {
_selectedUsers.remove(user);
});
if (_selectedUsers.isEmpty) {
Navigator.pop(context, _selectedUsers);
}
},
), ),
); ),
}, ],
), ),
), );
), }),
],
),
), ),
); );
} }
+210 -179
View File
@@ -87,196 +87,227 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
) )
], ],
), ),
body: NestedScrollView( body: ValueListenableBuilder<ConnectionStatus>(
floatHeaderSlivers: true, valueListenable: StreamChat.of(context).client.wsConnectionStatus,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { builder: (context, status, _) {
return <Widget>[ String statusString = '';
SliverToBoxAdapter( bool showStatus = true;
child: SearchTextField(
controller: _controller, switch (status) {
), case ConnectionStatus.connected:
), statusString = 'Connected';
if (_selectedUsers.isNotEmpty) showStatus = false;
SliverToBoxAdapter( break;
child: Container( case ConnectionStatus.connecting:
height: 104, statusString = 'Reconnecting...';
child: ListView.separated( break;
scrollDirection: Axis.horizontal, case ConnectionStatus.disconnected:
itemCount: _selectedUsers.length, statusString = 'Disconnected';
padding: const EdgeInsets.all(8), break;
separatorBuilder: (_, __) => SizedBox(width: 16), }
itemBuilder: (_, index) { return InfoTile(
final user = _selectedUsers.elementAt(index); showMessage: showStatus,
return Column( tileAnchor: Alignment.topCenter,
children: [ childAnchor: Alignment.topCenter,
Stack( message: statusString,
children: [ child: NestedScrollView(
UserAvatar( floatHeaderSlivers: true,
onlineIndicatorAlignment: Alignment(0.9, 0.9), headerSliverBuilder:
user: user, (BuildContext context, bool innerBoxIsScrolled) {
showOnlineStatus: true, return <Widget>[
borderRadius: BorderRadius.circular(32), SliverToBoxAdapter(
constraints: BoxConstraints.tightFor( child: SearchTextField(
height: 64, controller: _controller,
width: 64, ),
), ),
), if (_selectedUsers.isNotEmpty)
Positioned( SliverToBoxAdapter(
top: -4, child: Container(
right: -4, height: 104,
child: GestureDetector( child: ListView.separated(
onTap: () { scrollDirection: Axis.horizontal,
if (_selectedUsers.contains(user)) { itemCount: _selectedUsers.length,
setState( padding: const EdgeInsets.all(8),
() => _selectedUsers.remove(user)); separatorBuilder: (_, __) => SizedBox(width: 16),
} itemBuilder: (_, index) {
}, final user = _selectedUsers.elementAt(index);
child: Container( return Column(
decoration: BoxDecoration( children: [
color: StreamChatTheme.of(context) Stack(
.colorTheme children: [
.white, UserAvatar(
shape: BoxShape.circle, onlineIndicatorAlignment:
border: Border.all( Alignment(0.9, 0.9),
color: StreamChatTheme.of(context) user: user,
.colorTheme showOnlineStatus: true,
.whiteSnow, borderRadius: BorderRadius.circular(32),
constraints: BoxConstraints.tightFor(
height: 64,
width: 64,
),
), ),
), Positioned(
child: StreamSvgIcon.close( top: -4,
color: StreamChatTheme.of(context) right: -4,
.colorTheme child: GestureDetector(
.black, onTap: () {
size: 24, if (_selectedUsers.contains(user)) {
setState(() =>
_selectedUsers.remove(user));
}
},
child: Container(
decoration: BoxDecoration(
color: StreamChatTheme.of(context)
.colorTheme
.white,
shape: BoxShape.circle,
border: Border.all(
color:
StreamChatTheme.of(context)
.colorTheme
.whiteSnow,
),
),
child: StreamSvgIcon.close(
color: StreamChatTheme.of(context)
.colorTheme
.black,
size: 24,
),
),
),
)
],
),
SizedBox(height: 4),
Text(
user.name.split(' ')[0],
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 12,
), ),
), ),
), ],
) );
], },
), ),
SizedBox(height: 4), ),
Text( ),
user.name.split(' ')[0], SliverPersistentHeader(
style: TextStyle( pinned: true,
fontWeight: FontWeight.bold, delegate: _HeaderDelegate(
fontSize: 12, height: 30,
child: Container(
width: double.maxFinite,
decoration: BoxDecoration(
gradient: StreamChatTheme.of(context)
.colorTheme
.bgGradient,
),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 8,
horizontal: 8,
),
child: Text(
_isSearchActive
? 'Matches for \"$_userNameQuery\"'
: 'On the platform',
style: TextStyle(
color:
StreamChatTheme.of(context).colorTheme.grey,
),
), ),
), ),
], ),
);
},
),
),
),
SliverPersistentHeader(
pinned: true,
delegate: _HeaderDelegate(
height: 30,
child: Container(
width: double.maxFinite,
decoration: BoxDecoration(
gradient: StreamChatTheme.of(context).colorTheme.bgGradient,
),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 8,
horizontal: 8,
),
child: Text(
_isSearchActive
? 'Matches for \"$_userNameQuery\"'
: 'On the platform',
style: TextStyle(
color: StreamChatTheme.of(context).colorTheme.grey,
), ),
), ),
), ];
), },
), body: GestureDetector(
), behavior: HitTestBehavior.opaque,
]; onPanDown: (_) => FocusScope.of(context).unfocus(),
}, child: UsersBloc(
body: GestureDetector( child: UserListView(
behavior: HitTestBehavior.opaque, selectedUsers: _selectedUsers,
onPanDown: (_) => FocusScope.of(context).unfocus(), pullToRefresh: false,
child: UsersBloc( groupAlphabetically: _isSearchActive ? false : true,
child: UserListView( onUserTap: (user, _) {
selectedUsers: _selectedUsers, if (!_selectedUsers.contains(user)) {
pullToRefresh: false, setState(() {
groupAlphabetically: _isSearchActive ? false : true, _selectedUsers.add(user);
onUserTap: (user, _) { });
if (!_selectedUsers.contains(user)) { } else {
setState(() { setState(() {
_selectedUsers.add(user); _selectedUsers.remove(user);
}); });
} else { }
setState(() { },
_selectedUsers.remove(user); pagination: PaginationParams(
}); limit: 25,
} ),
}, filter: {
pagination: PaginationParams( if (_userNameQuery.isNotEmpty)
limit: 25, 'name': {
), r'$autocomplete': _userNameQuery,
filter: { },
if (_userNameQuery.isNotEmpty) 'id': {
'name': { r'$ne': StreamChat.of(context).user.id,
r'$autocomplete': _userNameQuery, }
}, },
'id': { sort: [
r'$ne': StreamChat.of(context).user.id, SortOption(
} 'name',
}, direction: 1,
sort: [
SortOption(
'name',
direction: 1,
),
],
emptyBuilder: (_) {
return LayoutBuilder(
builder: (context, viewportConstraints) {
return SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
), ),
child: Center( ],
child: Column( emptyBuilder: (_) {
children: [ return LayoutBuilder(
Padding( builder: (context, viewportConstraints) {
padding: const EdgeInsets.all(24), return SingleChildScrollView(
child: StreamSvgIcon.search( physics: AlwaysScrollableScrollPhysics(),
size: 96, child: ConstrainedBox(
color: StreamChatTheme.of(context) constraints: BoxConstraints(
.colorTheme minHeight: viewportConstraints.maxHeight,
.grey, ),
child: Center(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(24),
child: StreamSvgIcon.search(
size: 96,
color: StreamChatTheme.of(context)
.colorTheme
.grey,
),
),
Text(
'No user matches these keywords...',
style: StreamChatTheme.of(context)
.textTheme
.footnote
.copyWith(
color: StreamChatTheme.of(context)
.colorTheme
.grey,
),
),
],
),
), ),
), ),
Text( );
'No user matches these keywords...', },
style: StreamChatTheme.of(context) );
.textTheme },
.footnote ),
.copyWith( ),
color: StreamChatTheme.of(context) ),
.colorTheme ),
.grey, );
), }),
),
],
),
),
),
);
},
);
},
),
),
),
),
); );
} }
} }