migrate sample app
This commit is contained in:
@@ -27,7 +27,7 @@ class Channel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a channel client instance from a [ChannelState] object
|
/// Create a channel client instance from a [ChannelState] object
|
||||||
Channel.fromState(this._client, ChannelState channelState) {
|
Channel.fromState(this._client, ChannelState channelState) : _extraData = {} {
|
||||||
_cid = channelState.channel!.cid;
|
_cid = channelState.channel!.cid;
|
||||||
_id = channelState.channel!.id;
|
_id = channelState.channel!.id;
|
||||||
type = channelState.channel!.type;
|
type = channelState.channel!.type;
|
||||||
@@ -45,9 +45,9 @@ class Channel {
|
|||||||
|
|
||||||
String? _id;
|
String? _id;
|
||||||
String? _cid;
|
String? _cid;
|
||||||
Map<String, dynamic>? _extraData;
|
Map<String, dynamic> _extraData;
|
||||||
|
|
||||||
set extraData(Map<String, dynamic>? extraData) {
|
set extraData(Map<String, dynamic> extraData) {
|
||||||
if (_initializedCompleter.isCompleted) {
|
if (_initializedCompleter.isCompleted) {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
'Once the channel is initialized you should use channel.update '
|
'Once the channel is initialized you should use channel.update '
|
||||||
@@ -189,7 +189,7 @@ class Channel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Channel extra data
|
/// Channel extra data
|
||||||
Map<String, dynamic>? get extraData =>
|
Map<String, dynamic> get extraData =>
|
||||||
state?._channelState.channel?.extraData ?? _extraData;
|
state?._channelState.channel?.extraData ?? _extraData;
|
||||||
|
|
||||||
/// Channel extra data as a stream
|
/// Channel extra data as a stream
|
||||||
@@ -1028,7 +1028,7 @@ class Channel {
|
|||||||
})
|
})
|
||||||
..addAll(options);
|
..addAll(options);
|
||||||
|
|
||||||
if (_extraData != null) {
|
if (_extraData.isNotEmpty) {
|
||||||
payload['data'] = _extraData;
|
payload['data'] = _extraData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1684,8 +1684,7 @@ class ChannelClientState {
|
|||||||
...messages,
|
...messages,
|
||||||
];
|
];
|
||||||
|
|
||||||
newThreads[parentId]!
|
newThreads[parentId]!.sort(_sortByCreatedAt);
|
||||||
.sort(_sortByCreatedAt as int Function(Message, Message)?);
|
|
||||||
} else {
|
} else {
|
||||||
newThreads[parentId] = messages;
|
newThreads[parentId] = messages;
|
||||||
}
|
}
|
||||||
@@ -1712,7 +1711,7 @@ class ChannelClientState {
|
|||||||
.any((newMessage) => newMessage.id == m.id) !=
|
.any((newMessage) => newMessage.id == m.id) !=
|
||||||
true)
|
true)
|
||||||
.toList(),
|
.toList(),
|
||||||
]..sort(_sortByCreatedAt as int Function(Message, Message)?);
|
]..sort(_sortByCreatedAt);
|
||||||
|
|
||||||
final newWatchers = <User>[
|
final newWatchers = <User>[
|
||||||
...updatedState.watchers,
|
...updatedState.watchers,
|
||||||
@@ -1751,17 +1750,8 @@ class ChannelClientState {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
int? _sortByCreatedAt(a, b) {
|
int _sortByCreatedAt(Message a, Message b) =>
|
||||||
if (a.createdAt == null) {
|
a.createdAt.compareTo(b.createdAt);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b.createdAt == null) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.createdAt.compareTo(b.createdAt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The channel state related to this client
|
/// The channel state related to this client
|
||||||
ChannelState get _channelState => _channelStateController.value!;
|
ChannelState get _channelState => _channelStateController.value!;
|
||||||
@@ -1799,15 +1789,15 @@ class ChannelClientState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Channel related typing users last value
|
/// Channel related typing users last value
|
||||||
List<User>? get typingEvents => _typingEventsController.value as List<User>?;
|
List<User> get typingEvents => _typingEventsController.value!;
|
||||||
|
|
||||||
/// Channel related typing users stream
|
/// Channel related typing users stream
|
||||||
Stream<List<User?>> get typingEventsStream => _typingEventsController.stream;
|
Stream<List<User>> get typingEventsStream => _typingEventsController.stream;
|
||||||
final BehaviorSubject<List<User?>> _typingEventsController =
|
final BehaviorSubject<List<User>> _typingEventsController =
|
||||||
BehaviorSubject.seeded([]);
|
BehaviorSubject.seeded([]);
|
||||||
|
|
||||||
final Channel _channel;
|
final Channel _channel;
|
||||||
final Map<User?, DateTime> _typings = {};
|
final Map<User, DateTime> _typings = {};
|
||||||
|
|
||||||
void _listenTypingEvents() {
|
void _listenTypingEvents() {
|
||||||
if (_channelState.channel?.config.typingEvents == false) {
|
if (_channelState.channel?.config.typingEvents == false) {
|
||||||
@@ -1818,9 +1808,12 @@ class ChannelClientState {
|
|||||||
..add(
|
..add(
|
||||||
_channel.on(EventType.typingStart).listen(
|
_channel.on(EventType.typingStart).listen(
|
||||||
(event) {
|
(event) {
|
||||||
if (event.user!.id != _channel.client.state.user!.id) {
|
if (event.user != null) {
|
||||||
_typings[event.user] = DateTime.now();
|
final user = event.user!;
|
||||||
_typingEventsController.add(_typings.keys.toList());
|
if (user.id != _channel.client.state.user?.id) {
|
||||||
|
_typings[user] = DateTime.now();
|
||||||
|
_typingEventsController.add(_typings.keys.toList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -1828,9 +1821,12 @@ class ChannelClientState {
|
|||||||
..add(
|
..add(
|
||||||
_channel.on(EventType.typingStop).listen(
|
_channel.on(EventType.typingStop).listen(
|
||||||
(event) {
|
(event) {
|
||||||
if (event.user!.id != _channel.client.state.user!.id) {
|
if (event.user != null) {
|
||||||
_typings.remove(event.user);
|
final user = event.user!;
|
||||||
_typingEventsController.add(_typings.keys.toList());
|
if (user.id != _channel.client.state.user?.id) {
|
||||||
|
_typings.remove(event.user);
|
||||||
|
_typingEventsController.add(_typings.keys.toList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -780,10 +780,11 @@ class StreamChatClient {
|
|||||||
PaginationParams paginationParams = const PaginationParams(),
|
PaginationParams paginationParams = const PaginationParams(),
|
||||||
}) async {
|
}) async {
|
||||||
final offlineChannels = (await _chatPersistenceClient?.getChannelStates(
|
final offlineChannels = (await _chatPersistenceClient?.getChannelStates(
|
||||||
filter: filter,
|
filter: filter,
|
||||||
sort: sort,
|
sort: sort,
|
||||||
paginationParams: paginationParams,
|
paginationParams: paginationParams,
|
||||||
))!;
|
)) ??
|
||||||
|
[];
|
||||||
final updatedData = _mapChannelStateToChannel(offlineChannels);
|
final updatedData = _mapChannelStateToChannel(offlineChannels);
|
||||||
state.channels = updatedData.key;
|
state.channels = updatedData.key;
|
||||||
return updatedData.value;
|
return updatedData.value;
|
||||||
@@ -1193,7 +1194,7 @@ class StreamChatClient {
|
|||||||
Channel channel(
|
Channel channel(
|
||||||
String type, {
|
String type, {
|
||||||
String? id,
|
String? id,
|
||||||
Map<String, dynamic>? extraData,
|
Map<String, dynamic> extraData = const {},
|
||||||
}) {
|
}) {
|
||||||
if (id != null && state.channels?.containsKey('$type:$id') == true) {
|
if (id != null && state.channels?.containsKey('$type:$id') == true) {
|
||||||
if (state.channels!['$type:$id'] != null) {
|
if (state.channels!['$type:$id'] != null) {
|
||||||
|
|||||||
@@ -516,7 +516,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
await channelClient.watch();
|
await channelClient.watch();
|
||||||
|
|
||||||
final event = Event(type: EventType.any);
|
final event = const Event(type: EventType.any);
|
||||||
|
|
||||||
when(
|
when(
|
||||||
() => mockDio.post<String>(
|
() => mockDio.post<String>(
|
||||||
@@ -564,7 +564,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
await channelClient.watch();
|
await channelClient.watch();
|
||||||
|
|
||||||
final event = Event(type: EventType.typingStart);
|
final event = const Event(type: EventType.typingStart);
|
||||||
|
|
||||||
when(
|
when(
|
||||||
() => mockDio.post<String>(
|
() => mockDio.post<String>(
|
||||||
@@ -610,7 +610,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
await channelClient.watch();
|
await channelClient.watch();
|
||||||
|
|
||||||
final event = Event(type: EventType.typingStop);
|
final event = const Event(type: EventType.typingStop);
|
||||||
|
|
||||||
when(
|
when(
|
||||||
() => mockDio.post<String>(
|
() => mockDio.post<String>(
|
||||||
@@ -901,8 +901,10 @@ void main() {
|
|||||||
'presence': true,
|
'presence': true,
|
||||||
};
|
};
|
||||||
|
|
||||||
when(() => mockDio.post<String>('/channels/messaging/query',
|
when(() => mockDio.post<String>(
|
||||||
data: options)).thenAnswer(
|
'/channels/messaging/query',
|
||||||
|
data: options,
|
||||||
|
)).thenAnswer(
|
||||||
(_) async => Response(
|
(_) async => Response(
|
||||||
data: r'''
|
data: r'''
|
||||||
{
|
{
|
||||||
@@ -1198,8 +1200,10 @@ void main() {
|
|||||||
|
|
||||||
final response = await channelClient.query(options: options);
|
final response = await channelClient.query(options: options);
|
||||||
|
|
||||||
verify(() => mockDio.post<String>('/channels/messaging/query',
|
verify(() => mockDio.post<String>(
|
||||||
data: options)).called(1);
|
'/channels/messaging/query',
|
||||||
|
data: options,
|
||||||
|
)).called(1);
|
||||||
expect(channelClient.id, response.channel?.id);
|
expect(channelClient.id, response.channel?.id);
|
||||||
expect(channelClient.cid, response.channel?.cid);
|
expect(channelClient.cid, response.channel?.cid);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ analyzer:
|
|||||||
- lib/**/*.g.dart
|
- lib/**/*.g.dart
|
||||||
- lib/**/*.freezed.dart
|
- lib/**/*.freezed.dart
|
||||||
- example/*
|
- example/*
|
||||||
|
- test/*
|
||||||
linter:
|
linter:
|
||||||
rules:
|
rules:
|
||||||
- always_use_package_imports
|
- always_use_package_imports
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ class StreamExample extends StatelessWidget {
|
|||||||
/// If you'd prefer using pre-made UI widgets for your app, please see our other
|
/// If you'd prefer using pre-made UI widgets for your app, please see our other
|
||||||
/// package, `stream_chat_flutter`.
|
/// package, `stream_chat_flutter`.
|
||||||
const StreamExample({
|
const StreamExample({
|
||||||
Key key,
|
Key? key,
|
||||||
@required this.client,
|
required this.client,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// Instance of Stream Client.
|
/// Instance of Stream Client.
|
||||||
@@ -55,7 +55,7 @@ class StreamExample extends StatelessWidget {
|
|||||||
home: HomeScreen(),
|
home: HomeScreen(),
|
||||||
builder: (context, child) => StreamChatCore(
|
builder: (context, child) => StreamChatCore(
|
||||||
client: client,
|
client: client,
|
||||||
child: child,
|
child: child!,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ class HomeScreen extends StatelessWidget {
|
|||||||
'type': 'messaging',
|
'type': 'messaging',
|
||||||
'members': {
|
'members': {
|
||||||
r'$in': [
|
r'$in': [
|
||||||
StreamChatCore.of(context).user.id,
|
StreamChatCore.of(context).user!.id,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -100,10 +100,13 @@ class HomeScreen extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
errorBuilder: (BuildContext context, dynamic error) {
|
errorBuilder: (
|
||||||
|
BuildContext context,
|
||||||
|
dynamic error,
|
||||||
|
) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Oh no, something went wrong. Please check your config.'),
|
'Oh no, something went wrong. Please check your config. ${error}'),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
listBuilder: (
|
listBuilder: (
|
||||||
@@ -112,20 +115,20 @@ class HomeScreen extends StatelessWidget {
|
|||||||
) =>
|
) =>
|
||||||
LazyLoadScrollView(
|
LazyLoadScrollView(
|
||||||
onEndOfPage: () async {
|
onEndOfPage: () async {
|
||||||
channelListController.paginateData();
|
channelListController.paginateData!();
|
||||||
},
|
},
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
itemCount: channels.length,
|
itemCount: channels.length,
|
||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
final _item = channels[index];
|
final _item = channels[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_item.name),
|
title: Text(_item.name!),
|
||||||
subtitle: StreamBuilder<Message>(
|
subtitle: StreamBuilder<Message?>(
|
||||||
stream: _item.state.lastMessageStream,
|
stream: _item.state!.lastMessageStream,
|
||||||
initialData: _item.state.lastMessage,
|
initialData: _item.state!.lastMessage,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
return Text(snapshot.data.text);
|
return Text(snapshot.data!.text!);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SizedBox();
|
return SizedBox();
|
||||||
@@ -169,8 +172,8 @@ class MessageScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MessageScreenState extends State<MessageScreen> {
|
class _MessageScreenState extends State<MessageScreen> {
|
||||||
TextEditingController _controller;
|
late final TextEditingController _controller;
|
||||||
ScrollController _scrollController;
|
late final ScrollController _scrollController;
|
||||||
final messageListController = MessageListController();
|
final messageListController = MessageListController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -203,11 +206,11 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: StreamBuilder<List<User>>(
|
title: StreamBuilder<List<User>>(
|
||||||
initialData: channel.state.typingEvents,
|
initialData: channel.state?.typingEvents,
|
||||||
stream: channel.state.typingEventsStream,
|
stream: channel.state?.typingEventsStream,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData && snapshot.data.isNotEmpty) {
|
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||||
return Text('${snapshot.data.first.name} is typing...');
|
return Text('${snapshot.data!.first.name} is typing...');
|
||||||
}
|
}
|
||||||
return SizedBox();
|
return SizedBox();
|
||||||
},
|
},
|
||||||
@@ -219,7 +222,7 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: LazyLoadScrollView(
|
child: LazyLoadScrollView(
|
||||||
onEndOfPage: () async {
|
onEndOfPage: () async {
|
||||||
messageListController.paginateData();
|
messageListController.paginateData!();
|
||||||
},
|
},
|
||||||
child: MessageListCore(
|
child: MessageListCore(
|
||||||
emptyBuilder: (BuildContext context) {
|
emptyBuilder: (BuildContext context) {
|
||||||
@@ -247,12 +250,12 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
final item = messages[index];
|
final item = messages[index];
|
||||||
final client = StreamChatCore.of(context).client;
|
final client = StreamChatCore.of(context).client;
|
||||||
if (item.user.id == client.uid) {
|
if (item.user!.id == client.uid) {
|
||||||
return Align(
|
return Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(item.text),
|
child: Text(item.text!),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -260,7 +263,7 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(item.text),
|
child: Text(item.text!),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -268,7 +271,7 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
errorWidgetBuilder: (BuildContext context, error) {
|
errorWidgetBuilder: (BuildContext context, error) {
|
||||||
print(error?.toString());
|
print(error.toString());
|
||||||
return Center(
|
return Center(
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 100.0,
|
height: 100.0,
|
||||||
@@ -282,7 +285,7 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -308,7 +311,7 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: const Padding(
|
child: const Padding(
|
||||||
padding: EdgeInsets.all(8.0),
|
padding: EdgeInsets.all(8),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.send,
|
Icons.send,
|
||||||
@@ -332,12 +335,12 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
/// below, we add two simple extensions to the [StreamChatClient] and [Channel].
|
/// below, we add two simple extensions to the [StreamChatClient] and [Channel].
|
||||||
extension on StreamChatClient {
|
extension on StreamChatClient {
|
||||||
/// Fetches the current user id.
|
/// Fetches the current user id.
|
||||||
String get uid => state.user.id;
|
String get uid => state.user!.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
extension on Channel {
|
extension on Channel {
|
||||||
/// Fetches the name of the channel by accessing [extraData] or [cid].
|
/// Fetches the name of the channel by accessing [extraData] or [cid].
|
||||||
String get name {
|
String? get name {
|
||||||
final _channelName = extraData['name'];
|
final _channelName = extraData['name'];
|
||||||
if (_channelName != null) {
|
if (_channelName != null) {
|
||||||
return _channelName;
|
return _channelName;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
version: 1.0.0+1
|
version: 1.0.0+1
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.7.0 <3.0.0"
|
sdk: '>=2.12.0 <3.0.0'
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ class ChannelListCoreState extends State<ChannelListCore> {
|
|||||||
stream: channelsBlocState.channelsStream,
|
stream: channelsBlocState.channelsStream,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) {
|
if (snapshot.hasError) {
|
||||||
|
print('snapshot: ${snapshot.stackTrace}');
|
||||||
return widget.errorBuilder(context, snapshot.error!);
|
return widget.errorBuilder(context, snapshot.error!);
|
||||||
}
|
}
|
||||||
if (!snapshot.hasData) {
|
if (!snapshot.hasData) {
|
||||||
|
|||||||
@@ -779,8 +779,8 @@ void main() {
|
|||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
final channels = _generateChannels(mockClient);
|
final channels = _generateChannels(mockClient);
|
||||||
int channelComparator(Channel a, Channel b) {
|
int channelComparator(Channel a, Channel b) {
|
||||||
final aData = a.extraData!['extra_data_key'] as String;
|
final aData = a.extraData['extra_data_key'] as String;
|
||||||
final bData = b.extraData!['extra_data_key'] as String;
|
final bData = b.extraData['extra_data_key'] as String;
|
||||||
return bData.compareTo(aData);
|
return bData.compareTo(aData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user