Skip to content

Commit 5efff58

Browse files
committed
realm [nfc]: Move data here from PerAccountStore
1 parent 6b1f9af commit 5efff58

File tree

4 files changed

+173
-115
lines changed

4 files changed

+173
-115
lines changed

lib/model/realm.dart

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import '../api/model/events.dart';
12
import '../api/model/initial_snapshot.dart';
3+
import '../api/model/model.dart';
24
import 'store.dart';
35

46
/// The portion of [PerAccountStore] for realm settings, server settings,
@@ -7,12 +9,104 @@ import 'store.dart';
79
/// See also:
810
/// * [RealmStoreImpl] for the implementation of this that does the work.
911
mixin RealmStore {
12+
int get serverPresencePingIntervalSeconds;
13+
int get serverPresenceOfflineThresholdSeconds;
14+
15+
RealmWildcardMentionPolicy get realmWildcardMentionPolicy;
16+
bool get realmMandatoryTopics;
17+
/// For docs, please see [InitialSnapshot.realmWaitingPeriodThreshold].
18+
int get realmWaitingPeriodThreshold;
19+
bool get realmAllowMessageEditing;
20+
int? get realmMessageContentEditLimitSeconds;
21+
bool get realmPresenceDisabled;
22+
int get maxFileUploadSizeMib;
23+
24+
/// The display name to use for empty topics.
25+
///
26+
/// This should only be accessed when FL >= 334, since topics cannot
27+
/// be empty otherwise.
28+
// TODO(server-10) simplify this
29+
String get realmEmptyTopicDisplayName;
30+
31+
Map<String, RealmDefaultExternalAccount> get realmDefaultExternalAccounts;
32+
List<CustomProfileField> get customProfileFields;
33+
/// For docs, please see [InitialSnapshot.emailAddressVisibility].
34+
EmailAddressVisibility? get emailAddressVisibility;
1035
}
1136

