diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml
index a717cb31890e70294a2e07038e9222a54489d534..55860ad6147a8796f5bdf244d8e2853afe5feab6 100644
--- a/resources/qml/MessageView.qml
+++ b/resources/qml/MessageView.qml
@@ -7,6 +7,7 @@ import "./components"
 import "./delegates"
 import "./emoji"
 import "./ui"
+import "./dialogs"
 import Qt.labs.platform 1.1 as Platform
 import QtQuick 2.15
 import QtQuick.Controls 2.15
@@ -585,6 +586,21 @@ Item {
             open();
         }
 
+        Component {
+            id: removeReason
+            InputDialog {
+                id: removeReasonDialog
+
+                property string eventId
+
+                title: qsTr("Reason for removal")
+                prompt: qsTr("Enter reason for removal or hit enter for no reason:")
+                onAccepted: function(text) {
+                    room.redactEvent(eventId, text);
+                }
+            }
+        }
+
         Platform.MenuItem {
             visible: messageContextMenu.text
             enabled: visible
@@ -665,7 +681,13 @@ Item {
         Platform.MenuItem {
             visible: (room ? room.permissions.canRedact() : false) || messageContextMenu.isSender
             text: qsTr("Remo&ve message")
-            onTriggered: room.redactEvent(messageContextMenu.eventId)
+            onTriggered: function() {
+                var dialog = removeReason.createObject(timelineRoot);
+                dialog.eventId = messageContextMenu.eventId;
+                dialog.show();
+                dialog.forceActiveFocus();
+                timelineRoot.destroyOnClose(dialog);
+            }
         }
 
         Platform.MenuItem {
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 903f137f54269f6169b68296c730b9121425b09c..8e6c723550034673c0f0a3f4ffeec2c5c6d50955 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -1240,7 +1240,7 @@ TimelineModel::showReadReceipts(QString id)
 }
 
 void
-TimelineModel::redactEvent(const QString &id)
+TimelineModel::redactEvent(const QString &id, const QString &reason)
 {
     if (!id.isEmpty()) {
         auto edits = events.edits(id.toStdString());
@@ -1255,7 +1255,8 @@ TimelineModel::redactEvent(const QString &id)
               }
 
               emit dataAtIdChanged(id);
-          });
+          },
+          reason.toStdString());
 
         // redact all edits to prevent leaks
         for (const auto &e : edits) {
@@ -1271,7 +1272,8 @@ TimelineModel::redactEvent(const QString &id)
                   }
 
                   emit dataAtIdChanged(id);
-              });
+              },
+              reason.toStdString());
         }
     }
 }
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index e4e3fa9d2581fedbe02eba230bc55791ac23d8e2..f47203f0d91d92d6bd226c4441e2c3649f6fccac 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -272,7 +272,7 @@ public:
     Q_INVOKABLE void unpin(const QString &id);
     Q_INVOKABLE void pin(const QString &id);
     Q_INVOKABLE void showReadReceipts(QString id);
-    Q_INVOKABLE void redactEvent(const QString &id);
+    Q_INVOKABLE void redactEvent(const QString &id, const QString &reason = "");
     Q_INVOKABLE int idToIndex(const QString &id) const;
     Q_INVOKABLE QString indexToId(int index) const;
     Q_INVOKABLE void openMedia(const QString &eventId);