@@ -7,6 +7,7 @@ import 'package:flutter/foundation.dart';
77
88import '../api/exception.dart' ;
99import '../api/model/events.dart' ;
10+ import '../api/model/initial_snapshot.dart' ;
1011import '../api/model/model.dart' ;
1112import '../api/route/messages.dart' ;
1213import '../log.dart' ;
@@ -78,6 +79,118 @@ mixin MessageStore on ChannelStore {
7879 /// Should only be called when there is a failed request,
7980 /// per [getEditMessageErrorStatus] .
8081 ({String originalRawContent, String newContent}) takeFailedMessageEdit (int messageId);
82+
83+ /// Whether the user has permission to delete a message, as of [atDate] .
84+ ///
85+ /// For a value of [atDate] , use [ZulipBinding.instance.utcNow] .
86+ bool selfCanDeleteMessage (int messageId, {required DateTime atDate}) {
87+ // Compare web's message_delete.get_deletability.
88+
89+ final message = messages[messageId];
90+ if (message == null ) return false ; // TODO(log)
91+
92+ final ZulipStream ? channel;
93+ if (message is StreamMessage ) {
94+ channel = streams[message.streamId];
95+ if (channel == null ) {
96+ assert (false ); // TODO(log)
97+ return true ;
98+ }
99+ } else {
100+ channel = null ;
101+ }
102+
103+ if (channel != null && channel.isArchived) {
104+ return false ;
105+ }
106+
107+ // TODO really the default should be `role:administrators`:
108+ // https://github.com/zulip/zulip-flutter/pull/1842#discussion_r2331362461
109+ if (realmCanDeleteAnyMessageGroup != null
110+ && selfHasPermissionForGroupSetting (realmCanDeleteAnyMessageGroup! ,
111+ GroupSettingType .realm, 'can_delete_any_message_group' )) {
112+ return true ;
113+ }
114+
115+ if (channel != null ) {
116+ if (channel.canDeleteAnyMessageGroup != null
117+ && selfHasPermissionForGroupSetting (channel.canDeleteAnyMessageGroup! ,
118+ GroupSettingType .stream, 'can_delete_any_message_group' )) {
119+ return true ;
120+ }
121+ }
122+
123+ final sender = getUser (message.senderId);
124+ if (sender == null ) return false ;
125+
126+ if (! (
127+ sender.userId == selfUserId
128+ || (sender.isBot && sender.botOwnerId == selfUserId)
129+ )) {
130+ return false ;
131+ }
132+
133+ // Web returns false here for local-echoed message objects;
134+ // that's impossible here because `message` can't be an [OutboxMessage]
135+ // (it's a [Message] from [MessageStore.messages]).
136+
137+ if (realmCanDeleteOwnMessageGroup != null ) {
138+ if (! selfHasPermissionForGroupSetting (realmCanDeleteOwnMessageGroup! ,
139+ GroupSettingType .realm, 'can_delete_own_message_group' )) {
140+ if (channel == null ) {
141+ // i.e. this is a DM
142+ return false ;
143+ }
144+
145+ if (
146+ channel.canDeleteOwnMessageGroup == null
147+ || ! selfHasPermissionForGroupSetting (channel.canDeleteOwnMessageGroup! ,
148+ GroupSettingType .stream, 'can_delete_own_message_group' )
149+ ) {
150+ return false ;
151+ }
152+ }
153+ } else if (realmDeleteOwnMessagePolicy != null ) {
154+ if (! _selfPassesLegacyDeleteMessagePolicy (messageId, atDate: atDate)) {
155+ return false ;
156+ }
157+ } else {
158+ assert (false ); // TODO(log)
159+ return true ;
160+ }
161+
162+ if (realmMessageContentDeleteLimitSeconds == null ) {
163+ // i.e., no limit
164+ return true ;
165+ }
166+ return atDate.millisecondsSinceEpoch ~ / 1000 - message.timestamp
167+ <= realmMessageContentDeleteLimitSeconds! ;
168+ }
169+
170+ bool _selfPassesLegacyDeleteMessagePolicy (int messageId, {required DateTime atDate}) {
171+ assert (realmDeleteOwnMessagePolicy != null );
172+ final role = selfUser.role;
173+
174+ // (Could early-return true on [UserRole.unknown],
175+ // but pre-291 servers shouldn't be giving us an unknown role.)
176+
177+ switch (realmDeleteOwnMessagePolicy! ) {
178+ case RealmDeleteOwnMessagePolicy .everyone:
179+ case RealmDeleteOwnMessagePolicy .members:
180+ return true ;
181+ case RealmDeleteOwnMessagePolicy .fullMembers: {
182+ if (! role.isAtLeast (UserRole .member)) return false ;
183+ if (role == UserRole .member) {
184+ return hasPassedWaitingPeriod (selfUser, byDate: atDate);
185+ }
186+ return true ;
187+ }
188+ case RealmDeleteOwnMessagePolicy .moderators:
189+ return role.isAtLeast (UserRole .moderator);
190+ case RealmDeleteOwnMessagePolicy .admins:
191+ return role.isAtLeast (UserRole .administrator);
192+ }
193+ }
81194}
82195
83196mixin ProxyMessageStore on MessageStore {
0 commit comments