Skip to content

Commit d909dcb

Browse files
committed
compose: Support editing an already-sent message
Fixes: #126
1 parent 449f326 commit d909dcb

19 files changed

+751
-65
lines changed

assets/icons/ZulipIcons.ttf

268 Bytes
Binary file not shown.

assets/icons/edit.svg

Lines changed: 4 additions & 0 deletions
Loading

assets/l10n/app_en.arb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,14 @@
685685
"@messageIsMovedLabel": {
686686
"description": "Label for a moved message. (Use ALL CAPS for cased alphabets: Latin, Greek, Cyrillic, etc.)"
687687
},
688+
"messageIsEditingLabel": "SAVING EDIT...",
689+
"@messageIsEditingLabel": {
690+
"description": "Label shown while a message edit is being saved. (Use ALL CAPS for cased alphabets: Latin, Greek, Cyrillic, etc.)"
691+
},
692+
"messageIsEditErrorLabel": "EDIT ISN'T SAVED. CHECK YOUR CONNECTION.",
693+
"@messageIsEditErrorLabel": {
694+
"description": "Label shown when a message edit failed to save. (Use ALL CAPS for cased alphabets: Latin, Greek, Cyrillic, etc.)"
695+
},
688696
"pollWidgetQuestionMissing": "No question.",
689697
"@pollWidgetQuestionMissing": {
690698
"description": "Text to display for a poll when the question is missing"
@@ -716,5 +724,25 @@
716724
"emojiPickerSearchEmoji": "Search emoji",
717725
"@emojiPickerSearchEmoji": {
718726
"description": "Hint text for the emoji picker search text field."
727+
},
728+
"actionSheetOptionEditMessage": "Edit",
729+
"@actionSheetOptionEditMessage": {
730+
"description": "Label for action sheet button to edit a message."
731+
},
732+
"errorEditingFailed": "Failed to edit message",
733+
"@errorEditingFailed": {
734+
"description": "Error title when editing a message fails."
735+
},
736+
"editMessageSaveTooltip": "Save changes",
737+
"@editMessageSaveTooltip": {
738+
"description": "Tooltip for the save button when editing a message"
739+
},
740+
"editMessageTitle": "Edit the message",
741+
"@editMessageTitle": {
742+
"description": "Title shown in the edit message banner"
743+
},
744+
"dialogSave": "Save",
745+
"@dialogSave": {
746+
"description": "Button label to save changes"
719747
}
720748
}

lib/api/model/model.dart

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:json_annotation/json_annotation.dart';
2+
import 'package:flutter/foundation.dart';
23

