diff --git a/src/components/ui/DateDivider.tsx b/src/components/ui/DateDivider.tsx
index f310753dec1639fb25faf30597bd76e9e162168e..5f6e1a0af05e73af8347794bc3b25923e31cce95 100644
--- a/src/components/ui/DateDivider.tsx
+++ b/src/components/ui/DateDivider.tsx
@@ -4,9 +4,9 @@ import styled, { css } from "styled-components";
 const Base = styled.div<{ unread?: boolean }>`
     height: 0;
     display: flex;
-    margin: 14px 10px;
     user-select: none;
     align-items: center;
+    margin: 17px 12px 5px;
     border-top: thin solid var(--tertiary-foreground);
 
     time {
diff --git a/src/lib/ContextMenus.tsx b/src/lib/ContextMenus.tsx
index c1d35ba08186eb539e432f797c42732a6bcef32e..e0e3a37570451b60eb7fb1828d769fb3519fe345 100644
--- a/src/lib/ContextMenus.tsx
+++ b/src/lib/ContextMenus.tsx
@@ -17,6 +17,7 @@ import { useChannel, useChannelPermission, useForceUpdate, useServer, useServerP
 import { Children } from "../types/Preact";
 import LineDivider from "../components/ui/LineDivider";
 import { connectState } from "../redux/connector";
+import { internalEmit } from "./eventEmitter";
 
 interface ContextMenuData {
     user?: string;
@@ -162,7 +163,7 @@ function ContextMenus(props: WithDispatcher) {
 
                 case "edit_message":
                     {
-                        // InternalEventEmitter.emit("edit_message", data.id);
+                        internalEmit("MessageRenderer", "edit_message", data.id);
                     }
                     break;
 
diff --git a/src/lib/eventEmitter.ts b/src/lib/eventEmitter.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5eaf08d1f033125e651e0b0ef45b80f27a43ae32
--- /dev/null
+++ b/src/lib/eventEmitter.ts
@@ -0,0 +1,18 @@
+import EventEmitter from "eventemitter3";
+export const InternalEvent = new EventEmitter();
+
+export function internalSubscribe(ns: string, event: string, fn: (...args: any[]) => void) {
+    InternalEvent.addListener(ns + '/' + event, fn);
+    return () => InternalEvent.removeListener(ns + '/' + event, fn);
+}
+
+export function internalEmit(ns: string, event: string, ...args: any[]) {
+    InternalEvent.emit(ns + '/' + event, ...args);
+}
+
+// Event structure: namespace/event
+
+/// Event List
+// - MessageRenderer/edit_last
+// - MessageRenderer/edit_message
+// - MessageBox/focus
diff --git a/src/pages/channels/messaging/MessageEditor.tsx b/src/pages/channels/messaging/MessageEditor.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..065eb4cd11a424899b2da60d5904813723d1bc84
--- /dev/null
+++ b/src/pages/channels/messaging/MessageEditor.tsx
@@ -0,0 +1,84 @@
+import styled from "styled-components";
+import { useContext, useState } from "preact/hooks";
+import TextAreaAutoSize from "../../../lib/TextAreaAutoSize";
+import { MessageObject } from "../../../context/revoltjs/util";
+import { AppContext } from "../../../context/revoltjs/RevoltClient";
+import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
+
+const EditorBase = styled.div`
+    display: flex;
+    flex-direction: column;
+
+    textarea {
+        resize: none;
+        padding: 12px;
+        border-radius: 3px;
+        white-space: pre-wrap;
+        background: var(--secondary-header);
+    }
+
+    .caption {
+        padding: 2px;
+        font-size: 11px;
+        color: var(--tertiary-foreground);
+
+        a {
+            cursor: pointer;
+            &:hover {
+                text-decoration: underline;
+            }
+        }
+    }
+`;
+
+interface Props {
+    message: MessageObject
+    finish: () => void
+}
+
+export default function MessageEditor({ message, finish }: Props) {
+    const [ content, setContent ] = useState(message.content as string ?? '');
+    const client = useContext(AppContext);
+
+    async function save() {
+        finish();
+
+        if (content.length === 0) {
+            // @ts-expect-error
+            openScreen({ id: 'special_prompt', type: 'delete_message', target: message });
+        } else if (content !== message.content) {
+            await client.channels.editMessage(
+                message.channel,
+                message._id,
+                { content }
+            );
+        }
+    }
+
+    return (
+        <EditorBase>
+            <TextAreaAutoSize
+                maxRows={3}
+                padding={12}
+                value={content}
+                maxLength={2000}
+                onChange={ev => setContent(ev.currentTarget.value)}
+                onKeyDown={e => {
+                    if (
+                        !e.shiftKey &&
+                        e.key === "Enter" &&
+                        !isTouchscreenDevice
+                    ) {
+                        e.preventDefault();
+                        save();
+                    }
+                }}
+                // forceFocus
+            />
+            <span className="caption">
+                escape to <a onClick={finish}>cancel</a> &middot;
+                enter to <a onClick={save}>save</a>
+            </span>
+        </EditorBase>
+    )
+}
diff --git a/src/pages/channels/messaging/MessageRenderer.tsx b/src/pages/channels/messaging/MessageRenderer.tsx
index b1b5493653ecf7d299989f01716596e5a16a8a15..4f30cd982c63f001c53ce57dec20f1ff2f6482b3 100644
--- a/src/pages/channels/messaging/MessageRenderer.tsx
+++ b/src/pages/channels/messaging/MessageRenderer.tsx
@@ -1,4 +1,6 @@
 import { decodeTime } from "ulid";
+import MessageEditor from "./MessageEditor";
+import { Children } from "../../../types/Preact";
 import { useEffect, useState } from "preact/hooks";
 import ConversationStart from "./ConversationStart";
 import { connectState } from "../../../redux/connector";
@@ -7,11 +9,11 @@ import { RenderState } from "../../../lib/renderer/types";
 import DateDivider from "../../../components/ui/DateDivider";
 import { QueuedMessage } from "../../../redux/reducers/queue";
 import { MessageObject } from "../../../context/revoltjs/util";
+import Message from "../../../components/common/messaging/Message";
 import RequiresOnline from "../../../context/revoltjs/RequiresOnline";
 import { useForceUpdate, useUsers } from "../../../context/revoltjs/hooks";
-import { Children } from "../../../types/Preact";
+import { internalSubscribe, internalEmit } from "../../../lib/eventEmitter";
 import { SystemMessage } from "../../../components/common/messaging/SystemMessage";
-import Message from "../../../components/common/messaging/Message";
 
 interface Props {
     id: string;
@@ -32,8 +34,9 @@ function MessageRenderer({ id, state, queue }: Props) {
     const [editing, setEditing] = useState<string | undefined>(undefined);
     const stopEditing = () => {
         setEditing(undefined);
-        // InternalEventEmitter.emit("focus_textarea", "message");
+        internalEmit("MessageBox", "focus");
     };
+
     useEffect(() => {
         function editLast() {
             if (state.type !== 'RENDER') return;
@@ -45,13 +48,12 @@ function MessageRenderer({ id, state, queue }: Props) {
             }
         }
 
-        // InternalEventEmitter.addListener("edit_last", editLast);
-        // InternalEventEmitter.addListener("edit_message", setEditing);
+        const subs = [
+            internalSubscribe("MessageRenderer", "edit_last", editLast),
+            internalSubscribe("MessageRenderer", "edit_message", setEditing)
+        ]
 
-        return () => {
-            // InternalEventEmitter.removeListener("edit_last", editLast);
-            // InternalEventEmitter.removeListener("edit_message", setEditing);
-        };
+        return () => subs.forEach(unsub => unsub());
     }, [state.messages]);
 
     let render: Children[] = [],
@@ -107,17 +109,13 @@ function MessageRenderer({ id, state, queue }: Props) {
                 <Message message={message}
                     key={message._id}
                     head={head}
+                    content={
+                        editing === message._id ?
+                            <MessageEditor message={message} finish={stopEditing} />
+                            : undefined
+                    }
                     attachContext />
             );
-            /*render.push(
-                <Message
-                    editing={editing === message._id ? stopEditing : undefined}
-                    user={users.find(x => x?._id === message.author)}
-                    message={message}
-                    key={message._id}
-                    head={head}
-                />
-            );*/
         }
 
         previous = message;