Skip to content

Commit ab2bbbf

Browse files
PIG208gnprice
authored andcommitted
model: Add PerAccountStore.savedSnippets, updating with events
1 parent 477a777 commit ab2bbbf

File tree

6 files changed

+125
-3
lines changed

6 files changed

+125
-3
lines changed

lib/model/saved_snippet.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import 'package:collection/collection.dart';
2+
3+
import '../api/model/events.dart';
4+
import '../api/model/model.dart';
5+
import 'store.dart';
6+
7+
mixin SavedSnippetStore {
8+
Map<int, SavedSnippet> get savedSnippets;
9+
}
10+
11+
class SavedSnippetStoreImpl extends PerAccountStoreBase with SavedSnippetStore {
12+
SavedSnippetStoreImpl({
13+
required super.core,
14+
required Iterable<SavedSnippet> savedSnippets,
15+
}) : _savedSnippets = {
16+
for (final savedSnippet in savedSnippets)
17+
savedSnippet.id: savedSnippet,
18+
};
19+
20+
@override
21+
late Map<int, SavedSnippet> savedSnippets = UnmodifiableMapView(_savedSnippets);
22+
final Map<int, SavedSnippet> _savedSnippets;
23+
24+
void handleSavedSnippetsEvent(SavedSnippetsEvent event) {
25+
switch (event) {
26+
case SavedSnippetsAddEvent(:final savedSnippet):
27+
_savedSnippets[savedSnippet.id] = savedSnippet;
28+
29+
case SavedSnippetsUpdateEvent(:final savedSnippet):
30+
assert(_savedSnippets[savedSnippet.id]!.dateCreated
31+
== savedSnippet.dateCreated); // TODO(log)
32+
_savedSnippets[savedSnippet.id] = savedSnippet;
33+
34+
case SavedSnippetsRemoveEvent(:final savedSnippetId):
35+
_savedSnippets.remove(savedSnippetId);
36+
}
37+
}
38+
}

