Skip to content

Commit 68d7cd1

Browse files
committed
api: Add updateMessage route
And move the PropagateMode definition from events.dart to model.dart, since it's no longer specific to an event.
1 parent fed04bf commit 68d7cd1

File tree

7 files changed

+118
-9
lines changed

7 files changed

+118
-9
lines changed

lib/api/model/events.dart

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -766,14 +766,6 @@ class UpdateMessageEvent extends Event {
766766
Map<String, dynamic> toJson() => _$UpdateMessageEventToJson(this);
767767
}
768768

769-
/// As in [UpdateMessageEvent.propagateMode].
770-
@JsonEnum(fieldRename: FieldRename.snake)
771-
enum PropagateMode {
772-
changeOne,
773-
changeLater,
774-
changeAll;
775-
}
776-
777769
/// A Zulip event of type `delete_message`: https://zulip.com/api/get-events#delete_message
778770
@JsonSerializable(fieldRename: FieldRename.snake)
779771
class DeleteMessageEvent extends Event {

lib/api/model/events.g.dart

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/api/model/model.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,3 +942,13 @@ enum MessageEditState {
942942
return MessageEditState.none;
943943
}
944944
}
945+
946+
/// As in [updateMessage] or [UpdateMessageEvent.propagateMode].
947+
@JsonEnum(fieldRename: FieldRename.snake, alwaysCreate: true)
948+
enum PropagateMode {
949+
changeOne,
950+
changeLater,
951+
changeAll;
952+
953+
String toJson() =>_$PropagateModeEnumMap[this]!;
954+
}

lib/api/model/model.g.dart

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/api/route/messages.dart

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,39 @@ class SendMessageResult {
258258
Map<String, dynamic> toJson() => _$SendMessageResultToJson(this);
259259
}
260260

261+
/// https://zulip.com/api/update-message
262+
Future<UpdateMessageResult> updateMessage(
263+
ApiConnection connection, {
264+
required int messageId,
265+
String? topic,
266+
PropagateMode? propagateMode,
267+
bool? sendNotificationToOldThread,
268+
bool? sendNotificationToNewThread,
269+
String? content,
270+
int? streamId,
271+
}) {
272+
return connection.patch('updateMessage', UpdateMessageResult.fromJson, 'messages/$messageId', {
273+
if (topic != null) 'topic': RawParameter(topic),
274+
if (propagateMode != null) 'propagate_mode': RawParameter(propagateMode.toJson()),
275+
if (sendNotificationToOldThread != null) 'send_notification_to_old_thread': sendNotificationToOldThread,
276+
if (sendNotificationToNewThread != null) 'send_notification_to_new_thread': sendNotificationToNewThread,
277+
if (content != null) 'content': RawParameter(content),
278+
if (streamId != null) 'stream_id': streamId,
279+
});
280+
}
281+
282+
@JsonSerializable(fieldRename: FieldRename.snake)
283+
class UpdateMessageResult {
284+
// final List<DetachedUpload> detachedUploads; // TODO handle
285+
286+
UpdateMessageResult();
287+
288+
factory UpdateMessageResult.fromJson(Map<String, dynamic> json) =>
289+
_$UpdateMessageResultFromJson(json);
290+
291+
Map<String, dynamic> toJson() => _$UpdateMessageResultToJson(this);
292+
}
293+
261294
/// https://zulip.com/api/upload-file
262295
Future<UploadFileResult> uploadFile(
263296
ApiConnection connection, {

lib/api/route/messages.g.dart

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/api/route/messages_test.dart

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,67 @@ void main() {
420420
});
421421
});
422422

423+
group('updateMessage', () {
424+
Future<UpdateMessageResult> checkUpdateMessage(
425+
FakeApiConnection connection, {
426+
required int messageId,
427+
String? topic,
428+
PropagateMode? propagateMode,
429+
bool? sendNotificationToOldThread,
430+
bool? sendNotificationToNewThread,
431+
String? content,
432+
int? streamId,
433+
required Map<String, String> expected,
434+
}) async {
435+
final result = await updateMessage(connection,
436+
messageId: messageId,
437+
topic: topic,
438+
propagateMode: propagateMode,
439+
sendNotificationToOldThread: sendNotificationToOldThread,
440+
sendNotificationToNewThread: sendNotificationToNewThread,
441+
content: content,
442+
streamId: streamId,
443+
);
444+
check(connection.lastRequest).isA<http.Request>()
445+
..method.equals('PATCH')
446+
..url.path.equals('/api/v1/messages/$messageId')
447+
..bodyFields.deepEquals(expected);
448+
return result;
449+
}
450+
451+
test('topic/content change', () {
452+
// A separate test exercises `streamId`;
453+
// the API doesn't allow changing channel and content at the same time.
454+
return FakeApiConnection.with_((connection) async {
455+
connection.prepare(json: UpdateMessageResult().toJson());
456+
await checkUpdateMessage(connection,
457+
messageId: eg.streamMessage().id,
458+
topic: 'new topic',
459+
propagateMode: PropagateMode.changeAll,
460+
sendNotificationToOldThread: true,
461+
sendNotificationToNewThread: true,
462+
content: 'asdf',
463+
expected: {
464+
'topic': 'new topic',
465+
'propagate_mode': 'change_all',
466+
'send_notification_to_old_thread': 'true',
467+
'send_notification_to_new_thread': 'true',
468+
'content': 'asdf',
469+
});
470+
});
471+
});
472+
473+
test('channel change', () {
474+
return FakeApiConnection.with_((connection) async {
475+
connection.prepare(json: UpdateMessageResult().toJson());
476+
await checkUpdateMessage(connection,
477+
messageId: eg.streamMessage().id,
478+
streamId: 1,
479+
expected: {'stream_id': '1'});
480+
});
481+
});
482+
});
483+
423484
group('uploadFile', () {
424485
Future<void> checkUploadFile(FakeApiConnection connection, {
425486
required List<List<int>> content,

0 commit comments

Comments
 (0)