@@ -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
0 commit comments