1237
/// The implementation of [RealmStore] that does the work.
1338
class RealmStoreImpl extends PerAccountStoreBase with RealmStore {
1439
RealmStoreImpl({
1540
required super.core,
1641
required InitialSnapshot initialSnapshot,
17-
});
42+
}) :
43+
serverPresencePingIntervalSeconds = initialSnapshot.serverPresencePingIntervalSeconds,
44+
serverPresenceOfflineThresholdSeconds = initialSnapshot.serverPresenceOfflineThresholdSeconds,
45+
realmWildcardMentionPolicy = initialSnapshot.realmWildcardMentionPolicy,
46+
realmMandatoryTopics = initialSnapshot.realmMandatoryTopics,
47+
realmWaitingPeriodThreshold = initialSnapshot.realmWaitingPeriodThreshold,
48+
realmPresenceDisabled = initialSnapshot.realmPresenceDisabled,
49+
maxFileUploadSizeMib = initialSnapshot.maxFileUploadSizeMib,
50+
_realmEmptyTopicDisplayName = initialSnapshot.realmEmptyTopicDisplayName,
51+
realmAllowMessageEditing = initialSnapshot.realmAllowMessageEditing,
52+
realmMessageContentEditLimitSeconds = initialSnapshot.realmMessageContentEditLimitSeconds,
53+
realmDefaultExternalAccounts = initialSnapshot.realmDefaultExternalAccounts,
54+
customProfileFields = _sortCustomProfileFields(initialSnapshot.customProfileFields),
55+
emailAddressVisibility = initialSnapshot.emailAddressVisibility;
56+
57+
@override
58+
final int serverPresencePingIntervalSeconds;
59+
@override
60+
final int serverPresenceOfflineThresholdSeconds;
61+
62+
@override
63+
final RealmWildcardMentionPolicy realmWildcardMentionPolicy; // TODO(#668): update this realm setting
64+
@override
65+
final bool realmMandatoryTopics; // TODO(#668): update this realm setting
66+
@override
67+
final int realmWaitingPeriodThreshold; // TODO(#668): update this realm setting
68+
@override
69+
final bool realmAllowMessageEditing; // TODO(#668): update this realm setting
70+
@override
71+
final int? realmMessageContentEditLimitSeconds; // TODO(#668): update this realm setting
72+
@override
73+
final bool realmPresenceDisabled; // TODO(#668): update this realm setting
74+
@override
75+
final int maxFileUploadSizeMib; // No event for this.
76+
77+
@override
78+
String get realmEmptyTopicDisplayName {
79+
assert(zulipFeatureLevel >= 334); // TODO(server-10)
80+
assert(_realmEmptyTopicDisplayName != null); // TODO(log)
81+
return _realmEmptyTopicDisplayName ?? 'general chat';
82+
}
83+
final String? _realmEmptyTopicDisplayName; // TODO(#668): update this realm setting
84+
85+
@override
86+
final Map<String, RealmDefaultExternalAccount> realmDefaultExternalAccounts;
87+
88+
@override
89+
List<CustomProfileField> customProfileFields;
90+
91+
static List<CustomProfileField> _sortCustomProfileFields(List<CustomProfileField> initialCustomProfileFields) {
92+
// TODO(server): The realm-wide field objects have an `order` property,
93+
// but the actual API appears to be that the fields should be shown in
94+
// the order they appear in the array (`custom_profile_fields` in the
95+
// API; our `realmFields` array here.) See chat thread:
96+
// https://chat.zulip.org/#narrow/stream/378-api-design/topic/custom.20profile.20fields/near/1382982
97+
//
98+
// We go on to put at the start of the list any fields that are marked for
99+
// displaying in the "profile summary". (Possibly they should be at the
100+
// start of the list in the first place, but make sure just in case.)
101+
final displayFields = initialCustomProfileFields.where((e) => e.displayInProfileSummary == true);
102+
final nonDisplayFields = initialCustomProfileFields.where((e) => e.displayInProfileSummary != true);
103+
return displayFields.followedBy(nonDisplayFields).toList();
104+
}
105+
106+
@override
107+
final EmailAddressVisibility? emailAddressVisibility; // TODO(#668): update this realm setting
108+
109+
void handleCustomProfileFieldsEvent(CustomProfileFieldsEvent event) {
110+
customProfileFields = _sortCustomProfileFields(event.fields);
111+
}
18112
}

lib/model/store.dart

