Merge pull request #89 from GetStream/develop

Develop
This commit is contained in:
Deven Joshi
2020-09-30 12:43:23 +05:30
committed by GitHub
5 changed files with 217 additions and 15 deletions
+194
View File
@@ -108,6 +108,14 @@ class ChannelListPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return CreateChannelPage();
}));
},
),
body: ChannelsBloc(
child: ChannelListView(
filter: {
@@ -198,3 +206,189 @@ class ThreadPage extends StatelessWidget {
);
}
}
class CreateChannelPage extends StatefulWidget {
@override
_CreateChannelPageState createState() => _CreateChannelPageState();
}
class _CreateChannelPageState extends State<CreateChannelPage> {
final ScrollController _scrollController = ScrollController();
Client client;
List<User> users = [];
List<User> selectedUsers = [];
int offset = 0;
bool loading = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.transparent,
title: Text(
'Create a channel',
style: Theme.of(context).textTheme.headline6,
),
),
floatingActionButton:
selectedUsers.isNotEmpty ? _buildFAB(context) : SizedBox(),
body: _buildListView(),
);
}
ListView _buildListView() {
return ListView.builder(
controller: _scrollController,
itemBuilder: _itemBuilder,
itemCount: users.length,
);
}
Widget _itemBuilder(context, i) {
final user = users[i];
return ListTile(
onLongPress: () {
_selectUser(user);
},
selected: selectedUsers.contains(user),
onTap: () {
if (selectedUsers.isNotEmpty) {
return _selectUser(user);
}
_createChannel(context, [user]);
},
leading: UserAvatar(
user: user,
),
title: Text(user.name),
);
}
Widget _buildFAB(BuildContext context) {
return FloatingActionButton(
child: Icon(Icons.done),
onPressed: () async {
String name;
if (selectedUsers.length > 1) {
name = await _showEnterNameDialog(context);
if (name?.isNotEmpty != true) {
return;
}
}
_createChannel(context, selectedUsers, name);
},
);
}
Future<String> _showEnterNameDialog(BuildContext context) {
final controller = TextEditingController();
return showDialog(
context: context,
builder: (context) => SimpleDialog(
contentPadding: const EdgeInsets.all(16),
title: Text('Enter a name for the channel'),
children: [
TextField(
controller: controller,
decoration: InputDecoration(
border: OutlineInputBorder(),
),
),
ButtonBar(
children: [
FlatButton(
onPressed: () => Navigator.pop(context),
child: Text('Cancel'),
),
FlatButton(
onPressed: () => Navigator.pop(context, controller.text),
child: Text('Ok'),
),
],
),
],
),
);
}
Future _createChannel(
BuildContext context,
List<User> users, [
String name,
]) async {
final channel = client.channel('messaging', extraData: {
'members': [
client.state.user.id,
...users.map((e) => e.id),
],
if (name != null) 'name': name,
});
await channel.watch();
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) {
return StreamChannel(
child: ChannelPage(),
channel: channel,
);
},
),
);
}
void _selectUser(User user) {
if (!selectedUsers.contains(user)) {
setState(() {
selectedUsers.add(user);
});
} else {
setState(() {
selectedUsers.remove(user);
});
}
}
@override
void initState() {
super.initState();
client = StreamChat.of(context).client;
_scrollController.addListener(() async {
if (!loading &&
_scrollController.offset >=
_scrollController.position.maxScrollExtent - 100) {
offset += 25;
await _queryUsers();
}
});
_queryUsers();
}
Future<void> _queryUsers() {
loading = true;
return client.queryUsers(
pagination: PaginationParams(
limit: 25,
offset: offset,
),
sort: [
SortOption(
'name',
direction: SortOption.ASC,
),
],
).then((value) {
setState(() {
users = [
...users,
...value.users,
];
});
}).whenComplete(() => loading = false);
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
name: example
description: A new Flutter project.
version: 1.0.3+4
version: 1.0.6+7
environment:
sdk: ">=2.2.2 <3.0.0"
+11 -9
View File
@@ -120,15 +120,17 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
stream: channel.lastMessageAtStream,
initialData: channel.lastMessageAt,
builder: (context, snapshot) {
return (snapshot.data != null)
? Text(
'Active ${Jiffy(snapshot.data.toLocal()).fromNow()}',
style: StreamChatTheme.of(context)
.channelTheme
.channelHeaderTheme
.lastMessageAt,
)
: SizedBox();
if (snapshot.data == null) {
return SizedBox();
}
final jiffyDate = Jiffy(snapshot.data?.toLocal());
return Text(
'Active ${jiffyDate.isBefore(Jiffy()) ? jiffyDate.fromNow() : 'now'}',
style: StreamChatTheme.of(context)
.channelTheme
.channelHeaderTheme
.lastMessageAt,
);
},
);
}
+1
View File
@@ -42,6 +42,7 @@ class ChannelName extends StatelessWidget {
return Text(
title,
style: textStyle,
overflow: TextOverflow.ellipsis,
);
},
);
+10 -5
View File
@@ -124,18 +124,23 @@ class ChannelsBlocState extends State<ChannelsBloc>
_subscriptions.add(client.on(EventType.messageNew).listen((e) {
final newChannels = List<Channel>.from(channels ?? []);
final index = newChannels.indexWhere((c) => c.cid == e.cid);
if (index > 0) {
final channel = newChannels.removeAt(index);
newChannels.insert(0, channel);
_channelsController.add(newChannels);
if (index > -1) {
if (index > 0) {
final channel = newChannels.removeAt(index);
newChannels.insert(0, channel);
}
} else {
final hiddenIndex = _hiddenChannels.indexWhere((c) => c.cid == e.cid);
if (hiddenIndex > -1) {
newChannels.insert(0, _hiddenChannels[hiddenIndex]);
_hiddenChannels.removeAt(hiddenIndex);
_channelsController.add(newChannels);
} else {
if (client.state.channels[e.cid] != null) {
newChannels.insert(0, client.state.channels[e.cid]);
}
}
}
_channelsController.add(newChannels);
}));
}