34
import 'events.dart';
45
import 'initial_snapshot.dart';
@@ -541,8 +542,15 @@ sealed class Message {
541542
final String contentType;
542543

543544
// final List<MessageEditHistory> editHistory; // TODO handle
544-
@JsonKey(readValue: MessageEditState._readFromMessage, fromJson: Message._messageEditStateFromJson)
545-
MessageEditState editState;
545+
@JsonKey(readValue: MessageEditState._readFromMessage, fromJson: _messageEditStateFromJson)
546+
final ValueNotifier<MessageEditState> _editStateNotifier;
547+
548+
MessageEditState get editState => _editStateNotifier.value;
549+
set editState(MessageEditState value) {
550+
_editStateNotifier.value = value;
551+
}
552+
553+
ValueNotifier<MessageEditState> get editStateNotifier => _editStateNotifier;
546554

547555
final int id;
548556
bool isMeMessage;
@@ -572,7 +580,7 @@ sealed class Message {
572580
@JsonKey(name: 'match_subject')
573581
final String? matchTopic;
574582

575-
static MessageEditState _messageEditStateFromJson(Object? json) {
583+
static MessageEditState _messageEditStateFromJson(dynamic json) {
576584
// This is a no-op so that [MessageEditState._readFromMessage]
577585
// can return the enum value directly.
578586
return json as MessageEditState;
@@ -603,7 +611,7 @@ sealed class Message {
603611
required this.client,
604612
required this.content,
605613
required this.contentType,
606-
required this.editState,
614+
required MessageEditState editState,
607615
required this.id,
608616
required this.isMeMessage,
609617
required this.lastEditTimestamp,
@@ -617,7 +625,7 @@ sealed class Message {
617625
required this.flags,
618626
required this.matchContent,
619627
required this.matchTopic,
620-
});
628+
}) : _editStateNotifier = ValueNotifier(editState);
621629

622630
factory Message.fromJson(Map<String, dynamic> json) {
623631
final type = json['type'] as String;
@@ -863,7 +871,9 @@ class DmMessage extends Message {
863871
enum MessageEditState {
864872
none,
865873
edited,
866-
moved;
874+
moved,
875+
editing,
876+
editError;
867877

868878
/// Whether the given topic move reflected either a "resolve topic"
869879
/// or "unresolve topic" operation.

lib/generated/l10n/zulip_localizations.dart

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,18 @@ abstract class ZulipLocalizations {
10231023
/// **'MOVED'**
10241024
String get messageIsMovedLabel;
10251025

1026+
/// Label shown while a message edit is being saved. (Use ALL CAPS for cased alphabets: Latin, Greek, Cyrillic, etc.)
1027+
///
1028+
/// In en, this message translates to:
1029+
/// **'SAVING EDIT...'**
1030+
String get messageIsEditingLabel;
1031+
1032+
/// Label shown when a message edit failed to save. (Use ALL CAPS for cased alphabets: Latin, Greek, Cyrillic, etc.)
1033+
///
1034+
/// In en, this message translates to:
1035+
/// **'EDIT ISN\'T SAVED. CHECK YOUR CONNECTION.'**
1036+
String get messageIsEditErrorLabel;
1037+
10261038
/// Text to display for a poll when the question is missing
10271039
///
10281040
/// In en, this message translates to:
@@ -1070,6 +1082,36 @@ abstract class ZulipLocalizations {
10701082
/// In en, this message translates to:
10711083
/// **'Search emoji'**
10721084
String get emojiPickerSearchEmoji;
1085+
1086+
/// Label for action sheet button to edit a message.
1087+
///
1088+
/// In en, this message translates to:
1089+
/// **'Edit'**
1090+
String get actionSheetOptionEditMessage;
1091+
1092+
/// Error title when editing a message fails.
1093+
///
1094+
/// In en, this message translates to:
1095+
/// **'Failed to edit message'**
1096+
String get errorEditingFailed;
1097+
1098+
/// Tooltip for the save button when editing a message
1099+
///
1100+
/// In en, this message translates to:
1101+
/// **'Save changes'**
1102+
String get editMessageSaveTooltip;
1103+
1104+
/// Title shown in the edit message banner
1105+
///
1106+
/// In en, this message translates to:
1107+
/// **'Edit the message'**
1108+
String get editMessageTitle;
1109+
1110+
/// Button label to save changes
1111+
///
1112+
/// In en, this message translates to:
1113+
/// **'Save'**
1114+
String get dialogSave;
10731115
}
10741116

10751117
class _ZulipLocalizationsDelegate extends LocalizationsDelegate<ZulipLocalizations> {

lib/generated/l10n/zulip_localizations_ar.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,12 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
541541
@override
542542
String get messageIsMovedLabel => 'MOVED';
543543

544+
@override
545+
String get messageIsEditingLabel => 'SAVING EDIT...';
546+
547+
@override
548+
String get messageIsEditErrorLabel => 'EDIT ISN\'T SAVED. CHECK YOUR CONNECTION.';
549+
544550
@override
545551
String get pollWidgetQuestionMissing => 'No question.';
546552

@@ -564,4 +570,19 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
564570

565571
@override
566572
String get emojiPickerSearchEmoji => 'Search emoji';
573+
574+
@override
575+
String get actionSheetOptionEditMessage => 'Edit';
576+
577+
@override
578+
String get errorEditingFailed => 'Failed to edit message';
579+
580+
@override
581+
String get editMessageSaveTooltip => 'Save changes';
582+
583+
@override
584+
String get editMessageTitle => 'Edit the message';
585+
586+
@override
587+
String get dialogSave => 'Save';
567588
}

lib/generated/l10n/zulip_localizations_en.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,12 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
541541
@override
542542
String get messageIsMovedLabel => 'MOVED';
543543

544+
@override
545+
String get messageIsEditingLabel => 'SAVING EDIT...';
546+
547+
@override
548+
String get messageIsEditErrorLabel => 'EDIT ISN\'T SAVED. CHECK YOUR CONNECTION.';
549+
544550
@override
545551
String get pollWidgetQuestionMissing => 'No question.';
546552

@@ -564,4 +570,19 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
564570

565571
@override
566572
String get emojiPickerSearchEmoji => 'Search emoji';
573+
574+
@override
575+
String get actionSheetOptionEditMessage => 'Edit';
576+
577+
@override
578+
String get errorEditingFailed => 'Failed to edit message';
579+
580+
@override
581+
String get editMessageSaveTooltip => 'Save changes';
582+
583+
@override
584+
String get editMessageTitle => 'Edit the message';
585+
586+
@override
587+
String get dialogSave => 'Save';
567588
}

lib/generated/l10n/zulip_localizations_ja.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,12 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
541541
@override
542542
String get messageIsMovedLabel => 'MOVED';
543543

544+
@override
545+
String get messageIsEditingLabel => 'SAVING EDIT...';
546+
547+
@override
548+
String get messageIsEditErrorLabel => 'EDIT ISN\'T SAVED. CHECK YOUR CONNECTION.';
549+
544550
@override
545551
String get pollWidgetQuestionMissing => 'No question.';
546552

@@ -564,4 +570,19 @@ class ZulipLocalizationsJa extends ZulipLocalizations {
564570

565571
@override
566572
String get emojiPickerSearchEmoji => 'Search emoji';
573+
574+
@override
575+
String get actionSheetOptionEditMessage => 'Edit';
576+
577+
@override
578+
String get errorEditingFailed => 'Failed to edit message';
579+
580+
@override
581+
String get editMessageSaveTooltip => 'Save changes';
582+
583+
@override
584+
String get editMessageTitle => 'Edit the message';
585+
586+
@override
587+
String get dialogSave => 'Save';
567588
}

lib/generated/l10n/zulip_localizations_nb.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,12 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
541541
@override
542542
String get messageIsMovedLabel => 'MOVED';
543543

544+
@override
545+
String get messageIsEditingLabel => 'SAVING EDIT...';
546+
547+
@override
548+
String get messageIsEditErrorLabel => 'EDIT ISN\'T SAVED. CHECK YOUR CONNECTION.';
549+
544550
@override
545551
String get pollWidgetQuestionMissing => 'No question.';
546552

@@ -564,4 +570,19 @@ class ZulipLocalizationsNb extends ZulipLocalizations {
564570

565571
@override
566572
String get emojiPickerSearchEmoji => 'Search emoji';
573+
574+
@override
575+
String get actionSheetOptionEditMessage => 'Edit';
576+
577+
@override
578+
String get errorEditingFailed => 'Failed to edit message';
579+
580+
@override
581+
String get editMessageSaveTooltip => 'Save changes';
582+
583+
@override
584+
String get editMessageTitle => 'Edit the message';
585+
586+
@override
587+
String get dialogSave => 'Save';
567588
}

lib/generated/l10n/zulip_localizations_pl.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,12 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
541541
@override
542542
String get messageIsMovedLabel => 'PRZENIESIONO';
543543

544+
@override
545+
String get messageIsEditingLabel => 'SAVING EDIT...';
546+
547+
@override
548+
String get messageIsEditErrorLabel => 'EDIT ISN\'T SAVED. CHECK YOUR CONNECTION.';
549+
544550
@override
545551
String get pollWidgetQuestionMissing => 'Brak pytania.';
546552

@@ -564,4 +570,19 @@ class ZulipLocalizationsPl extends ZulipLocalizations {
564570

565571
@override
566572
String get emojiPickerSearchEmoji => 'Szukaj emoji';
573+
574+
@override
575+
String get actionSheetOptionEditMessage => 'Edit';
576+
577+
@override
578+
String get errorEditingFailed => 'Failed to edit message';
579+
580+
@override
581+
String get editMessageSaveTooltip => 'Save changes';
582+
583+
@override
584+
String get editMessageTitle => 'Edit the message';
585+
586+
@override
587+
String get dialogSave => 'Save';
567588
}

lib/generated/l10n/zulip_localizations_ru.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,12 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
541541
@override
542542
String get messageIsMovedLabel => 'ПЕРЕМЕЩЕНО';
543543

544+
@override
545+
String get messageIsEditingLabel => 'SAVING EDIT...';
546+
547+
@override
548+
String get messageIsEditErrorLabel => 'EDIT ISN\'T SAVED. CHECK YOUR CONNECTION.';
549+
544550
@override
545551
String get pollWidgetQuestionMissing => 'Нет вопроса.';
546552

@@ -564,4 +570,19 @@ class ZulipLocalizationsRu extends ZulipLocalizations {
564570

565571
@override
566572
String get emojiPickerSearchEmoji => 'Поиск эмодзи';
573+
574+
@override
575+
String get actionSheetOptionEditMessage => 'Edit';
576+
577+
@override
578+
String get errorEditingFailed => 'Failed to edit message';
579+
580+
@override
581+
String get editMessageSaveTooltip => 'Save changes';
582+
583+
@override
584+
String get editMessageTitle => 'Edit the message';
585+
586+
@override
587+
String get dialogSave => 'Save';
567588
}

lib/generated/l10n/zulip_localizations_sk.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,12 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
541541
@override
542542
String get messageIsMovedLabel => 'PRESUNUTÉ';
543543

544+
@override
545+
String get messageIsEditingLabel => 'SAVING EDIT...';
546+
547+
@override
548+
String get messageIsEditErrorLabel => 'EDIT ISN\'T SAVED. CHECK YOUR CONNECTION.';
549+
544550
@override
545551
String get pollWidgetQuestionMissing => 'Bez otázky.';
546552

@@ -564,4 +570,19 @@ class ZulipLocalizationsSk extends ZulipLocalizations {
564570

565571
@override
566572
String get emojiPickerSearchEmoji => 'Hľadať emotikon';
573+
574+
@override
575+
String get actionSheetOptionEditMessage => 'Edit';
576+
577+
@override
578+
String get errorEditingFailed => 'Failed to edit message';
579+
580+
@override
581+
String get editMessageSaveTooltip => 'Save changes';
582+
583+
@override
584+
String get editMessageTitle => 'Edit the message';
585+
586+
@override
587+
String get dialogSave => 'Save';
567588
}

0 commit comments

Comments
 (0)