Skip to content

Commit 1eeb197

Browse files
committed
model: Use prevContentSha256 in edit-message method
1 parent 2c69364 commit 1eeb197

File tree

3 files changed

+59
-21
lines changed

3 files changed

+59
-21
lines changed

lib/model/message.dart

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import 'dart:convert';
22

3+
import 'package:crypto/crypto.dart';
4+
35
import '../api/model/events.dart';
46
import '../api/model/model.dart';
57
import '../api/route/messages.dart';
@@ -51,7 +53,11 @@ mixin MessageStore {
5153
/// See also:
5254
/// * [getEditMessageErrorStatus]
5355
/// * [takeFailedMessageEdit]
54-
void editMessage({required int messageId, required String newContent});
56+
void editMessage({
57+
required int messageId,
58+
required String originalRawContent,
59+
required String newContent,
60+
});
5561

5662
/// Forgets the failed edit request and returns the attempted new content.
5763
///
@@ -171,6 +177,7 @@ class MessageStoreImpl extends PerAccountStoreBase with MessageStore {
171177
@override
172178
void editMessage({
173179
required int messageId,
180+
required String originalRawContent,
174181
required String newContent,
175182
}) async {
176183
if (_editMessageRequests.containsKey(messageId)) {
@@ -181,7 +188,10 @@ class MessageStoreImpl extends PerAccountStoreBase with MessageStore {
181188
hasError: false, newContent: newContent);
182189
_notifyMessageListViewsForOneMessage(messageId);
183190
try {
184-
await updateMessage(connection, messageId: messageId, content: newContent);
191+
await updateMessage(connection,
192+
messageId: messageId,
193+
content: newContent,
194+
prevContentSha256: sha256.convert(utf8.encode(originalRawContent)).toString());
185195
// On success, we'll clear the status from _editMessageRequests
186196
// when we get the event.
187197
} catch (e) {

lib/model/store.dart

+7-2
Original file line numberDiff line numberDiff line change
@@ -753,9 +753,14 @@ class PerAccountStore extends PerAccountStoreBase with ChangeNotifier, EmojiStor
753753
return _messages.getEditMessageErrorStatus(messageId);
754754
}
755755
@override
756-
void editMessage({required int messageId, required String newContent}) {
756+
void editMessage({
757+
required int messageId,
758+
required String originalRawContent,
759+
required String newContent,
760+
}) {
757761
assert(!_disposed);
758-
return _messages.editMessage(messageId: messageId, newContent: newContent);
762+
return _messages.editMessage(messageId: messageId,
763+
originalRawContent: originalRawContent, newContent: newContent);
759764
}
760765
@override
761766
String takeFailedMessageEdit(int messageId) {

test/model/message_test.dart

+40-17
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,15 @@ void main() {
136136
check(connection.takeRequests()).length.equals(1); // message-list fetchInitial
137137
}
138138

139-
void checkRequest(int messageId, String content) {
139+
void checkRequest(int messageId, {
140+
required String prevContentSha256,
141+
required String content,
142+
}) {
140143
check(connection.takeRequests()).single.isA<http.Request>()
141144
..method.equals('PATCH')
142145
..url.path.equals('/api/v1/messages/$messageId')
143146
..bodyFields.deepEquals({
147+
if (store.zulipFeatureLevel >= 379) 'prev_content_sha256': prevContentSha256,
144148
'content': content,
145149
});
146150
}
@@ -151,8 +155,11 @@ void main() {
151155

152156
connection.prepare(
153157
json: UpdateMessageResult().toJson(), delay: Duration(seconds: 1));
154-
store.editMessage(messageId: message.id, newContent: 'new content');
155-
checkRequest(message.id, 'new content');
158+
store.editMessage(messageId: message.id,
159+
originalRawContent: 'old content', newContent: 'new content');
160+
checkRequest(message.id,
161+
prevContentSha256: '34a780ad578b997db55b260beb60b501f3e04d30ba1a51fcf43cd8dd1241780d',
162+
content: 'new content');
156163
checkNotifiedOnce();
157164

158165
async.elapse(Duration(milliseconds: 500));
@@ -179,8 +186,11 @@ void main() {
179186

180187
connection.prepare(
181188
json: UpdateMessageResult().toJson(), delay: Duration(seconds: 1));
182-
store.editMessage(messageId: message.id, newContent: 'new content');
183-
checkRequest(message.id, 'new content');
189+
store.editMessage(messageId: message.id,
190+
originalRawContent: 'old content', newContent: 'new content');
191+
checkRequest(message.id,
192+
prevContentSha256: '34a780ad578b997db55b260beb60b501f3e04d30ba1a51fcf43cd8dd1241780d',
193+
content: 'new content');
184194
checkNotifiedOnce();
185195

186196
async.elapse(Duration(milliseconds: 500));
@@ -189,8 +199,11 @@ void main() {
189199
check(store.getEditMessageErrorStatus(otherMessage.id)).isNull();
190200
connection.prepare(
191201
json: UpdateMessageResult().toJson(), delay: Duration(seconds: 1));
192-
store.editMessage(messageId: otherMessage.id, newContent: 'other message new content');
193-
checkRequest(otherMessage.id, 'other message new content');
202+
store.editMessage(messageId: otherMessage.id,
203+
originalRawContent: 'other message old content', newContent: 'other message new content');
204+
checkRequest(otherMessage.id,
205+
prevContentSha256: '954956d2fe9f84b646bb7102340b759a9b627cb1ad853289b12251cb25b1e2bf',
206+
content: 'other message new content');
194207
checkNotifiedOnce();
195208

196209
async.elapse(Duration(milliseconds: 500));
@@ -221,7 +234,8 @@ void main() {
221234
check(store.getEditMessageErrorStatus(message.id)).isNull();
222235

223236
connection.prepare(apiException: eg.apiBadRequest(), delay: Duration(seconds: 1));
224-
store.editMessage(messageId: message.id, newContent: 'new content');
237+
store.editMessage(messageId: message.id,
238+
originalRawContent: 'old content', newContent: 'new content');
225239
checkNotifiedOnce();
226240
async.elapse(Duration(seconds: 1));
227241
check(store.getEditMessageErrorStatus(message.id)).isNotNull().isTrue();
@@ -233,7 +247,8 @@ void main() {
233247
check(store.getEditMessageErrorStatus(message.id)).isNull();
234248

235249
connection.prepare(apiException: eg.apiBadRequest(), delay: Duration(seconds: 1));
236-
store.editMessage(messageId: message.id, newContent: 'new content');
250+
store.editMessage(messageId: message.id,
251+
originalRawContent: 'old content', newContent: 'new content');
237252
checkNotifiedOnce();
238253
async.elapse(Duration(seconds: 1));
239254
check(store.getEditMessageErrorStatus(message.id)).isNotNull().isTrue();
@@ -255,12 +270,14 @@ void main() {
255270

256271
connection.prepare(
257272
json: UpdateMessageResult().toJson(), delay: Duration(seconds: 1));
258-
store.editMessage(messageId: message.id, newContent: 'new content');
273+
store.editMessage(messageId: message.id,
274+
originalRawContent: 'old content', newContent: 'new content');
259275
async.elapse(Duration(milliseconds: 500));
260276
check(connection.takeRequests()).length.equals(1);
261277
checkNotifiedOnce();
262278

263-
await check(store.editMessage(messageId: message.id, newContent: 'newer content'))
279+
await check(store.editMessage(messageId: message.id,
280+
originalRawContent: 'old content', newContent: 'newer content'))
264281
.isA<Future<void>>().throws<StateError>();
265282
check(connection.takeRequests()).isEmpty();
266283
}));
@@ -273,7 +290,8 @@ void main() {
273290

274291
connection.prepare(
275292
httpException: const SocketException('failed'), delay: Duration(seconds: 1));
276-
store.editMessage(messageId: message.id, newContent: 'new content');
293+
store.editMessage(messageId: message.id,
294+
originalRawContent: 'old content', newContent: 'new content');
277295
checkNotifiedOnce();
278296

279297
async.elapse(Duration(milliseconds: 500));
@@ -294,7 +312,8 @@ void main() {
294312

295313
connection.prepare(
296314
httpException: const SocketException('failed'), delay: Duration(seconds: 1));
297-
store.editMessage(messageId: message.id, newContent: 'new content');
315+
store.editMessage(messageId: message.id,
316+
originalRawContent: 'old content', newContent: 'new content');
298317
checkNotifiedOnce();
299318

300319
async.elapse(Duration(seconds: 1));
@@ -314,7 +333,8 @@ void main() {
314333

315334
connection.prepare(
316335
httpException: const SocketException('failed'), delay: Duration(seconds: 1));
317-
store.editMessage(messageId: message.id, newContent: 'new content');
336+
store.editMessage(messageId: message.id,
337+
originalRawContent: 'old content', newContent: 'new content');
318338
checkNotifiedOnce();
319339

320340
async.elapse(Duration(seconds: 1));
@@ -333,7 +353,8 @@ void main() {
333353
check(store.getEditMessageErrorStatus(message.id)).isNull();
334354

335355
connection.prepare(apiException: eg.apiBadRequest(), delay: Duration(seconds: 1));
336-
store.editMessage(messageId: message.id, newContent: 'new content');
356+
store.editMessage(messageId: message.id,
357+
originalRawContent: 'old content', newContent: 'new content');
337358
checkNotifiedOnce();
338359
async.elapse(Duration(seconds: 1));
339360
check(store.getEditMessageErrorStatus(message.id)).isNotNull().isTrue();
@@ -349,7 +370,8 @@ void main() {
349370
check(store.getEditMessageErrorStatus(message.id)).isNull();
350371

351372
connection.prepare(apiException: eg.apiBadRequest(), delay: Duration(seconds: 1));
352-
store.editMessage(messageId: message.id, newContent: 'new content');
373+
store.editMessage(messageId: message.id,
374+
originalRawContent: 'old content', newContent: 'new content');
353375
checkNotifiedOnce();
354376

355377
async.elapse(Duration(milliseconds: 500));
@@ -373,7 +395,8 @@ void main() {
373395

374396
connection.prepare(
375397
json: UpdateMessageResult().toJson(), delay: Duration(seconds: 1));
376-
store.editMessage(messageId: message.id, newContent: 'new content');
398+
store.editMessage(messageId: message.id,
399+
originalRawContent: 'old content', newContent: 'new content');
377400
checkNotifiedOnce();
378401

379402
async.elapse(Duration(milliseconds: 500));

0 commit comments

Comments
 (0)