@@ -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,122 @@ 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 ) {
91+ assert (false ); // TODO(log)
92+ return true ;
93+ }
94+
95+ final ZulipStream ? channel;
96+ if (message is StreamMessage ) {
97+ channel = streams[message.streamId];
98+ if (channel == null ) {
99+ assert (false ); // TODO(log)
100+ return true ;
101+ }
102+ } else {
103+ channel = null ;
104+ }
105+
106+ if (channel != null && channel.isArchived) {
107+ return false ;
108+ }
109+
110+ // TODO(#1850) really the default should be `role:administrators`:
111+ // https://github.com/zulip/zulip-flutter/pull/1842#discussion_r2331362461
112+ if (realmCanDeleteAnyMessageGroup != null
113+ && selfHasPermissionForGroupSetting (realmCanDeleteAnyMessageGroup! ,
114+ GroupSettingType .realm, 'can_delete_any_message_group' )) {
115+ return true ;
116+ }
117+
118+ if (channel != null ) {
119+ if (channel.canDeleteAnyMessageGroup != null
120+ && selfHasPermissionForGroupSetting (channel.canDeleteAnyMessageGroup! ,
121+ GroupSettingType .stream, 'can_delete_any_message_group' )) {
122+ return true ;
123+ }
124+ }
125+
126+ final sender = getUser (message.senderId);
127+ if (sender == null ) return false ;
128+
129+ if (! (
130+ sender.userId == selfUserId
131+ || (sender.isBot && sender.botOwnerId == selfUserId)
132+ )) {
133+ return false ;
134+ }
135+
136+ // Web returns false here for local-echoed message objects;
137+ // that's impossible here because `message` can't be an [OutboxMessage]
138+ // (it's a [Message] from [MessageStore.messages]).
139+
140+ if (realmCanDeleteOwnMessageGroup != null ) {
141+ if (! selfHasPermissionForGroupSetting (realmCanDeleteOwnMessageGroup! ,
142+ GroupSettingType .realm, 'can_delete_own_message_group' )) {
143+ if (channel == null ) {
144+ // i.e. this is a DM
145+ return false ;
146+ }
147+
148+ if (
149+ channel.canDeleteOwnMessageGroup == null
150+ || ! selfHasPermissionForGroupSetting (channel.canDeleteOwnMessageGroup! ,
151+ GroupSettingType .stream, 'can_delete_own_message_group' )
152+ ) {
153+ return false ;
154+ }
155+ }
156+ } else if (realmDeleteOwnMessagePolicy != null ) {
157+ if (! _selfPassesLegacyDeleteMessagePolicy (messageId, atDate: atDate)) {
158+ return false ;
159+ }
160+ } else {
161+ assert (false ); // TODO(log)
162+ return true ;
163+ }
164+
165+ if (realmMessageContentDeleteLimitSeconds == null ) {
166+ // i.e., no limit
167+ return true ;
168+ }
169+ return atDate.millisecondsSinceEpoch ~ / 1000 - message.timestamp
170+ <= realmMessageContentDeleteLimitSeconds! ;
171+ }
172+
173+ bool _selfPassesLegacyDeleteMessagePolicy (int messageId, {required DateTime atDate}) {
174+ assert (realmDeleteOwnMessagePolicy != null );
175+ final role = selfUser.role;
176+
177+ // (Could early-return true on [UserRole.unknown],
178+ // but pre-291 servers shouldn't be giving us an unknown role.)
179+
180+ switch (realmDeleteOwnMessagePolicy! ) {
181+ case RealmDeleteOwnMessagePolicy .everyone:
182+ return true ;
183+ case RealmDeleteOwnMessagePolicy .members:
184+ return role.isAtLeast (UserRole .member);
185+ case RealmDeleteOwnMessagePolicy .fullMembers: {
186+ if (! role.isAtLeast (UserRole .member)) return false ;
187+ if (role == UserRole .member) {
188+ return hasPassedWaitingPeriod (selfUser, byDate: atDate);
189+ }
190+ return true ;
191+ }
192+ case RealmDeleteOwnMessagePolicy .moderators:
193+ return role.isAtLeast (UserRole .moderator);
194+ case RealmDeleteOwnMessagePolicy .admins:
195+ return role.isAtLeast (UserRole .administrator);
196+ }
197+ }
81198}
82199
83200mixin ProxyMessageStore on MessageStore {
0 commit comments