feat: Added gridview for channel list view and changed implementation for image sharing

This commit is contained in:
Deven Joshi
2020-12-22 17:45:08 +05:30
parent b0093dc065
commit 4aa2a8946a
5 changed files with 192 additions and 92 deletions
+6
View File
@@ -52,6 +52,7 @@ class ChannelImage extends StatelessWidget {
this.onTap,
this.showOnlineStatus = true,
this.borderRadius,
this.selected = false,
}) : super(key: key);
final BorderRadius borderRadius;
@@ -67,6 +68,8 @@ class ChannelImage extends StatelessWidget {
final bool showOnlineStatus;
final bool selected;
@override
Widget build(BuildContext context) {
final streamChat = StreamChat.of(context);
@@ -99,6 +102,7 @@ class ChannelImage extends StatelessWidget {
onTap();
}
: null,
selected: selected,
);
});
} else {
@@ -111,12 +115,14 @@ class ChannelImage extends StatelessWidget {
.toList();
return GroupImage(
images: images,
borderRadius: borderRadius,
constraints: constraints ??
StreamChatTheme.of(context)
.channelPreviewTheme
.avatarTheme
.constraints,
onTap: onTap,
selected: selected,
);
}
+61
View File
@@ -74,6 +74,8 @@ class ChannelListView extends StatefulWidget {
this.onStartChatPressed,
this.swipeToAction = false,
this.pullToRefresh = true,
this.crossAxisCount = 1,
this.selectedChannels = const [],
}) : super(key: key);
/// The builder that will be used in case of error
@@ -134,6 +136,11 @@ class ChannelListView extends StatefulWidget {
/// Callback used in the default empty list widget
final VoidCallback onStartChatPressed;
/// The number of children in the cross axis.
final int crossAxisCount;
final List<Channel> selectedChannels;
@override
_ChannelListViewState createState() => _ChannelListViewState();
}
@@ -259,6 +266,18 @@ class _ChannelListViewState extends State<ChannelListView>
}
if (channels.isNotEmpty) {
if (widget.crossAxisCount > 1) {
child = GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: widget.crossAxisCount),
itemCount: channels.length,
physics: AlwaysScrollableScrollPhysics(),
controller: _scrollController,
itemBuilder: (context, index) {
return _gridItemBuilder(context, index, channels);
},
);
} else {
child = ListView.custom(
physics: AlwaysScrollableScrollPhysics(),
controller: _scrollController,
@@ -277,6 +296,7 @@ class _ChannelListViewState extends State<ChannelListView>
);
}
}
}
return AnimatedSwitcher(
child: child,
@@ -581,6 +601,47 @@ class _ChannelListViewState extends State<ChannelListView>
}
}
Widget _gridItemBuilder(BuildContext context, int i, List<Channel> channels) {
var channel = channels[i];
var selected = widget.selectedChannels.contains(channel);
return Container(
key: ValueKey<String>('CHANNEL-${channel.id}'),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ChannelImage(
channel: channel,
borderRadius: BorderRadius.circular(32),
selected: selected,
constraints: BoxConstraints.tightFor(
width: 64,
height: 64,
),
onTap: () {
widget.onChannelTap(channel, null);
},
),
SizedBox(height: 7),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: StreamChannel(
child: ChannelName(
textStyle: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
),
),
channel: channel,
),
),
],
),
);
}
Widget _buildQueryProgressIndicator(
context,
ChannelsBlocState channelsProvider,
+33 -2
View File
@@ -9,18 +9,30 @@ class GroupImage extends StatelessWidget {
@required this.images,
this.constraints,
this.onTap,
this.borderRadius,
this.selected = false,
this.selectionColor = const Color(0xFF006CFF),
this.selectionThickness = 4,
}) : super(key: key);
final List<String> images;
final BoxConstraints constraints;
final VoidCallback onTap;
final bool selected;
final BorderRadius borderRadius;
final Color selectionColor;
final double selectionThickness;
@override
Widget build(BuildContext context) {
return GestureDetector(
var avatar;
final streamChatTheme = StreamChatTheme.of(context);
avatar = GestureDetector(
onTap: onTap,
child: ClipRRect(
borderRadius: StreamChatTheme.of(context)
borderRadius: borderRadius ??
StreamChatTheme.of(context)
.ownMessageTheme
.avatarTheme
.borderRadius,
@@ -91,5 +103,24 @@ class GroupImage extends StatelessWidget {
),
),
);
if (selected) {
avatar = ClipRRect(
borderRadius: (borderRadius ??
streamChatTheme.ownMessageTheme.avatarTheme.borderRadius) +
BorderRadius.circular(selectionThickness),
child: Container(
color: selectionColor,
height: 64.0,
width: 64.0,
child: Padding(
padding: EdgeInsets.all(selectionThickness),
child: avatar,
),
),
);
}
return avatar;
}
}
+21 -22
View File
@@ -68,7 +68,7 @@ class _ImageFooterState extends State<ImageFooter> {
String _userNameQuery;
bool _isSearchActive = false;
Set<User> _selectedUsers = {};
List<Channel> _selectedChannels = [];
bool _loading = false;
Timer _debounce;
@@ -278,22 +278,28 @@ class _ImageFooterState extends State<ImageFooter> {
),
clipBehavior: Clip.antiAlias,
child: Scaffold(
resizeToAvoidBottomInset: false,
body: UsersBloc(
child: Column(
children: [
_buildTextInputSection(modalSetState),
if (_userSearchMode)
SizedBox(
height: 22.0,
),
Expanded(
child: UserListView(
selectedUsers: _selectedUsers,
onUserTap: (user, _) {
child: ChannelsBloc(
child: ChannelListView(
selectedChannels: _selectedChannels,
onChannelTap: (user, _) {
_searchController.clear();
if (!_selectedUsers.contains(user)) {
if (!_selectedChannels.contains(user)) {
modalSetState(() {
_selectedUsers.add(user);
_selectedChannels.add(user);
});
} else {
modalSetState(() {
_selectedUsers.remove(user);
_selectedChannels.remove(user);
});
}
},
@@ -323,7 +329,8 @@ class _ImageFooterState extends State<ImageFooter> {
physics: AlwaysScrollableScrollPhysics(),
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
minHeight:
viewportConstraints.maxHeight,
),
child: Center(
child: Column(
@@ -347,9 +354,10 @@ class _ImageFooterState extends State<ImageFooter> {
},
),
),
if (_selectedUsers.isNotEmpty)
),
if (_selectedChannels.isNotEmpty)
_buildShareTextInputSection(modalSetState),
if (!_userSearchMode && _selectedUsers.isEmpty)
if (!_userSearchMode && _selectedChannels.isEmpty)
Align(
alignment: Alignment.bottomCenter,
child: Container(
@@ -614,25 +622,16 @@ class _ImageFooterState extends State<ImageFooter> {
final client = StreamChat.of(context).client;
for (var user in _selectedUsers) {
var c = client.channel('messaging', extraData: {
'members': [
user.id,
StreamChat.of(context).user.id,
],
});
await c.watch();
for (var channel in _selectedChannels) {
final message = Message(
text: text,
attachments: [attachments[widget.currentPage]],
);
await c.sendMessage(message);
await channel.sendMessage(message);
}
_selectedUsers.clear();
_selectedChannels.clear();
Navigator.pop(context);
}
+3
View File
@@ -61,12 +61,15 @@ class UserAvatar extends StatelessWidget {
: streamChatTheme.defaultUserImage(context, user),
),
);
if (selected) {
avatar = ClipRRect(
borderRadius: (borderRadius ??
streamChatTheme.ownMessageTheme.avatarTheme.borderRadius) +
BorderRadius.circular(selectionThickness),
child: Container(
constraints: constraints ??
streamChatTheme.ownMessageTheme.avatarTheme.constraints,
color: selectionColor,
child: Padding(
padding: EdgeInsets.all(selectionThickness),