@@ -7,6 +7,7 @@ import 'package:flutter/foundation.dart';
7
7
8
8
import '../api/exception.dart' ;
9
9
import '../api/model/events.dart' ;
10
+ import '../api/model/initial_snapshot.dart' ;
10
11
import '../api/model/model.dart' ;
11
12
import '../api/route/messages.dart' ;
12
13
import '../log.dart' ;
@@ -78,6 +79,122 @@ mixin MessageStore on ChannelStore {
78
79
/// Should only be called when there is a failed request,
79
80
/// per [getEditMessageErrorStatus] .
80
81
({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
+ }
81
198
}
82
199
83
200
mixin ProxyMessageStore on MessageStore {
0 commit comments