diff --git a/web/workspace/src/lib/workspace/console/ComposerInput.svelte b/web/workspace/src/lib/workspace/console/ComposerInput.svelte index 55aa74bd..6d0b0321 100644 --- a/web/workspace/src/lib/workspace/console/ComposerInput.svelte +++ b/web/workspace/src/lib/workspace/console/ComposerInput.svelte @@ -218,6 +218,7 @@ } function handlePasteEvent(event: ClipboardEvent): boolean { + if (disabled || view?.state.readOnly) return false; const content = event.clipboardData?.getData("text/plain"); if (!content) return false; const measurement = measureComposerPaste(content); @@ -255,6 +256,7 @@ currentView: EditorView, direction: "backward" | "forward", ): boolean { + if (currentView.state.readOnly) return false; const selection = currentView.state.selection.main; const pastes = composerPasteAtoms( currentView.state.doc.toString(), @@ -291,7 +293,10 @@ ])), keymap.of([...defaultKeymap, ...historyKeymap]), pasteChips, - editable.of(EditorView.editable.of(!disabled)), + editable.of([ + EditorView.editable.of(!disabled), + EditorState.readOnly.of(disabled), + ]), EditorState.allowMultipleSelections.of(false), EditorView.lineWrapping, EditorView.contentAttributes.of({ @@ -368,7 +373,10 @@ $effect(() => { const isDisabled = disabled; view?.dispatch({ - effects: editable.reconfigure(EditorView.editable.of(!isDisabled)), + effects: editable.reconfigure([ + EditorView.editable.of(!isDisabled), + EditorState.readOnly.of(isDisabled), + ]), }); }); diff --git a/web/workspace/src/lib/workspace/console/worker-console.ui.test.ts b/web/workspace/src/lib/workspace/console/worker-console.ui.test.ts index 86d8e875..eac18d19 100644 --- a/web/workspace/src/lib/workspace/console/worker-console.ui.test.ts +++ b/web/workspace/src/lib/workspace/console/worker-console.ui.test.ts @@ -607,6 +607,8 @@ Deno.test("Worker Console paste chips preserve typed draft and target authority" composerInput.includes( "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("preserveExactText = false") && consolePage.includes("buildComposerSegmentsRequest(value.segments, {") &&