feat: add name get, set and update on Channel
This commit is contained in:
@@ -17,6 +17,32 @@ import 'package:stream_chat/stream_chat.dart';
|
|||||||
|
|
||||||
/// Class that manages a specific channel.
|
/// Class that manages a specific channel.
|
||||||
///
|
///
|
||||||
|
/// #### Channel name
|
||||||
|
///
|
||||||
|
/// {@template name}
|
||||||
|
/// If an optional [name] argument is provided in the constructor then it
|
||||||
|
/// will be set on [extraData] with a key of 'name'.
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// final channel = Channel(client, type, id, name: 'Channel name');
|
||||||
|
/// print(channel.name == channel.extraData['name']); // true
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Before the channel is initialized the name can be set directly:
|
||||||
|
/// ```dart
|
||||||
|
/// channel.name = 'New channel name';
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// To update the name after the channel has been initialized, call:
|
||||||
|
/// ```dart
|
||||||
|
/// channel.updateName('Updated channel name');
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This will do a partial update to update the name.
|
||||||
|
/// {@endtemplate}
|
||||||
|
///
|
||||||
|
/// #### Channel image
|
||||||
|
///
|
||||||
/// {@template image}
|
/// {@template image}
|
||||||
/// If an optional [image] argument is provided in the constructor then it
|
/// If an optional [image] argument is provided in the constructor then it
|
||||||
/// will be set on [extraData] with a key of 'image'.
|
/// will be set on [extraData] with a key of 'image'.
|
||||||
@@ -31,7 +57,7 @@ import 'package:stream_chat/stream_chat.dart';
|
|||||||
/// channel.image = 'https://getstream.io/new-image';
|
/// channel.image = 'https://getstream.io/new-image';
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// To update the image after the channel has been initialized call:
|
/// To update the image after the channel has been initialized, call:
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// channel.updateImage('https://getstream.io/new-image');
|
/// channel.updateImage('https://getstream.io/new-image');
|
||||||
/// ```
|
/// ```
|
||||||
@@ -49,10 +75,12 @@ class Channel {
|
|||||||
this._id, {
|
this._id, {
|
||||||
Map<String, Object?>? extraData,
|
Map<String, Object?>? extraData,
|
||||||
String? image,
|
String? image,
|
||||||
|
String? name,
|
||||||
}) : _cid = _id != null ? '$_type:$_id' : null,
|
}) : _cid = _id != null ? '$_type:$_id' : null,
|
||||||
_extraData = {
|
_extraData = {
|
||||||
...?extraData,
|
...?extraData,
|
||||||
if (image != null) 'image': image,
|
if (image != null) 'image': image,
|
||||||
|
if (name != null) 'name': name,
|
||||||
} {
|
} {
|
||||||
_client.logger.info('New Channel instance created, not yet initialized');
|
_client.logger.info('New Channel instance created, not yet initialized');
|
||||||
}
|
}
|
||||||
@@ -98,13 +126,26 @@ class Channel {
|
|||||||
set image(String? image) {
|
set image(String? image) {
|
||||||
if (_initializedCompleter.isCompleted) {
|
if (_initializedCompleter.isCompleted) {
|
||||||
throw StateError(
|
throw StateError(
|
||||||
'Once the channel is initialized you should use channel.update '
|
'Once the channel is initialized you should use channel.updateImage '
|
||||||
'to update channel image',
|
'to update the channel image',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_extraData.addAll({'image': image});
|
_extraData.addAll({'image': image});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shortcut to set channel name.
|
||||||
|
///
|
||||||
|
/// {@macro name}
|
||||||
|
set name(String? name) {
|
||||||
|
if (_initializedCompleter.isCompleted) {
|
||||||
|
throw StateError(
|
||||||
|
'Once the channel is initialized you should use channel.updateName '
|
||||||
|
'to update the channel image',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_extraData.addAll({'name': name});
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if the channel is muted.
|
/// Returns true if the channel is muted.
|
||||||
bool get isMuted =>
|
bool get isMuted =>
|
||||||
_client.state.currentUser?.channelMutes
|
_client.state.currentUser?.channelMutes
|
||||||
@@ -279,6 +320,39 @@ class Channel {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shortcut to get channel name.
|
||||||
|
///
|
||||||
|
/// If no name is set this returns the channel cid, else null.
|
||||||
|
///
|
||||||
|
/// {@macro name}
|
||||||
|
String? get name {
|
||||||
|
if (extraData.containsKey('name')) {
|
||||||
|
final name = extraData['name']! as String;
|
||||||
|
if (name.isNotEmpty) return name;
|
||||||
|
}
|
||||||
|
return cid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Channel [name] as a stream.
|
||||||
|
///
|
||||||
|
/// If no name is set the stream returns the channel cid.
|
||||||
|
///
|
||||||
|
/// The channel needs to be initialized.
|
||||||
|
///
|
||||||
|
/// {@macro name}
|
||||||
|
Stream<String> get nameStream {
|
||||||
|
_checkInitialized();
|
||||||
|
return state!.channelStateStream.map(
|
||||||
|
(cs) {
|
||||||
|
if (cs.channel?.extraData.containsKey('name') ?? false) {
|
||||||
|
final name = cs.channel!.extraData['name']! as String;
|
||||||
|
if (name.isNotEmpty) return name;
|
||||||
|
}
|
||||||
|
return name!;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// The main Stream chat client.
|
/// The main Stream chat client.
|
||||||
StreamChatClient get client => _client;
|
StreamChatClient get client => _client;
|
||||||
final StreamChatClient _client;
|
final StreamChatClient _client;
|
||||||
@@ -862,7 +936,7 @@ class Channel {
|
|||||||
|
|
||||||
/// Update the channel's [image].
|
/// Update the channel's [image].
|
||||||
///
|
///
|
||||||
/// This is equivelant to calling [updatePartial] and providing a map with an
|
/// This is the same as calling [updatePartial] and providing a map with an
|
||||||
/// 'image' key:
|
/// 'image' key:
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
@@ -877,17 +951,28 @@ class Channel {
|
|||||||
/// ```
|
/// ```
|
||||||
Future<PartialUpdateChannelResponse> updateImage(
|
Future<PartialUpdateChannelResponse> updateImage(
|
||||||
String image,
|
String image,
|
||||||
) {
|
) =>
|
||||||
_checkInitialized();
|
updatePartial(set: {'image': image});
|
||||||
|
|
||||||
return _client.updateChannelPartial(
|
/// Update the channel's [name].
|
||||||
id!,
|
///
|
||||||
type,
|
/// This is the same as calling [updatePartial] and providing a map with a
|
||||||
set: {
|
/// 'name' key:
|
||||||
'image': image,
|
///
|
||||||
},
|
/// ```dart
|
||||||
);
|
/// channel.updatePartial(
|
||||||
}
|
/// set: {'name': 'Updated channel name'}
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Instead do:
|
||||||
|
/// ```dart
|
||||||
|
/// channel.updateName('Updated channel name');
|
||||||
|
/// ```
|
||||||
|
Future<PartialUpdateChannelResponse> updateName(
|
||||||
|
String name,
|
||||||
|
) =>
|
||||||
|
updatePartial(set: {'name': name});
|
||||||
|
|
||||||
/// Edit the channel custom data.
|
/// Edit the channel custom data.
|
||||||
Future<UpdateChannelResponse> update(
|
Future<UpdateChannelResponse> update(
|
||||||
|
|||||||
@@ -89,6 +89,28 @@ void main() {
|
|||||||
expect(newChannelInstance.image, newImage);
|
expect(newChannelInstance.image, newImage);
|
||||||
expect(newChannelInstance.extraData['image'], newImage);
|
expect(newChannelInstance.extraData['image'], newImage);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should be able to get and set `name`', () {
|
||||||
|
expect(channel.extraData.isEmpty, isTrue);
|
||||||
|
expect(
|
||||||
|
channel.name,
|
||||||
|
channelId,
|
||||||
|
reason: 'if name is not set then use channel id',
|
||||||
|
);
|
||||||
|
|
||||||
|
const name = 'Channel name';
|
||||||
|
channel.name = name;
|
||||||
|
|
||||||
|
expect(channel.name, name);
|
||||||
|
expect(channel.extraData['name'], name);
|
||||||
|
|
||||||
|
const newName = 'New channel name';
|
||||||
|
final newChannelInstance =
|
||||||
|
Channel(client, channelType, channelId, name: newName);
|
||||||
|
|
||||||
|
expect(newChannelInstance.name, newName);
|
||||||
|
expect(newChannelInstance.extraData['name'], newName);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO : test all persistence related logic in this group
|
// TODO : test all persistence related logic in this group
|
||||||
@@ -217,6 +239,14 @@ void main() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should throw if trying to set `name`', () {
|
||||||
|
try {
|
||||||
|
channel.name = 'New name';
|
||||||
|
} catch (e) {
|
||||||
|
expect(e, isA<StateError>());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
group('`.sendMessage`', () {
|
group('`.sendMessage`', () {
|
||||||
test('should work fine', () async {
|
test('should work fine', () async {
|
||||||
final message = Message(id: 'test-message-id');
|
final message = Message(id: 'test-message-id');
|
||||||
@@ -1246,6 +1276,35 @@ void main() {
|
|||||||
).called(1);
|
).called(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('`.updateName`', () async {
|
||||||
|
const name = 'Name';
|
||||||
|
|
||||||
|
final channelModel = ChannelModel(
|
||||||
|
cid: channelCid,
|
||||||
|
extraData: {'name': name},
|
||||||
|
);
|
||||||
|
|
||||||
|
when(() => client.updateChannelPartial(
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
set: {'name': name},
|
||||||
|
)).thenAnswer(
|
||||||
|
(_) async => PartialUpdateChannelResponse()..channel = channelModel,
|
||||||
|
);
|
||||||
|
final res = await channel.updateName(name);
|
||||||
|
|
||||||
|
expect(res, isNotNull);
|
||||||
|
expect(res.channel.extraData['name'], name);
|
||||||
|
|
||||||
|
verify(
|
||||||
|
() => client.updateChannelPartial(
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
set: {'name': name},
|
||||||
|
),
|
||||||
|
).called(1);
|
||||||
|
});
|
||||||
|
|
||||||
test('`.updatePartial`', () async {
|
test('`.updatePartial`', () async {
|
||||||
const set = {
|
const set = {
|
||||||
'name': 'Stream Team',
|
'name': 'Stream Team',
|
||||||
|
|||||||
@@ -329,21 +329,9 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extensions can be used to add functionality to the SDK. In the examples
|
/// Extensions can be used to add functionality to the SDK. In the example
|
||||||
/// below, we add two simple extensions to the [StreamChatClient] and [Channel].
|
/// below, we add a simple extensions to the [StreamChatClient].
|
||||||
extension on StreamChatClient {
|
extension on StreamChatClient {
|
||||||
/// Fetches the current user id.
|
/// Fetches the current user id.
|
||||||
String get uid => state.currentUser!.id;
|
String get uid => state.currentUser!.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
extension on Channel {
|
|
||||||
/// Fetches the name of the channel by accessing [extraData] or [cid].
|
|
||||||
String? get name {
|
|
||||||
final _channelName = extraData['name'];
|
|
||||||
if (_channelName != null) {
|
|
||||||
return _channelName as String;
|
|
||||||
} else {
|
|
||||||
return cid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user