Lines changed: 28 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -487,19 +487,6 @@ class PerAccountStore extends PerAccountStoreBase with
487487
core: core,
488488
groups: UserGroupStoreImpl(core: core,
489489
groups: initialSnapshot.realmUserGroups),
490-
serverPresencePingIntervalSeconds: initialSnapshot.serverPresencePingIntervalSeconds,
491-
serverPresenceOfflineThresholdSeconds: initialSnapshot.serverPresenceOfflineThresholdSeconds,
492-
realmWildcardMentionPolicy: initialSnapshot.realmWildcardMentionPolicy,
493-
realmMandatoryTopics: initialSnapshot.realmMandatoryTopics,
494-
realmWaitingPeriodThreshold: initialSnapshot.realmWaitingPeriodThreshold,
495-
realmPresenceDisabled: initialSnapshot.realmPresenceDisabled,
496-
maxFileUploadSizeMib: initialSnapshot.maxFileUploadSizeMib,
497-
realmEmptyTopicDisplayName: initialSnapshot.realmEmptyTopicDisplayName,
498-
realmAllowMessageEditing: initialSnapshot.realmAllowMessageEditing,
499-
realmMessageContentEditLimitSeconds: initialSnapshot.realmMessageContentEditLimitSeconds,
500-
realmDefaultExternalAccounts: initialSnapshot.realmDefaultExternalAccounts,
501-
customProfileFields: _sortCustomProfileFields(initialSnapshot.customProfileFields),
502-
emailAddressVisibility: initialSnapshot.emailAddressVisibility,
503490
realm: RealmStoreImpl(core: core, initialSnapshot: initialSnapshot),
504491
emoji: EmojiStoreImpl(
505492
core: core, allRealmEmoji: initialSnapshot.realmEmoji),
@@ -538,19 +525,6 @@ class PerAccountStore extends PerAccountStoreBase with
538525
PerAccountStore._({
539526
required super.core,
540527
required UserGroupStoreImpl groups,
541-
required this.serverPresencePingIntervalSeconds,
542-
required this.serverPresenceOfflineThresholdSeconds,
543-
required this.realmWildcardMentionPolicy,
544-
required this.realmMandatoryTopics,
545-
required this.realmWaitingPeriodThreshold,
546-
required this.realmPresenceDisabled,
547-
required this.maxFileUploadSizeMib,
548-
required String? realmEmptyTopicDisplayName,
549-
required this.realmAllowMessageEditing,
550-
required this.realmMessageContentEditLimitSeconds,
551-
required this.realmDefaultExternalAccounts,
552-
required this.customProfileFields,
553-
required this.emailAddressVisibility,
554528
required RealmStoreImpl realm,
555529
required EmojiStoreImpl emoji,
556530
required this.userSettings,
@@ -565,7 +539,6 @@ class PerAccountStore extends PerAccountStoreBase with
565539
required this.recentDmConversationsView,
566540
required this.recentSenders,
567541
}) : _groups = groups,
568-
_realmEmptyTopicDisplayName = realmEmptyTopicDisplayName,
569542
_realm = realm,
570543
_emoji = emoji,
571544
_savedSnippets = savedSnippets,
@@ -606,36 +579,34 @@ class PerAccountStore extends PerAccountStoreBase with
606579
UserGroupStore get userGroupStore => _groups;
607580
final UserGroupStoreImpl _groups;
608581

609-
final int serverPresencePingIntervalSeconds;
610-
final int serverPresenceOfflineThresholdSeconds;
611-
612-
final RealmWildcardMentionPolicy realmWildcardMentionPolicy; // TODO(#668): update this realm setting
613-
final bool realmMandatoryTopics; // TODO(#668): update this realm setting
614-
/// For docs, please see [InitialSnapshot.realmWaitingPeriodThreshold].
615-
final int realmWaitingPeriodThreshold; // TODO(#668): update this realm setting
616-
final bool realmAllowMessageEditing; // TODO(#668): update this realm setting
617-
final int? realmMessageContentEditLimitSeconds; // TODO(#668): update this realm setting
618-
final bool realmPresenceDisabled; // TODO(#668): update this realm setting
619-
final int maxFileUploadSizeMib; // No event for this.
620-
621-
/// The display name to use for empty topics.
622-
///
623-
/// This should only be accessed when FL >= 334, since topics cannot
624-
/// be empty otherwise.
625-
// TODO(server-10) simplify this
626-
String get realmEmptyTopicDisplayName {
627-
assert(zulipFeatureLevel >= 334);
628-
assert(_realmEmptyTopicDisplayName != null); // TODO(log)
629-
return _realmEmptyTopicDisplayName ?? 'general chat';
630-
}
631-
final String? _realmEmptyTopicDisplayName; // TODO(#668): update this realm setting
632-
633-
final Map<String, RealmDefaultExternalAccount> realmDefaultExternalAccounts;
634-
List<CustomProfileField> customProfileFields;
635-
/// For docs, please see [InitialSnapshot.emailAddressVisibility].
636-
final EmailAddressVisibility? emailAddressVisibility; // TODO(#668): update this realm setting
582+
@override
583+
int get serverPresencePingIntervalSeconds => _realm.serverPresencePingIntervalSeconds;
584+
@override
585+
int get serverPresenceOfflineThresholdSeconds => _realm.serverPresenceOfflineThresholdSeconds;
586+
@override
587+
RealmWildcardMentionPolicy get realmWildcardMentionPolicy => _realm.realmWildcardMentionPolicy;
588+
@override
589+
bool get realmMandatoryTopics => _realm.realmMandatoryTopics;
590+
@override
591+
int get realmWaitingPeriodThreshold => _realm.realmWaitingPeriodThreshold;
592+
@override
593+
bool get realmAllowMessageEditing => _realm.realmAllowMessageEditing;
594+
@override
595+
int? get realmMessageContentEditLimitSeconds => _realm.realmMessageContentEditLimitSeconds;
596+
@override
597+
bool get realmPresenceDisabled => _realm.realmPresenceDisabled;
598+
@override
599+
int get maxFileUploadSizeMib => _realm.maxFileUploadSizeMib;
600+
@override
601+
String get realmEmptyTopicDisplayName => _realm.realmEmptyTopicDisplayName;
602+
@override
603+
Map<String, RealmDefaultExternalAccount> get realmDefaultExternalAccounts => _realm.realmDefaultExternalAccounts;
604+
@override
605+
List<CustomProfileField> get customProfileFields => _realm.customProfileFields;
606+
@override
607+
EmailAddressVisibility? get emailAddressVisibility => _realm.emailAddressVisibility;
637608

