Skip to content

store: Update streams and subscriptions on stream-create/delete events #183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions lib/api/model/events.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ abstract class Event {
case 'update': return RealmUserUpdateEvent.fromJson(json);
default: return UnexpectedEvent.fromJson(json);
}
case 'stream':
final op = json['op'] as String;
switch (op) {
case 'create': return StreamCreateEvent.fromJson(json);
case 'delete': return StreamDeleteEvent.fromJson(json);
// TODO(#182): case 'update': …
default: return UnexpectedEvent.fromJson(json);
}
case 'message': return MessageEvent.fromJson(json);
case 'heartbeat': return HeartbeatEvent.fromJson(json);
// TODO add many more event types
Expand Down Expand Up @@ -179,6 +187,54 @@ class RealmUserUpdateEvent extends RealmUserEvent {
Map<String, dynamic> toJson() => _$RealmUserUpdateEventToJson(this);
}

/// A Zulip event of type `stream`.
abstract class StreamEvent extends Event {
@override
@JsonKey(includeToJson: true)
String get type => 'stream';

String get op;

StreamEvent({required super.id});
}

/// A [StreamEvent] with op `create`: https://zulip.com/api/get-events#stream-create
@JsonSerializable(fieldRename: FieldRename.snake)
class StreamCreateEvent extends StreamEvent {
@override
String get op => 'create';

final List<ZulipStream> streams;

StreamCreateEvent({required super.id, required this.streams});

factory StreamCreateEvent.fromJson(Map<String, dynamic> json) =>
_$StreamCreateEventFromJson(json);

@override
Map<String, dynamic> toJson() => _$StreamCreateEventToJson(this);
}

/// A [StreamEvent] with op `delete`: https://zulip.com/api/get-events#stream-delete
@JsonSerializable(fieldRename: FieldRename.snake)
class StreamDeleteEvent extends StreamEvent {
@override
String get op => 'delete';

final List<ZulipStream> streams;

StreamDeleteEvent({required super.id, required this.streams});

factory StreamDeleteEvent.fromJson(Map<String, dynamic> json) =>
_$StreamDeleteEventFromJson(json);

@override
Map<String, dynamic> toJson() => _$StreamDeleteEventToJson(this);
}

// TODO(#182) StreamUpdateEvent, for a [StreamEvent] with op `update`:
// https://zulip.com/api/get-events#stream-update

/// A Zulip event of type `message`.
// TODO use [JsonSerializable] here too, using its customization features,
// in order to skip the boilerplate in [fromJson] and [toJson].
Expand Down
30 changes: 30 additions & 0 deletions lib/api/model/events.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions lib/model/store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,19 @@ class PerAccountStore extends ChangeNotifier {
}
autocompleteViewManager.handleRealmUserUpdateEvent(event);
notifyListeners();
} else if (event is StreamCreateEvent) {
assert(debugLog("server event: stream/create"));
streams.addEntries(event.streams.map((stream) => MapEntry(stream.streamId, stream)));
// (Don't touch `subscriptions`. If the user is subscribed to the stream,
// details will come in a later `subscription` event.)
notifyListeners();
} else if (event is StreamDeleteEvent) {
assert(debugLog("server event: stream/delete"));
for (final stream in event.streams) {
streams.remove(stream.streamId);
subscriptions.remove(stream.streamId);
}
notifyListeners();
} else if (event is MessageEvent) {
assert(debugLog("server event: message ${jsonEncode(event.message.toJson())}"));
for (final view in _messageListViews) {
Expand Down
8 changes: 8 additions & 0 deletions test/model/test_store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,12 @@ extension PerAccountStoreTestExtension on PerAccountStore {
addUser(user);
}
}

void addStream(ZulipStream stream) {
addStreams([stream]);
}

void addStreams(List<ZulipStream> streams) {
handleEvent(StreamCreateEvent(id: 1, streams: streams));
}
}