lib/model/store.dart

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import 'message_list.dart';
2929
import 'recent_dm_conversations.dart';
3030
import 'recent_senders.dart';
3131
import 'channel.dart';
32+
import 'saved_snippet.dart';
3233
import 'settings.dart';
3334
import 'typing_status.dart';
3435
import 'unreads.dart';
@@ -431,7 +432,7 @@ Uri? tryResolveUrl(Uri baseUrl, String reference) {
431432
/// This class does not attempt to poll an event queue
432433
/// to keep the data up to date. For that behavior, see
433434
/// [UpdateMachine].
434-
class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStore, UserStore, ChannelStore, MessageStore {
435+
class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStore, SavedSnippetStore, UserStore, ChannelStore, MessageStore {
435436
/// Construct a store for the user's data, starting from the given snapshot.
436437
///
437438
/// The global store must already have been updated with
@@ -486,6 +487,8 @@ class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStor
486487
emoji: EmojiStoreImpl(
487488
core: core, allRealmEmoji: initialSnapshot.realmEmoji),
488489
userSettings: initialSnapshot.userSettings,
490+
savedSnippets: SavedSnippetStoreImpl(
491+
core: core, savedSnippets: initialSnapshot.savedSnippets ?? []),
489492
typingNotifier: TypingNotifier(
490493
core: core,
491494
typingStoppedWaitPeriod: Duration(
@@ -524,6 +527,7 @@ class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStor
524527
required this.emailAddressVisibility,
525528
required EmojiStoreImpl emoji,
526529
required this.userSettings,
530+
required SavedSnippetStoreImpl savedSnippets,
527531
required this.typingNotifier,
528532
required UserStoreImpl users,
529533
required this.typingStatus,
@@ -534,6 +538,7 @@ class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStor
534538
required this.recentSenders,
535539
}) : _realmEmptyTopicDisplayName = realmEmptyTopicDisplayName,
536540
_emoji = emoji,
541+
_savedSnippets = savedSnippets,
537542
_users = users,
538543
_channels = channels,
539544
_messages = messages;
@@ -624,6 +629,10 @@ class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStor
624629

625630
final UserSettings? userSettings; // TODO(server-5)
626631

632+
@override
633+
Map<int, SavedSnippet> get savedSnippets => _savedSnippets.savedSnippets;
634+
final SavedSnippetStoreImpl _savedSnippets;
635+
627636
final TypingNotifier typingNotifier;
628637

629638
////////////////////////////////
@@ -872,8 +881,9 @@ class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStor
872881
notifyListeners();
873882

874883
case SavedSnippetsEvent():
875-
// TODO handle
876-
break;
884+
assert(debugLog('server event: saved_snippets/${event.op}'));
885+
_savedSnippets.handleSavedSnippetsEvent(event);
886+
notifyListeners();
877887

878888
case ChannelEvent():
879889
assert(debugLog("server event: stream/${event.op}"));

test/api/model/model_checks.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ extension UserChecks on Subject<User> {
2121
Subject<bool> get isSystemBot => has((x) => x.isSystemBot, 'isSystemBot');
2222
}
2323

24+
extension SavedSnippetChecks on Subject<SavedSnippet> {
25+
Subject<int> get id => has((x) => x.id, 'id');
26+
Subject<String> get title => has((x) => x.title, 'title');
27+
Subject<String> get content => has((x) => x.content, 'content');
28+
Subject<int> get dateCreated => has((x) => x.dateCreated, 'dateCreated');
29+
}
30+
2431
extension ZulipStreamChecks on Subject<ZulipStream> {
2532
}
2633

test/example_data.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,28 @@ final User thirdUser = user(fullName: 'Third User');
286286

287287
final User fourthUser = user(fullName: 'Fourth User');
288288

289+
////////////////////////////////////////////////////////////////
290+
// Data attached to the self-account on the realm
291+
//
292+
293+
int _nextSavedSnippetId() => _lastSavedSnippetId++;
294+
int _lastSavedSnippetId = 1;
295+
296+
SavedSnippet savedSnippet({
297+
int? id,
298+
String? title,
299+
String? content,
300+
int? dateCreated,
301+
}) {
302+
_checkPositive(id, 'saved snippet ID');
303+
return SavedSnippet(
304+
id: id ?? _nextSavedSnippetId(),
305+
title: title ?? 'A saved snippet',
306+
content: content ?? 'foo bar baz',
307+
dateCreated: dateCreated ?? 1234567890, // TODO generate timestamp
308+
);
309+
}
310+
289311
////////////////////////////////////////////////////////////////
290312
// Streams and subscriptions.
291313
//

test/model/saved_snippet_test.dart

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import 'package:checks/checks.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
import 'package:zulip/api/model/events.dart';
4+
import 'package:zulip/api/model/model.dart';
5+
6+
import '../api/model/model_checks.dart';
7+
import '../example_data.dart' as eg;
8+
import 'store_checks.dart';
9+
10+
void main() {
11+
test('handleSavedSnippetsEvent', () async {
12+
final store = eg.store(initialSnapshot: eg.initialSnapshot(
13+
savedSnippets: [eg.savedSnippet(id: 101)]));
14+
check(store).savedSnippets.values.single.id.equals(101);
15+
16+
await store.handleEvent(SavedSnippetsAddEvent(id: 1,
17+
savedSnippet: eg.savedSnippet(
18+
id: 102,
19+
title: 'foo title',
20+
content: 'foo content',
21+
)));
22+
check(store).savedSnippets.values.deepEquals(<Condition<Object?>>[
23+
(it) => it.isA<SavedSnippet>().id.equals(101),
24+
(it) => it.isA<SavedSnippet>()..id.equals(102)
25+
..title.equals('foo title')
26+
..content.equals('foo content')
27+
]);
28+
29+
await store.handleEvent(SavedSnippetsRemoveEvent(id: 1, savedSnippetId: 101));
30+
check(store).savedSnippets.values.single.id.equals(102);
31+
32+
await store.handleEvent(SavedSnippetsUpdateEvent(id: 1,
33+
savedSnippet: eg.savedSnippet(
34+
id: 102,
35+
title: 'bar title',
36+
content: 'bar content',
37+
dateCreated: store.savedSnippets.values.single.dateCreated,
38+
)));
39+
check(store).savedSnippets.values.single
40+
..id.equals(102)
41+
..title.equals('bar title')
42+
..content.equals('bar content');
43+
});
44+
}

test/model/store_checks.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ extension PerAccountStoreChecks on Subject<PerAccountStore> {
5656
Subject<Account> get account => has((x) => x.account, 'account');
5757
Subject<int> get selfUserId => has((x) => x.selfUserId, 'selfUserId');
5858
Subject<UserSettings?> get userSettings => has((x) => x.userSettings, 'userSettings');
59+
Subject<Map<int, SavedSnippet>> get savedSnippets => has((x) => x.savedSnippets, 'savedSnippets');
5960
Subject<Map<int, ZulipStream>> get streams => has((x) => x.streams, 'streams');
6061
Subject<Map<String, ZulipStream>> get streamsByName => has((x) => x.streamsByName, 'streamsByName');
6162
Subject<Map<int, Subscription>> get subscriptions => has((x) => x.subscriptions, 'subscriptions');

0 commit comments

Comments
 (0)