mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-05 16:16:49 +00:00
52 lines
2.3 KiB
TypeScript
52 lines
2.3 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useRef, useState, type RefObject } from "react";
|
|
import { registerComposer, type ComposerMetadata } from "@/lib/plugin-sandbox/composer-registry";
|
|
import { replaceTextareaRange, textToEditorHtml } from "@/lib/plugin-sandbox/composer-edit";
|
|
import { generateUUID } from "@/lib/utils";
|
|
import { ComposerPluginToolbarButtons } from "./composer-toolbar-menu";
|
|
|
|
type Props = {
|
|
inputRef: RefObject<HTMLTextAreaElement | null>;
|
|
readMetadata: () => ComposerMetadata;
|
|
onChange: (text: string) => void;
|
|
};
|
|
|
|
/** Own the quick-reply capability without an extra reading-pane render. */
|
|
export function QuickReplyPluginActions({ inputRef, readMetadata, onChange }: Props) {
|
|
const [composerId] = useState(generateUUID);
|
|
const metadataRef = useRef(readMetadata);
|
|
metadataRef.current = readMetadata;
|
|
useEffect(() => {
|
|
const registration = registerComposer({
|
|
readBody: () => { const text = inputRef.current?.value ?? ''; return { text, html: textToEditorHtml(text) }; },
|
|
readMetadata: () => metadataRef.current(),
|
|
readSelection: () => {
|
|
const input = inputRef.current;
|
|
const text = input?.value.slice(input.selectionStart, input.selectionEnd) ?? '';
|
|
return { text, html: textToEditorHtml(text), empty: !text };
|
|
},
|
|
replaceBody: (_html, text) => {
|
|
const input = inputRef.current;
|
|
if (!input || input.disabled) return false;
|
|
const changed = replaceTextareaRange(input, 0, input.value.length, text);
|
|
if (changed) onChange(input.value);
|
|
return changed;
|
|
},
|
|
replaceSelection: (_html, text, { below }) => {
|
|
const input = inputRef.current;
|
|
if (!input || input.disabled) return false;
|
|
let from = input.selectionStart;
|
|
let replacement = text;
|
|
if (below) { from = input.selectionEnd; replacement = `\n\n${text}`; }
|
|
const changed = replaceTextareaRange(input, from, input.selectionEnd, replacement);
|
|
if (changed) onChange(input.value);
|
|
return changed;
|
|
},
|
|
attach: async () => false,
|
|
}, composerId);
|
|
return registration.unregister;
|
|
}, [composerId, inputRef, onChange]);
|
|
return <ComposerPluginToolbarButtons alwaysVisible surface="composer-toolbar-actions" context={() => ({ composerId })} />;
|
|
}
|