fix: enforce Composer read-only state

This commit is contained in:
2026-09-01 20:48:16 +09:00
parent 8fbe4218c6
commit 1aeb6fdb35
2 changed files with 12 additions and 2 deletions
@@ -218,6 +218,7 @@
} }
function handlePasteEvent(event: ClipboardEvent): boolean { function handlePasteEvent(event: ClipboardEvent): boolean {
if (disabled || view?.state.readOnly) return false;
const content = event.clipboardData?.getData("text/plain"); const content = event.clipboardData?.getData("text/plain");
if (!content) return false; if (!content) return false;
const measurement = measureComposerPaste(content); const measurement = measureComposerPaste(content);
@@ -255,6 +256,7 @@
currentView: EditorView, currentView: EditorView,
direction: "backward" | "forward", direction: "backward" | "forward",
): boolean { ): boolean {
if (currentView.state.readOnly) return false;
const selection = currentView.state.selection.main; const selection = currentView.state.selection.main;
const pastes = composerPasteAtoms( const pastes = composerPasteAtoms(
currentView.state.doc.toString(), currentView.state.doc.toString(),
@@ -291,7 +293,10 @@
])), ])),
keymap.of([...defaultKeymap, ...historyKeymap]), keymap.of([...defaultKeymap, ...historyKeymap]),
pasteChips, pasteChips,
editable.of(EditorView.editable.of(!disabled)), editable.of([
EditorView.editable.of(!disabled),
EditorState.readOnly.of(disabled),
]),
EditorState.allowMultipleSelections.of(false), EditorState.allowMultipleSelections.of(false),
EditorView.lineWrapping, EditorView.lineWrapping,
EditorView.contentAttributes.of({ EditorView.contentAttributes.of({
@@ -368,7 +373,10 @@
$effect(() => { $effect(() => {
const isDisabled = disabled; const isDisabled = disabled;
view?.dispatch({ view?.dispatch({
effects: editable.reconfigure(EditorView.editable.of(!isDisabled)), effects: editable.reconfigure([
EditorView.editable.of(!isDisabled),
EditorState.readOnly.of(isDisabled),
]),
}); });
}); });
@@ -607,6 +607,8 @@ Deno.test("Worker Console paste chips preserve typed draft and target authority"
composerInput.includes( composerInput.includes(
"composerDeletionRange(selection, pastes, direction)", "composerDeletionRange(selection, pastes, direction)",
) && ) &&
composerInput.includes("EditorState.readOnly.of(isDisabled)") &&
composerInput.includes("if (currentView.state.readOnly) return false") &&
composerInput.includes('chip.setAttribute("aria-label", label)') && composerInput.includes('chip.setAttribute("aria-label", label)') &&
composerInput.includes("preserveExactText = false") && composerInput.includes("preserveExactText = false") &&
consolePage.includes("buildComposerSegmentsRequest(value.segments, {") && consolePage.includes("buildComposerSegmentsRequest(value.segments, {") &&