fix: attachment upload broken after v2.0.0 upgrade (#1525)

- base.ts: add replaceRange method to CodeMirror adapter
- file.tsx: use replaceSelection to insert loading text (fixes RangeError)
- file.tsx: use useState/useEffect for stable editorState reference in async callbacks

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
diff --git a/ui/src/components/Editor/ToolBars/file.tsx b/ui/src/components/Editor/ToolBars/file.tsx
index d48c0e6..3c2e54b 100644
--- a/ui/src/components/Editor/ToolBars/file.tsx
+++ b/ui/src/components/Editor/ToolBars/file.tsx
@@ -98,8 +98,7 @@
     uploadImage({ file: e.target.files[0], type: 'post_attachment' })
       .then((url) => {
         const text = `[${fileName}](${url})`;
-        editor.replaceRange('', startPos, endPos);
-        editor.replaceSelection(text);
+        editor.replaceRange(text, startPos, endPos);
       })
       .catch(() => {
         editor.replaceRange('', startPos, endPos);
diff --git a/ui/src/components/Editor/utils/codemirror/base.ts b/ui/src/components/Editor/utils/codemirror/base.ts
index 4a257f0..3b20653 100644
--- a/ui/src/components/Editor/utils/codemirror/base.ts
+++ b/ui/src/components/Editor/utils/codemirror/base.ts
@@ -97,6 +97,14 @@
       });
     },
 
+    replaceRange: (value: string, from: Position, to: Position) => {
+      const fromOffset = editor.state.doc.line(from.line).from + from.ch;
+      const toOffset = editor.state.doc.line(to.line).from + to.ch;
+      editor.dispatch({
+        changes: { from: fromOffset, to: toOffset, insert: value },
+      });
+    },
+
     getValue: () => {
       return editor.state.doc.toString();
     },