638-
final RealmStoreImpl _realm; // ignore: unused_field // TODO
609+
final RealmStoreImpl _realm;
639610

640611
////////////////////////////////
641612
// The realm's repertoire of available emoji.
@@ -930,7 +901,7 @@ class PerAccountStore extends PerAccountStoreBase with
930901

931902
case CustomProfileFieldsEvent():
932903
assert(debugLog("server event: custom_profile_fields"));
933-
customProfileFields = _sortCustomProfileFields(event.fields);
904+
_realm.handleCustomProfileFieldsEvent(event);
934905
notifyListeners();
935906

936907
case UserGroupEvent():
@@ -1043,21 +1014,6 @@ class PerAccountStore extends PerAccountStoreBase with
10431014
}
10441015
}
10451016

1046-
static List<CustomProfileField> _sortCustomProfileFields(List<CustomProfileField> initialCustomProfileFields) {
1047-
// TODO(server): The realm-wide field objects have an `order` property,
1048-
// but the actual API appears to be that the fields should be shown in
1049-
// the order they appear in the array (`custom_profile_fields` in the
1050-
// API; our `realmFields` array here.) See chat thread:
1051-
// https://chat.zulip.org/#narrow/stream/378-api-design/topic/custom.20profile.20fields/near/1382982
1052-
//
1053-
// We go on to put at the start of the list any fields that are marked for
1054-
// displaying in the "profile summary". (Possibly they should be at the
1055-
// start of the list in the first place, but make sure just in case.)
1056-
final displayFields = initialCustomProfileFields.where((e) => e.displayInProfileSummary == true);
1057-
final nonDisplayFields = initialCustomProfileFields.where((e) => e.displayInProfileSummary != true);
1058-
return displayFields.followedBy(nonDisplayFields).toList();
1059-
}
1060-
10611017
@override
10621018
String toString() => '${objectRuntimeType(this, 'PerAccountStore')}#${shortHash(this)}';
10631019
}

