diff --git a/src/app/currentconversation.cpp b/src/app/currentconversation.cpp
index 787fa2429dc07aaddab0ca439f2ec3f8ba896eb4..b6ea5704308ea82909b154450c81f443d589df4d 100644
--- a/src/app/currentconversation.cpp
+++ b/src/app/currentconversation.cpp
@@ -53,6 +53,7 @@ CurrentConversation::updateData()
         const auto& accInfo = lrcInstance_->accountModel().getAccountInfo(accountId);
         if (auto optConv = accInfo.conversationModel->getConversationForUid(convId)) {
             auto& convInfo = optConv->get();
+            set_lastSelfMessageId(convInfo.lastSelfMessageId);
             set_uris(convInfo.participantsUris());
             set_isSwarm(convInfo.isSwarm());
             set_isLegacy(convInfo.isLegacy());
diff --git a/src/app/currentconversation.h b/src/app/currentconversation.h
index 62c7944f2a86f5955a61221ca1131bd9648d1be0..99d6ae654180ec97c8d95534275911758fe32281 100644
--- a/src/app/currentconversation.h
+++ b/src/app/currentconversation.h
@@ -54,6 +54,7 @@ class CurrentConversation final : public QObject
     QML_PROPERTY(QVariantList, activeCalls)
     QML_PROPERTY(QStringList, errors)
     QML_PROPERTY(QStringList, backendErrors)
+    QML_PROPERTY(QString, lastSelfMessageId)
 
     // TODO: these belong in CurrentCall(which doesn't exist yet)
     QML_PROPERTY(bool, hideSelf)
diff --git a/src/app/mainview/components/ChatView.qml b/src/app/mainview/components/ChatView.qml
index f3990cf08599b950da47fb457dd4a7f86e1d03a6..dfd7f73f138deb99d90868acb57e4bad24aeafd1 100644
--- a/src/app/mainview/components/ChatView.qml
+++ b/src/app/mainview/components/ChatView.qml
@@ -124,7 +124,6 @@ Rectangle {
             }
         }
 
-
         Connections {
             target: CurrentConversation
             enabled: true
@@ -293,4 +292,14 @@ Rectangle {
             }
         }
     }
+
+    Shortcut {
+        sequence: "Ctrl+Escape"
+        context: Qt.WindowShortcut
+        enabled: root.visible
+        onActivated: {
+            MessagesAdapter.replyToId = ""
+            MessagesAdapter.editId = ""
+        }
+    }
 }
diff --git a/src/app/mainview/components/KeyboardShortcutTable.qml b/src/app/mainview/components/KeyboardShortcutTable.qml
index 591ee637b63107f8e160d21467929fdacfbf1045..3e58e876428b8e67c8fb7e57e2ce9a566a68c7a7 100644
--- a/src/app/mainview/components/KeyboardShortcutTable.qml
+++ b/src/app/mainview/components/KeyboardShortcutTable.qml
@@ -105,6 +105,14 @@ Window {
             shortcut: "Shift + Ctrl + A"
             description: qsTr("Accept contact request")
         }
