From fd8645c1574b4a04f87e8045e8ca16b358c24260 Mon Sep 17 00:00:00 2001 From: Zef Hemel Date: Mon, 16 Jan 2023 11:28:59 +0100 Subject: [PATCH] Nicer read-only mode --- web/cm_plugins/readonly.ts | 7 +++++++ web/editor.tsx | 42 ++++++++++++++++++++++---------------- web/reducer.ts | 2 +- web/types.ts | 5 +---- 4 files changed, 33 insertions(+), 23 deletions(-) create mode 100644 web/cm_plugins/readonly.ts diff --git a/web/cm_plugins/readonly.ts b/web/cm_plugins/readonly.ts new file mode 100644 index 00000000..05eebe29 --- /dev/null +++ b/web/cm_plugins/readonly.ts @@ -0,0 +1,7 @@ +import { EditorState } from "../deps.ts"; + +export function readonlyMode() { + return EditorState.changeFilter.of((tr): boolean => { + return !tr.docChanged; + }); +} diff --git a/web/editor.tsx b/web/editor.tsx index efe71282..123ce0a7 100644 --- a/web/editor.tsx +++ b/web/editor.tsx @@ -80,13 +80,9 @@ import { SlashCommandHook } from "./hooks/slash_command.ts"; import { PathPageNavigator } from "./navigator.ts"; import reducer from "./reducer.ts"; import customMarkdownStyle from "./style.ts"; -import { clientStoreSyscalls } from "./syscalls/clientStore.ts"; import { collabSyscalls } from "./syscalls/collab.ts"; import { editorSyscalls } from "./syscalls/editor.ts"; -import { fulltextSyscalls } from "./syscalls/fulltext.ts"; -import { indexerSyscalls } from "./syscalls/index.ts"; import { spaceSyscalls } from "./syscalls/space.ts"; -import { storeSyscalls } from "./syscalls/store.ts"; import { systemSyscalls } from "./syscalls/system.ts"; import { AppViewState, BuiltinSettings, initialViewState } from "./types.ts"; @@ -96,9 +92,8 @@ import type { CompleteEvent, } from "../plug-api/app_event.ts"; import { CodeWidgetHook } from "./hooks/code_widget.ts"; -import { sandboxFetchSyscalls } from "../plugos/syscalls/fetch.ts"; -import { syncSyscalls } from "../common/syscalls/sync.ts"; import { throttle } from "../common/async_util.ts"; +import { readonlyMode } from "./cm_plugins/readonly.ts"; const frontMatterRegex = /^---\n(.*?)---\n/ms; @@ -179,7 +174,7 @@ export class Editor { this.render(parent); this.editorView = new EditorView({ - state: this.createEditorState("", ""), + state: this.createEditorState("", "", false), parent: document.getElementById("sb-editor")!, }); @@ -448,7 +443,11 @@ export class Editor { return this.eventHook.dispatchEvent(name, data); } - createEditorState(pageName: string, text: string): EditorState { + createEditorState( + pageName: string, + text: string, + readOnly: boolean, + ): EditorState { const commandKeyBindings: KeyBinding[] = []; for (const def of this.commandHook.editorCommands.values()) { if (def.command.key) { @@ -491,6 +490,11 @@ export class Editor { EditorView.theme({}, { dark: this.viewState.uiOptions.darkMode }), // Enable vim mode, or not [...editor.viewState.uiOptions.vimMode ? [vim({ status: true })] : []], + [ + ...readOnly || editor.viewState.uiOptions.forcedROMode + ? [readonlyMode()] + : [], + ], // The uber markdown mode markdown({ base: buildMarkdown(this.mdExtensions), @@ -708,12 +712,15 @@ export class Editor { this.saveState(this.currentPage); editorView.setState( - this.createEditorState(this.currentPage, editorView.state.sliceDoc()), + this.createEditorState( + this.currentPage, + editorView.state.sliceDoc(), + this.viewState.currentPageMeta?.perm === "ro", + ), ); if (editorView.contentDOM) { this.tweakEditorDOM( editorView.contentDOM, - this.viewState.perm === "ro", ); } @@ -833,10 +840,14 @@ export class Editor { }; } - const editorState = this.createEditorState(pageName, doc.text); + const editorState = this.createEditorState( + pageName, + doc.text, + doc.meta.perm === "ro", + ); editorView.setState(editorState); if (editorView.contentDOM) { - this.tweakEditorDOM(editorView.contentDOM, doc.meta.perm === "ro"); + this.tweakEditorDOM(editorView.contentDOM); } const stateRestored = this.restoreState(pageName); this.space.watchPage(pageName); @@ -860,14 +871,10 @@ export class Editor { return stateRestored; } - tweakEditorDOM(contentDOM: HTMLElement, readOnly: boolean) { + tweakEditorDOM(contentDOM: HTMLElement) { contentDOM.spellcheck = true; contentDOM.setAttribute("autocorrect", "on"); contentDOM.setAttribute("autocapitalize", "on"); - contentDOM.setAttribute( - "contenteditable", - readOnly || this.viewState.uiOptions.forcedROMode ? "false" : "true", - ); } private restoreState(pageName: string): boolean { @@ -919,7 +926,6 @@ export class Editor { if (editor.editorView) { editor.tweakEditorDOM( editor.editorView.contentDOM, - viewState.perm === "ro", ); } }, [viewState.uiOptions.forcedROMode]); diff --git a/web/reducer.ts b/web/reducer.ts index 9675e5ef..822bded1 100644 --- a/web/reducer.ts +++ b/web/reducer.ts @@ -23,8 +23,8 @@ export default function reducer( : pageMeta ), ), - perm: action.meta.perm, currentPage: action.meta.name, + currentPageMeta: action.meta, }; case "page-changed": return { diff --git a/web/types.ts b/web/types.ts index aae40352..56beca36 100644 --- a/web/types.ts +++ b/web/types.ts @@ -25,8 +25,7 @@ export type PanelConfig = { export type AppViewState = { currentPage?: string; - editingPageName: boolean; - perm: EditorMode; + currentPageMeta?: PageMeta; isLoading: boolean; showPageNavigator: boolean; showCommandPalette: boolean; @@ -65,8 +64,6 @@ export type AppViewState = { }; export const initialViewState: AppViewState = { - perm: "rw", - editingPageName: false, isLoading: false, showPageNavigator: false, showCommandPalette: false,