test/model/realm_test.dart

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import 'package:checks/checks.dart';
2+
import 'package:test/scaffolding.dart';
3+
import 'package:zulip/api/model/events.dart';
4+
import 'package:zulip/api/model/model.dart';
5+
6+
import '../example_data.dart' as eg;
7+
8+
void main() {
9+
group('customProfileFields', () {
10+
test('update clobbers old list', () async {
11+
final store = eg.store(initialSnapshot: eg.initialSnapshot(
12+
customProfileFields: [
13+
eg.customProfileField(0, CustomProfileFieldType.shortText),
14+
eg.customProfileField(1, CustomProfileFieldType.shortText),
15+
]));
16+
check(store.customProfileFields.map((f) => f.id)).deepEquals([0, 1]);
17+
18+
await store.handleEvent(CustomProfileFieldsEvent(id: 0, fields: [
19+
eg.customProfileField(0, CustomProfileFieldType.shortText),
20+
eg.customProfileField(2, CustomProfileFieldType.shortText),
21+
]));
22+
check(store.customProfileFields.map((f) => f.id)).deepEquals([0, 2]);
23+
});
24+
25+
test('sorts by displayInProfile', () async {
26+
// Sorts both the data from the initial snapshot…
27+
final store = eg.store(initialSnapshot: eg.initialSnapshot(
28+
customProfileFields: [
29+
eg.customProfileField(0, CustomProfileFieldType.shortText,
30+
displayInProfileSummary: false),
31+
eg.customProfileField(1, CustomProfileFieldType.shortText,
32+
displayInProfileSummary: true),
33+
eg.customProfileField(2, CustomProfileFieldType.shortText,
34+
displayInProfileSummary: false),
35+
]));
36+
check(store.customProfileFields.map((f) => f.id)).deepEquals([1, 0, 2]);
37+
38+
// … and from an event.
39+
await store.handleEvent(CustomProfileFieldsEvent(id: 0, fields: [
40+
eg.customProfileField(0, CustomProfileFieldType.shortText,
41+
displayInProfileSummary: false),
42+
eg.customProfileField(1, CustomProfileFieldType.shortText,
43+
displayInProfileSummary: false),
44+
eg.customProfileField(2, CustomProfileFieldType.shortText,
45+
displayInProfileSummary: true),
46+
]));
47+
check(store.customProfileFields.map((f) => f.id)).deepEquals([2, 0, 1]);
48+
});
49+
});
50+
}

test/model/store_test.dart

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -563,48 +563,6 @@ void main() {
563563
});
564564
});
565565

566-
group('PerAccountStore.customProfileFields', () {
567-
test('update clobbers old list', () async {
568-
final store = eg.store(initialSnapshot: eg.initialSnapshot(
569-
customProfileFields: [
570-
eg.customProfileField(0, CustomProfileFieldType.shortText),
571-
eg.customProfileField(1, CustomProfileFieldType.shortText),
572-
]));
573-
check(store.customProfileFields.map((f) => f.id)).deepEquals([0, 1]);
574-
575-
await store.handleEvent(CustomProfileFieldsEvent(id: 0, fields: [
576-
eg.customProfileField(0, CustomProfileFieldType.shortText),
577-
eg.customProfileField(2, CustomProfileFieldType.shortText),
578-
]));
579-
check(store.customProfileFields.map((f) => f.id)).deepEquals([0, 2]);
580-
});
581-
582-
test('sorts by displayInProfile', () async {
583-
// Sorts both the data from the initial snapshot…
584-
final store = eg.store(initialSnapshot: eg.initialSnapshot(
585-
customProfileFields: [
586-
eg.customProfileField(0, CustomProfileFieldType.shortText,
587-
displayInProfileSummary: false),
588-
eg.customProfileField(1, CustomProfileFieldType.shortText,
589-
displayInProfileSummary: true),
590-
eg.customProfileField(2, CustomProfileFieldType.shortText,
591-
displayInProfileSummary: false),
592-
]));
593-
check(store.customProfileFields.map((f) => f.id)).deepEquals([1, 0, 2]);
594-
595-
// … and from an event.
596-
await store.handleEvent(CustomProfileFieldsEvent(id: 0, fields: [
597-
eg.customProfileField(0, CustomProfileFieldType.shortText,
598-
displayInProfileSummary: false),
599-
eg.customProfileField(1, CustomProfileFieldType.shortText,
600-
displayInProfileSummary: false),
601-
eg.customProfileField(2, CustomProfileFieldType.shortText,
602-
displayInProfileSummary: true),
603-
]));
604-
check(store.customProfileFields.map((f) => f.id)).deepEquals([2, 0, 1]);
605-
});
606-
});
607-
608566
group('PerAccountStore.handleEvent', () {
609567
// Mostly this method just dispatches to ChannelStore and MessageStore etc.,
610568
// and so its tests generally live in the test files for those

0 commit comments

Comments
 (0)