feat: Switched to UserListView

This commit is contained in:
Deven Joshi
2020-11-30 15:56:25 +05:30
parent 3d1ea5d588
commit 832e31cbc6
2 changed files with 124 additions and 214 deletions
+73 -175
View File
@@ -60,7 +60,7 @@ class _ImageFooterState extends State<ImageFooter> {
TextEditingController _searchController = TextEditingController(); TextEditingController _searchController = TextEditingController();
TextEditingController _messageController = TextEditingController(); TextEditingController _messageController = TextEditingController();
List<User> _selectedUsers = []; Set<User> _selectedUsers = {};
bool _loading = false; bool _loading = false;
@override @override
@@ -204,171 +204,93 @@ class _ImageFooterState extends State<ImageFooter> {
showDialog( showDialog(
context: context, context: context,
builder: (context) { builder: (context) {
return StreamChannel( return StatefulBuilder(builder: (context, modalSetState) {
channel: channel,
child: Scaffold(
backgroundColor: Colors.transparent,
body: StatefulBuilder(builder: (modalContext, modalSetState) {
return Align(
alignment: _userSearchMode
? Alignment.topCenter
: Alignment.bottomCenter,
child: Material(
color: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
child: Stack(
children: [
ListView(
children: [
if (!_userSearchMode &&
MediaQuery.of(context).viewInsets.bottom == 0.0)
GestureDetector(
child: Container(
height:
MediaQuery.of(modalContext).size.height / 2,
color: Colors.transparent,
),
onTapUp: (val) {
Navigator.pop(modalContext);
},
),
Container(
margin: EdgeInsets.symmetric(
horizontal: 8.0,
),
padding: EdgeInsets.symmetric(
vertical: 4.0,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(16.0),
topLeft: Radius.circular(16.0),
)),
child: _buildTextInputSection(modalSetState),
),
Container(
margin: EdgeInsets.symmetric(
horizontal: 8.0,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(
_userSearchMode ? 16.0 : 0.0),
bottomLeft: Radius.circular(
_userSearchMode ? 16.0 : 0.0),
),
),
child: FutureBuilder<QueryUsersResponse>(
future: _userQuery,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
var filteredData =
snapshot.data.users.toList();
if (_userSearchMode &&
_searchController.text.length > 0) {
filteredData = snapshot.data.users
.where((element) => element.name
.toLowerCase()
.contains(_searchController.text
.toLowerCase()))
.toList();
}
return GridView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, position) {
var user = filteredData[position];
var isUserSelected =
_selectedUsers.contains(user);
return Padding( return Padding(
padding: const EdgeInsets.all(8.0), padding: const 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( child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [ children: [
Stack( _buildTextInputSection(modalSetState),
children: [ Expanded(
CircleAvatar( child: UserListView(
maxRadius: 32.0, selectedUsers: _selectedUsers,
child: UserAvatar( onUserTap: (user, _) {
onTap: (user) { _searchController.clear();
if (isUserSelected) { if (!_selectedUsers.contains(user)) {
_selectedUsers modalSetState(() {
.remove(user); _selectedUsers.add(user);
});
} else { } else {
_selectedUsers modalSetState(() {
.add(user); _selectedUsers.remove(user);
});
} }
modalSetState(() {});
}, },
user: user, crossAxisCount: 3,
constraints: pagination: PaginationParams(
BoxConstraints.tightFor( limit: 25,
height: isUserSelected
? 56
: 64,
width: isUserSelected
? 56
: 64,
),
borderRadius:
BorderRadius.circular(
32),
), ),
filter: {
if (_searchController.text.isNotEmpty)
'name': {
r'$autocomplete': _searchController.text,
},
'id': {
r'$ne': StreamChat.of(context).user.id,
},
},
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(
children: [
Padding( Padding(
padding: padding: const EdgeInsets.all(24),
const EdgeInsets.all(8.0), child: StreamSvgIcon.search(
child: Text( size: 96,
user.name, color: Colors.grey,
style: Theme.of(context)
.textTheme
.subtitle2,
textAlign: TextAlign.center,
maxLines: 2,
), ),
), ),
Text(
'No user matches these keywords...'),
], ],
), ),
),
),
); );
}, },
itemCount: filteredData.length,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
childAspectRatio: 0.75,
),
); );
}), },
), ),
],
), ),
if (_selectedUsers.isNotEmpty)
_buildShareTextInputSection(modalSetState),
if (!_userSearchMode && _selectedUsers.isEmpty) if (!_userSearchMode && _selectedUsers.isEmpty)
Align( Align(
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
child: Container( child: Container(
color: Colors.white, color: Colors.white,
height: 48.0, height: 48.0,
margin: EdgeInsets.symmetric(
horizontal: 8.0,
),
child: Material( child: Material(
child: InkWell( child: InkWell(
onTap: () async { onTap: () async {
@@ -392,7 +314,7 @@ class _ImageFooterState extends State<ImageFooter> {
child: Text( child: Text(
'Save to Photos', 'Save to Photos',
style: TextStyle( style: TextStyle(
color: StreamChatTheme.of(modalContext) color: StreamChatTheme.of(context)
.accentColor, .accentColor,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -403,15 +325,13 @@ class _ImageFooterState extends State<ImageFooter> {
), ),
), ),
), ),
if (!_userSearchMode && _selectedUsers.isNotEmpty)
_buildShareTextInputSection(modalSetState),
], ],
), ),
), ),
); ),
}),
), ),
); );
});
}, },
); );
} }
@@ -440,13 +360,14 @@ class _ImageFooterState extends State<ImageFooter> {
decoration: InputDecoration( decoration: InputDecoration(
isDense: true, isDense: true,
prefixIconConstraints: prefixIconConstraints:
BoxConstraints.tight(Size(38.0, 38.0)), BoxConstraints.tight(Size(36.0, 44.0)),
prefixIcon: Transform.scale( prefixIcon: Padding(
scale: 1.2, padding: const EdgeInsets.symmetric(
alignment: Alignment.center, vertical: 2.0, horizontal: 6.0),
child: StreamSvgIcon.search( child: StreamSvgIcon.search(
color: Colors.black, color: Colors.black,
)), ),
),
hintText: 'Search', hintText: 'Search',
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(32.0), borderRadius: BorderRadius.circular(32.0),
@@ -512,10 +433,9 @@ class _ImageFooterState extends State<ImageFooter> {
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 6.0), padding: const EdgeInsets.symmetric(horizontal: 6.0),
child: IconButton( child: IconButton(
icon: StreamSvgIcon.search( icon: StreamSvgIcon.share_arrow(
color: Colors.black, color: Colors.black,
), ),
iconSize: 24.0,
onPressed: () async { onPressed: () async {
var url = widget.urls[widget.currentPage].imageUrl ?? var url = widget.urls[widget.currentPage].imageUrl ??
widget.urls[widget.currentPage].assetUrl ?? widget.urls[widget.currentPage].assetUrl ??
@@ -580,11 +500,7 @@ class _ImageFooterState extends State<ImageFooter> {
), ),
), ),
), ),
AnimatedCrossFade( IconTheme(
crossFadeState: _messageController.text.isNotEmpty
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
firstChild: IconTheme(
data: StreamChatTheme.of(context) data: StreamChatTheme.of(context)
.channelTheme .channelTheme
.messageInputButtonIconTheme, .messageInputButtonIconTheme,
@@ -611,24 +527,6 @@ class _ImageFooterState extends State<ImageFooter> {
), ),
), ),
), ),
secondChild: IconTheme(
data: StreamChatTheme.of(context)
.channelTheme
.messageInputButtonIconTheme,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: InkWell(
onTap: () {},
child: StreamSvgIcon.Icon_send_message(
color: Colors.grey,
),
)),
),
),
duration: Duration(milliseconds: 300),
alignment: Alignment.center,
),
], ],
), ),
), ),
+12
View File
@@ -469,4 +469,16 @@ class StreamSvgIcon extends StatelessWidget {
height: size, height: size,
); );
} }
factory StreamSvgIcon.share_arrow({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'share_arrow.svg',
color: color,
width: size,
height: size,
);
}
} }