stoat-for-desktop/components/app/interface/channels/text/EditMessage.tsx

104 lines
2.9 KiB
TypeScript

import { Match, Switch } from "solid-js";
import { useMutation } from "@tanstack/solid-query";
import { Message } from "stoat.js";
import { css } from "styled-system/css";
import { styled } from "styled-system/jsx";
import { useClient } from "@revolt/client";
import { KeybindAction, createKeybind } from "@revolt/keybinds";
import { useModals } from "@revolt/modal";
import { useState } from "@revolt/state";
import { Text } from "@revolt/ui";
import { TextEditor2 } from "@revolt/ui/components/features/texteditor/TextEditor2";
import { useSearchSpace } from "@revolt/ui/components/utils/autoComplete";
export function EditMessage(props: { message: Message }) {
const state = useState();
const client = useClient();
const { openModal, isOpen, pop } = useModals();
const initialValue = [state.draft.editingMessageContent || ""] as const;
const change = useMutation(() => ({
mutationFn: (content: string) => props.message.edit({ content }),
onSuccess() {
state.draft.setEditingMessage(undefined);
},
onError(error) {
openModal({ type: "error2", error });
},
}));
function saveMessage() {
const content = state.draft.editingMessageContent;
if (content?.length) {
state.draft._setNodeReplacement?.(["_focus"]); // focus message box
change.mutate(content);
} else if (isOpen("delete_message")) {
void props.message.delete();
pop();
} else {
openModal({
type: "delete_message",
message: props.message,
});
}
}
createKeybind(KeybindAction.CHAT_CANCEL_EDITING, () => {
state.draft.setEditingMessage(undefined);
state.draft._setNodeReplacement?.(["_focus"]); // focus message box
});
const searchSpace = useSearchSpace(() => props.message, client);
return (
<>
<EditorBox class={css({ flexGrow: 1 })}>
<TextEditor2
autoFocus
onComplete={saveMessage}
onChange={state.draft.setEditingMessageContent}
initialValue={initialValue}
autoCompleteSearchSpace={searchSpace}
/>
</EditorBox>
<Switch
fallback={
<Text size="small">
escape to{" "}
<Action onClick={() => state.draft.setEditingMessage(undefined)}>
cancel
</Action>{" "}
&middot; enter to <Action onClick={saveMessage}>save</Action>
</Text>
}
>
<Match when={change.isPending}>
<Text size="small">Saving message...</Text>
</Match>
</Switch>
</>
);
}
const EditorBox = styled("div", {
base: {
background: "var(--md-sys-color-surface-container-highest)",
color: "var(--md-sys-color-on-surface-container)",
borderRadius: "var(--borderRadius-sm)",
padding: "var(--gap-md)",
},
});
const Action = styled("span", {
base: {
fontWeight: 600,
cursor: "pointer",
color: "var(--md-sys-color-primary)",
},
});