+        ListElement {
+            shortcut: "↑"
+            description: qsTr("Edit last message")
+        }
+        ListElement {
+            shortcut: "Ctrl + Esc"
+            description: qsTr("Cancel message edition")
+        }
     }
 
     ListModel {
diff --git a/src/app/mainview/components/MessageBarTextArea.qml b/src/app/mainview/components/MessageBarTextArea.qml
index b636deec723fb4576c07558e46f6c6d3cdbe0cea..f865fdb03522c3b61bbd3b3fb0eb5317e4f7567e 100644
--- a/src/app/mainview/components/MessageBarTextArea.qml
+++ b/src/app/mainview/components/MessageBarTextArea.qml
@@ -104,6 +104,12 @@ JamiFlickable {
             if (keyEvent.matches(StandardKey.Paste)) {
                 MessagesAdapter.onPaste()
                 keyEvent.accepted = true
+            } else if (keyEvent.matches(StandardKey.MoveToPreviousLine)) {
+                if (root.text !== "")
+                    return
+                MessagesAdapter.replyToId = ""
+                MessagesAdapter.editId = CurrentConversation.lastSelfMessageId
+                keyEvent.accepted = true;
             } else if (keyEvent.key === Qt.Key_Enter ||
                        keyEvent.key === Qt.Key_Return) {
                 if (!(keyEvent.modifiers & Qt.ShiftModifier)) {
diff --git a/src/libclient/api/conversation.h b/src/libclient/api/conversation.h
index 2671b7a1cfc3a3d090206cb749d33884e2f146f7..66c0e6d45295c642ee310e9ce5c47a73a4d42a52 100644
--- a/src/libclient/api/conversation.h
+++ b/src/libclient/api/conversation.h
@@ -78,6 +78,7 @@ struct Info
     QString confId;
     std::unique_ptr<MessageListModel> interactions;
     QString lastMessageUid;
+    QString lastSelfMessageId;
     QHash<QString, QString> parentsId; // pair messageid/parentid for messages without parent loaded
     unsigned int unreadMessages = 0;
     QVector<QPair<int, QString>> errors;
diff --git a/src/libclient/conversationmodel.cpp b/src/libclient/conversationmodel.cpp
index 5604a17c21d55a0bc081a8d7f753a98e9f1e299e..26c8ddc416029d8dd77d4cf86af587a4f6062894 100644
--- a/src/libclient/conversationmodel.cpp
+++ b/src/libclient/conversationmodel.cpp
@@ -1307,6 +1307,7 @@ ConversationModel::sendMessage(const QString& uid, const QString& body, const QS
             }
 
             newConv.lastMessageUid = msgId;
+            newConv.lastSelfMessageId = msgId;
             // Emit this signal for chatview in the client
             Q_EMIT newInteraction(convId, msgId, msg);
             // This conversation is now at the top of the list
@@ -1486,6 +1487,9 @@ ConversationModel::clearInteractionFromConversation(const QString& convId,
                 conversation.lastMessageUid = newLastId;
                 lastInteractionUpdated = true;
             }
+            if (conversation.lastSelfMessageId == interactionId) {
+                conversation.lastSelfMessageId = conversation.interactions->lastSelfMessageId();
+            }
 
         } catch (const std::out_of_range& e) {
             qDebug() << "can't clear interaction from conversation: " << e.what();
@@ -1521,6 +1525,7 @@ ConversationModel::clearInteractionsCache(const QString& convId)
             }
             conversation.allMessagesLoaded = false;
             conversation.lastMessageUid = "";
+            conversation.lastSelfMessageId = "";
             ConfigurationManager::instance().loadConversationMessages(owner.id, convId, "", 1);
         }
     } catch (const std::out_of_range& e) {
@@ -2469,6 +2474,7 @@ ConversationModelPimpl::slotConversationLoaded(uint32_t requestId,
         }
 
         conversation.lastMessageUid = conversation.interactions->lastMessageUid();
+        conversation.lastSelfMessageId = conversation.interactions->lastSelfMessageId();
         if (conversation.lastMessageUid.isEmpty() && !conversation.allMessagesLoaded
             && messages.size() != 0) {
             if (conversation.interactions->size() > 0) {
@@ -2627,6 +2633,7 @@ ConversationModelPimpl::slotMessageReceived(const QString& accountId,
             return;
         }
         conversation.lastMessageUid = conversation.interactions->lastMessageUid();
+        conversation.lastSelfMessageId = conversation.interactions->lastSelfMessageId();
         invalidateModel();
         if (!interaction::isOutgoing(msg)) {
             Q_EMIT behaviorController.newUnreadInteraction(linked.owner.id,
diff --git a/src/libclient/messagelistmodel.cpp b/src/libclient/messagelistmodel.cpp
index e7013b99815de9d05358e1087c43748c090a9c6b..e6913a508f833c54a902f18e3cdcf2dd2ff6594d 100644
--- a/src/libclient/messagelistmodel.cpp
+++ b/src/libclient/messagelistmodel.cpp
@@ -648,4 +648,17 @@ MessageListModel::lastMessageUid() const
     return {};
 }
 
+QString
+MessageListModel::lastSelfMessageId() const
+{
+    for (auto it = interactions_.rbegin(); it != interactions_.rend(); ++it) {
+        auto lastType = it->second.type;
+        if (lastType == interaction::Type::TEXT
+            and !it->second.body.isEmpty() and it->second.authorUri.isEmpty()) {
+            return it->first;
+        }
+    }
+    return {};
+}
+
 } // namespace lrc
diff --git a/src/libclient/messagelistmodel.h b/src/libclient/messagelistmodel.h
index f5b662bf450d13e0344dc016e9b5fac925621270..6c367bf77495b4f05e6d649f7d2c6670e41047de 100644
--- a/src/libclient/messagelistmodel.h
+++ b/src/libclient/messagelistmodel.h
@@ -138,6 +138,7 @@ public:
     void addEdition(const QString& msgId, const interaction::Info& info, bool end);
     void editMessage(const QString& msgId, interaction::Info& info);
     QString lastMessageUid() const;
+    QString lastSelfMessageId() const;
 
 protected:
     using Role = MessageList::Role;