Skip to content

Commit c1c0e7c

Browse files
committed
refactor: cleanup selection replace logic
1 parent 40ef184 commit c1c0e7c

1 file changed

Lines changed: 22 additions & 24 deletions

File tree

ui/src/components/organisms/markdown/MarkdownCombo.tsx

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ export function MarkdownCombo({ value = "", onChange, ...props }: MDEditorProps)
2929
end: ta.selectionEnd ?? 0,
3030
};
3131
};
32+
const getSelection = (): string => {
33+
updateSelection();
34+
const { start, end } = selectionRef.current;
35+
return value.slice(start, end);
36+
}
3237
const setSelection = (start: number, end: number) => {
3338
requestAnimationFrame(() => {
3439
const ta = textareaRef.current;
@@ -38,6 +43,16 @@ export function MarkdownCombo({ value = "", onChange, ...props }: MDEditorProps)
3843
selectionRef.current = { start: start, end: end };
3944
});
4045
};
46+
const replaceSelection = (replaceText: string) => {
47+
updateSelection();
48+
const { start, end } = selectionRef.current;
49+
50+
const nextValue = value.slice(0, start) + replaceText + value.slice(end);
51+
onChange?.(nextValue);
52+
53+
const nextCursor = start + replaceText.length;
54+
setSelection(nextCursor, nextCursor);
55+
}
4156

4257
useEffect(() => {
4358
const root = editorRef.current;
@@ -93,20 +108,14 @@ export function MarkdownCombo({ value = "", onChange, ...props }: MDEditorProps)
93108
// handle pasting http urls (for auto hyperlink)
94109
const pasteText = e.clipboardData?.getData("text/plain");
95110
if (pasteText?.startsWith("https://")) {
96-
updateSelection();
97-
const { start, end } = selectionRef.current;
98111

99112
// only do special handling if there was text selected
100113
// otherwise use the normal handling, so the undo/redo is preserved
101-
const selectedText = value.slice(start, end);
114+
const selectedText = getSelection();
102115
if (selectedText) {
103116
e.preventDefault();
104-
const replaceText = `[${selectedText}](${pasteText})`;
105-
const nextValue = value.slice(0, start) + replaceText + value.slice(end);
106-
onChange?.(nextValue);
107-
108-
const nextCursor = start + replaceText.length;
109-
setSelection(nextCursor, nextCursor);
117+
const replacementText = `[${selectedText}](${pasteText})`;
118+
replaceSelection(replacementText);
110119
return;
111120
}
112121
}
@@ -115,7 +124,6 @@ export function MarkdownCombo({ value = "", onChange, ...props }: MDEditorProps)
115124
const items = [...(allItems ?? [])].filter((i) => i.type.startsWith("image/"));
116125
if (!items.length) return;
117126

118-
119127
setUploading(true);
120128

121129
for (const item of items) {
@@ -128,8 +136,9 @@ export function MarkdownCombo({ value = "", onChange, ...props }: MDEditorProps)
128136
{
129137
onSuccess: (image) => {
130138
const baseUrl = window.location.origin;
131-
const inserted = `\n\n![pasted image](${baseUrl}/api/v1/image/${image.id})`;
132-
onChange?.(`${value}${inserted}`);
139+
const selectedText = getSelection() || "pasted image";
140+
const replacementText = `![${selectedText}](${baseUrl}/api/v1/image/${image.id})`;
141+
replaceSelection(replacementText);
133142
},
134143
onError: () => toast.error("Failed", { description: "Probably an unsupported file type" }),
135144
onSettled: () => setUploading(false),
@@ -145,19 +154,8 @@ export function MarkdownCombo({ value = "", onChange, ...props }: MDEditorProps)
145154
const toggleEmojiSelector = () => setEmojiOpen((v) => !v);
146155

147156
const handleEmojiClick = (emojiData: EmojiClickData) => {
148-
const emoji = emojiData.emoji;
149-
150-
updateSelection();
151-
152-
const { start, end } = selectionRef.current;
153-
154-
const nextValue = value.slice(0, start) + emoji + value.slice(end);
155-
156-
onChange?.(nextValue);
157+
replaceSelection(emojiData.emoji);
157158
setEmojiOpen(false);
158-
159-
const nextCursor = start + emoji.length;
160-
setSelection(nextCursor, nextCursor);
161159
};
162160

163161
return (

0 commit comments

Comments
 (0)