Skip to content

Commit 391b56a

Browse files
committed
model [nfc]: Move has-passed-waiting-period method to RealmStore
1 parent 4495100 commit 391b56a

File tree

6 files changed

+70
-46
lines changed

6 files changed

+70
-46
lines changed

lib/model/channel.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ mixin ChannelStore on UserStore {
213213
case ChannelPostPolicy.fullMembers: {
214214
if (!role.isAtLeast(UserRole.member)) return false;
215215
if (role == UserRole.member) {
216-
return hasPassedWaitingPeriod(selfUser, byDate: byDate);
216+
return selfHasPassedWaitingPeriod(byDate: byDate);
217217
}
218218
return true;
219219
}

lib/model/message.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ mixin MessageStore on ChannelStore {
186186
case RealmDeleteOwnMessagePolicy.fullMembers: {
187187
if (!role.isAtLeast(UserRole.member)) return false;
188188
if (role == UserRole.member) {
189-
return hasPassedWaitingPeriod(selfUser, byDate: atDate);
189+
return selfHasPassedWaitingPeriod(byDate: atDate);
190190
}
191191
return true;
192192
}

lib/model/realm.dart

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,16 @@ mixin RealmStore on PerAccountStoreBase, UserGroupStore {
128128
return topic;
129129
}
130130

131+
/// Whether the self-user has passed the realm's waiting period
132+
/// to be a full member.
133+
///
134+
/// See:
135+
/// https://zulip.com/api/roles-and-permissions#determining-if-a-user-is-a-full-member
136+
///
137+
/// To determine if the self-user is a full member,
138+
/// callers must also check that the user's role is at least [UserRole.member].
139+
bool selfHasPassedWaitingPeriod({required DateTime byDate});
140+
131141
/// Whether the self-user has the given (group-based) permission.
132142
bool selfHasPermissionForGroupSetting(GroupSettingValue value,
133143
GroupSettingType type, String name);
@@ -180,6 +190,9 @@ mixin ProxyRealmStore on RealmStore {
180190
@override
181191
List<CustomProfileField> get customProfileFields => realmStore.customProfileFields;
182192
@override
193+
bool selfHasPassedWaitingPeriod({required DateTime byDate}) =>
194+
realmStore.selfHasPassedWaitingPeriod(byDate: byDate);
195+
@override
183196
bool selfHasPermissionForGroupSetting(GroupSettingValue value, GroupSettingType type, String name) =>
184197
realmStore.selfHasPermissionForGroupSetting(value, type, name);
185198
}
@@ -203,6 +216,7 @@ class RealmStoreImpl extends HasUserGroupStore with RealmStore {
203216
required User selfUser,
204217
}) :
205218
_selfUserRole = selfUser.role,
219+
_selfUserDateJoined = selfUser.dateJoined,
206220
serverPresencePingIntervalSeconds = initialSnapshot.serverPresencePingIntervalSeconds,
207221
serverPresenceOfflineThresholdSeconds = initialSnapshot.serverPresenceOfflineThresholdSeconds,
208222
serverTypingStartedExpiryPeriodMilliseconds = initialSnapshot.serverTypingStartedExpiryPeriodMilliseconds,
@@ -224,6 +238,22 @@ class RealmStoreImpl extends HasUserGroupStore with RealmStore {
224238
realmDefaultExternalAccounts = initialSnapshot.realmDefaultExternalAccounts,
225239
customProfileFields = _sortCustomProfileFields(initialSnapshot.customProfileFields);
226240

241+
@override
242+
bool selfHasPassedWaitingPeriod({required DateTime byDate}) {
243+
// [User.dateJoined] is in UTC. For logged-in users, the format is:
244+
// YYYY-MM-DDTHH:mm+00:00, which includes the timezone offset for UTC.
245+
// For logged-out spectators, the format is: YYYY-MM-DD, which doesn't
246+
// include the timezone offset. In the later case, [DateTime.parse] will
247+
// interpret it as the client's local timezone, which could lead to
248+
// incorrect results; but that's acceptable for now because the app
249+
// doesn't support viewing as a spectator.
250+
//
251+
// See the related discussion:
252+
// https://chat.zulip.org/#narrow/channel/412-api-documentation/topic/provide.20an.20explicit.20format.20for.20.60realm_user.2Edate_joined.60/near/1980194
253+
final dateJoined = DateTime.parse(_selfUserDateJoined);
254+
return byDate.difference(dateJoined).inDays >= realmWaitingPeriodThreshold;
255+
}
256+
227257
@override
228258
bool selfHasPermissionForGroupSetting(GroupSettingValue value,
229259
GroupSettingType type, String name) {
@@ -262,8 +292,20 @@ class RealmStoreImpl extends HasUserGroupStore with RealmStore {
262292
/// The main home of this information is [UserStore]: `store.selfUser.role`.
263293
/// We need it here for interpreting some permission settings;
264294
/// so we denormalize it here to avoid a cycle between substores.
295+
///
296+
/// See also [_selfUserDateJoined].
265297
UserRole _selfUserRole;
266298

299+
/// The [User.dateJoined] of the self-user.
300+
///
301+
/// The main home of this information is [UserStore]:
302+
/// `store.selfUser.dateJoined`.
303+
/// We need it here for interpreting some permission settings;
304+
/// so we denormalize it here to avoid a cycle between substores.
305+
///
306+
/// See also [_selfUserRole].
307+
final String _selfUserDateJoined;
308+
267309
@override
268310
final int serverPresencePingIntervalSeconds;
269311
@override

lib/model/user.dart

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -91,28 +91,6 @@ mixin UserStore on PerAccountStoreBase, RealmStore {
9191
return getUser(senderId)?.fullName ?? message.senderFullName;
9292
}
9393

94-
/// Whether [user] has passed the realm's waiting period to be a full member.
95-
///
96-
/// See:
97-
/// https://zulip.com/api/roles-and-permissions#determining-if-a-user-is-a-full-member
98-
///
99-
/// To determine if a user is a full member, callers must also check that the
100-
/// user's role is at least [UserRole.member].
101-
bool hasPassedWaitingPeriod(User user, {required DateTime byDate}) {
102-
// [User.dateJoined] is in UTC. For logged-in users, the format is:
103-
// YYYY-MM-DDTHH:mm+00:00, which includes the timezone offset for UTC.
104-
// For logged-out spectators, the format is: YYYY-MM-DD, which doesn't
105-
// include the timezone offset. In the later case, [DateTime.parse] will
106-
// interpret it as the client's local timezone, which could lead to
107-
// incorrect results; but that's acceptable for now because the app
108-
// doesn't support viewing as a spectator.
109-
//
110-
// See the related discussion:
111-
// https://chat.zulip.org/#narrow/channel/412-api-documentation/topic/provide.20an.20explicit.20format.20for.20.60realm_user.2Edate_joined.60/near/1980194
112-
final dateJoined = DateTime.parse(user.dateJoined);
113-
return byDate.difference(dateJoined).inDays >= realmWaitingPeriodThreshold;
114-
}
115-
11694
/// Whether the user with [userId] is muted by the self-user.
11795
///
11896
/// Looks for [userId] in a private [Set],

test/model/realm_test.dart

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,32 @@ void main() {
3535
doCheck(eg.t('(no topic)'), eg.t(''), 370);
3636
});
3737

38+
group('selfHasPassedWaitingPeriod', () {
39+
final testCases = [
40+
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 0, 10, 00), false),
41+
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 1, 10, 00), false),
42+
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 2, 09, 59), false),
43+
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 2, 10, 00), true),
44+
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 1000, 07, 00), true),
45+
];
46+
47+
for (final (String dateJoined, DateTime currentDate, bool expected) in testCases) {
48+
test('self-user joined at $dateJoined ${expected ? 'has' : "hasn't"} '
49+
'passed waiting period by $currentDate', () {
50+
final selfUser = eg.user(dateJoined: dateJoined);
51+
final store = eg.store(
52+
selfUser: selfUser,
53+
initialSnapshot: eg.initialSnapshot(
54+
realmWaitingPeriodThreshold: 2,
55+
realmUsers: [selfUser],
56+
),
57+
);
58+
check(store.selfHasPassedWaitingPeriod(byDate: currentDate))
59+
.equals(expected);
60+
});
61+
}
62+
});
63+
3864
group('selfHasPermissionForGroupSetting', () {
3965
// Most of the implementation of this is in [UserGroupStore.selfInGroupSetting],
4066
// and is tested in more detail in user_group_test.dart .

test/model/user_test.dart

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -58,28 +58,6 @@ void main() {
5858
});
5959
});
6060

61-
group('hasPassedWaitingPeriod', () {
62-
final store = eg.store(initialSnapshot:
63-
eg.initialSnapshot(realmWaitingPeriodThreshold: 2));
64-
65-
final testCases = [
66-
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 0, 10, 00), false),
67-
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 1, 10, 00), false),
68-
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 2, 09, 59), false),
69-
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 2, 10, 00), true),
70-
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 1000, 07, 00), true),
71-
];
72-
73-
for (final (String dateJoined, DateTime currentDate, bool hasPassedWaitingPeriod) in testCases) {
74-
test('user joined at $dateJoined ${hasPassedWaitingPeriod ? 'has' : "hasn't"} '
75-
'passed waiting period by $currentDate', () {
76-
final user = eg.user(dateJoined: dateJoined);
77-
check(store.hasPassedWaitingPeriod(user, byDate: currentDate))
78-
.equals(hasPassedWaitingPeriod);
79-
});
80-
}
81-
});
82-
8361
group('RealmUserUpdateEvent', () {
8462
// TODO write more tests for handling RealmUserUpdateEvent
8563

0 commit comments

Comments
 (0)