Add global event pipeline.

Add message editor back.
This commit is contained in:
Paul 2021-06-22 10:28:13 +01:00
parent ef2848ee25
commit 5db0854b42
5 changed files with 121 additions and 20 deletions

View file

@ -4,9 +4,9 @@ import styled, { css } from "styled-components";
const Base = styled.div<{ unread?: boolean }>` const Base = styled.div<{ unread?: boolean }>`
height: 0; height: 0;
display: flex; display: flex;
margin: 14px 10px;
user-select: none; user-select: none;
align-items: center; align-items: center;
margin: 17px 12px 5px;
border-top: thin solid var(--tertiary-foreground); border-top: thin solid var(--tertiary-foreground);
time { time {

View file

@ -17,6 +17,7 @@ import { useChannel, useChannelPermission, useForceUpdate, useServer, useServerP
import { Children } from "../types/Preact"; import { Children } from "../types/Preact";
import LineDivider from "../components/ui/LineDivider"; import LineDivider from "../components/ui/LineDivider";
import { connectState } from "../redux/connector"; import { connectState } from "../redux/connector";
import { internalEmit } from "./eventEmitter";
interface ContextMenuData { interface ContextMenuData {
user?: string; user?: string;
@ -162,7 +163,7 @@ function ContextMenus(props: WithDispatcher) {
case "edit_message": case "edit_message":
{ {
// InternalEventEmitter.emit("edit_message", data.id); internalEmit("MessageRenderer", "edit_message", data.id);
} }
break; break;

18
src/lib/eventEmitter.ts Normal file
View file

@ -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

View file

@ -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>
)
}

View file

@ -1,4 +1,6 @@
import { decodeTime } from "ulid"; import { decodeTime } from "ulid";
import MessageEditor from "./MessageEditor";
import { Children } from "../../../types/Preact";
import { useEffect, useState } from "preact/hooks"; import { useEffect, useState } from "preact/hooks";
import ConversationStart from "./ConversationStart"; import ConversationStart from "./ConversationStart";
import { connectState } from "../../../redux/connector"; import { connectState } from "../../../redux/connector";
@ -7,11 +9,11 @@ import { RenderState } from "../../../lib/renderer/types";
import DateDivider from "../../../components/ui/DateDivider"; import DateDivider from "../../../components/ui/DateDivider";
import { QueuedMessage } from "../../../redux/reducers/queue"; import { QueuedMessage } from "../../../redux/reducers/queue";
import { MessageObject } from "../../../context/revoltjs/util"; import { MessageObject } from "../../../context/revoltjs/util";
import Message from "../../../components/common/messaging/Message";
import RequiresOnline from "../../../context/revoltjs/RequiresOnline"; import RequiresOnline from "../../../context/revoltjs/RequiresOnline";
import { useForceUpdate, useUsers } from "../../../context/revoltjs/hooks"; 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 { SystemMessage } from "../../../components/common/messaging/SystemMessage";
import Message from "../../../components/common/messaging/Message";
interface Props { interface Props {
id: string; id: string;
@ -32,8 +34,9 @@ function MessageRenderer({ id, state, queue }: Props) {
const [editing, setEditing] = useState<string | undefined>(undefined); const [editing, setEditing] = useState<string | undefined>(undefined);
const stopEditing = () => { const stopEditing = () => {
setEditing(undefined); setEditing(undefined);
// InternalEventEmitter.emit("focus_textarea", "message"); internalEmit("MessageBox", "focus");
}; };
useEffect(() => { useEffect(() => {
function editLast() { function editLast() {
if (state.type !== 'RENDER') return; if (state.type !== 'RENDER') return;
@ -45,13 +48,12 @@ function MessageRenderer({ id, state, queue }: Props) {
} }
} }
// InternalEventEmitter.addListener("edit_last", editLast); const subs = [
// InternalEventEmitter.addListener("edit_message", setEditing); internalSubscribe("MessageRenderer", "edit_last", editLast),
internalSubscribe("MessageRenderer", "edit_message", setEditing)
]
return () => { return () => subs.forEach(unsub => unsub());
// InternalEventEmitter.removeListener("edit_last", editLast);
// InternalEventEmitter.removeListener("edit_message", setEditing);
};
}, [state.messages]); }, [state.messages]);
let render: Children[] = [], let render: Children[] = [],
@ -107,17 +109,13 @@ function MessageRenderer({ id, state, queue }: Props) {
<Message message={message} <Message message={message}
key={message._id} key={message._id}
head={head} head={head}
content={
editing === message._id ?
<MessageEditor message={message} finish={stopEditing} />
: undefined
}
attachContext /> 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; previous = message;