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