Skip to content

Commit 1758286

Browse files
committed
model: Add hasPassedWaitingPeriod helper method to PerAccountStore
Also add `UserRole.isAtLeast` method.
1 parent 97485ab commit 1758286

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

lib/api/model/model.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,11 @@ enum UserRole{
303303
final int? apiValue;
304304

305305
int? toJson() => apiValue;
306+
307+
bool isAtLeast(UserRole threshold) {
308+
// Roles with more privilege have lower [apiValue].
309+
return apiValue! <= threshold.apiValue!;
310+
}
306311
}
307312

308313
/// As in `streams` in the initial snapshot.

lib/model/store.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,19 @@ class PerAccountStore extends ChangeNotifier with EmojiStore, ChannelStore, Mess
434434

435435
final TypingStatus typingStatus;
436436

437+
/// Whether [user] has passed the realm's waiting period to be a full member.
438+
///
439+
/// See:
440+
/// https://zulip.com/api/roles-and-permissions#determining-if-a-user-is-a-full-member
441+
///
442+
/// To determine if a user is a full member, callers must also check that the
443+
/// user's role is at least `UserRole.member`.
444+
bool hasPassedWaitingPeriod(User user, {required DateTime byDate}) {
445+
// dateJoined is in UTC, in the following format: 2024-02-24T11:18+00:00.
446+
final dateJoined = DateTime.parse(user.dateJoined);
447+
return byDate.difference(dateJoined).inDays >= realmWaitingPeriodThreshold;
448+
}
449+
437450
////////////////////////////////
438451
// Streams, topics, and stuff about them.
439452

test/model/store_test.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'dart:io';
44
import 'package:checks/checks.dart';
55
import 'package:fake_async/fake_async.dart';
66
import 'package:flutter/foundation.dart';
7+
import 'package:flutter/material.dart';
78
import 'package:http/http.dart' as http;
89
import 'package:test/scaffolding.dart';
910
import 'package:zulip/api/core.dart';
@@ -247,6 +248,28 @@ void main() {
247248
});
248249
});
249250

251+
group('PerAccountStore.hasPassedWaitingPeriod', () {
252+
final store = eg.store(initialSnapshot:
253+
eg.initialSnapshot(realmWaitingPeriodThreshold: 2));
254+
255+
final testCases = [
256+
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 0, 10, 00), false),
257+
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 1, 10, 00), false),
258+
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 2, 09, 59), false),
259+
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 2, 10, 00), true),
260+
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 1000, 07, 00), true),
261+
];
262+
263+
for (final (String dateJoined, DateTime currentDate, bool hasPassedWaitingPeriod) in testCases) {
264+
test('user joined at $dateJoined ${hasPassedWaitingPeriod ? 'has' : "hasn't"} '
265+
'passed waiting period by $currentDate', () {
266+
final user = eg.user(dateJoined: dateJoined);
267+
check(store.hasPassedWaitingPeriod(user, byDate: currentDate))
268+
.equals(hasPassedWaitingPeriod);
269+
});
270+
}
271+
});
272+
250273
group('PerAccountStore.handleEvent', () {
251274
// Mostly this method just dispatches to ChannelStore and MessageStore etc.,
252275
// and so most of the tests live in the test files for those

0 commit comments

Comments
 (0)