Nicer read-only mode

pull/320/head
Zef Hemel 2023-01-16 11:28:59 +01:00
parent 882f157cf1
commit fd8645c157
4 changed files with 33 additions and 23 deletions

View File

@ -0,0 +1,7 @@
import { EditorState } from "../deps.ts";
export function readonlyMode() {
return EditorState.changeFilter.of((tr): boolean => {
return !tr.docChanged;
});
}

View File

@ -80,13 +80,9 @@ import { SlashCommandHook } from "./hooks/slash_command.ts";
import { PathPageNavigator } from "./navigator.ts"; import { PathPageNavigator } from "./navigator.ts";
import reducer from "./reducer.ts"; import reducer from "./reducer.ts";
import customMarkdownStyle from "./style.ts"; import customMarkdownStyle from "./style.ts";
import { clientStoreSyscalls } from "./syscalls/clientStore.ts";
import { collabSyscalls } from "./syscalls/collab.ts"; import { collabSyscalls } from "./syscalls/collab.ts";
import { editorSyscalls } from "./syscalls/editor.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 { spaceSyscalls } from "./syscalls/space.ts";
import { storeSyscalls } from "./syscalls/store.ts";
import { systemSyscalls } from "./syscalls/system.ts"; import { systemSyscalls } from "./syscalls/system.ts";
import { AppViewState, BuiltinSettings, initialViewState } from "./types.ts"; import { AppViewState, BuiltinSettings, initialViewState } from "./types.ts";
@ -96,9 +92,8 @@ import type {
CompleteEvent, CompleteEvent,
} from "../plug-api/app_event.ts"; } from "../plug-api/app_event.ts";
import { CodeWidgetHook } from "./hooks/code_widget.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 { throttle } from "../common/async_util.ts";
import { readonlyMode } from "./cm_plugins/readonly.ts";
const frontMatterRegex = /^---\n(.*?)---\n/ms; const frontMatterRegex = /^---\n(.*?)---\n/ms;
@ -179,7 +174,7 @@ export class Editor {
this.render(parent); this.render(parent);
this.editorView = new EditorView({ this.editorView = new EditorView({
state: this.createEditorState("", ""), state: this.createEditorState("", "", false),
parent: document.getElementById("sb-editor")!, parent: document.getElementById("sb-editor")!,
}); });
@ -448,7 +443,11 @@ export class Editor {
return this.eventHook.dispatchEvent(name, data); return this.eventHook.dispatchEvent(name, data);
} }
createEditorState(pageName: string, text: string): EditorState { createEditorState(
pageName: string,
text: string,
readOnly: boolean,
): EditorState {
const commandKeyBindings: KeyBinding[] = []; const commandKeyBindings: KeyBinding[] = [];
for (const def of this.commandHook.editorCommands.values()) { for (const def of this.commandHook.editorCommands.values()) {
if (def.command.key) { if (def.command.key) {
@ -491,6 +490,11 @@ export class Editor {
EditorView.theme({}, { dark: this.viewState.uiOptions.darkMode }), EditorView.theme({}, { dark: this.viewState.uiOptions.darkMode }),
// Enable vim mode, or not // Enable vim mode, or not
[...editor.viewState.uiOptions.vimMode ? [vim({ status: true })] : []], [...editor.viewState.uiOptions.vimMode ? [vim({ status: true })] : []],
[
...readOnly || editor.viewState.uiOptions.forcedROMode
? [readonlyMode()]
: [],
],
// The uber markdown mode // The uber markdown mode
markdown({ markdown({
base: buildMarkdown(this.mdExtensions), base: buildMarkdown(this.mdExtensions),
@ -708,12 +712,15 @@ export class Editor {
this.saveState(this.currentPage); this.saveState(this.currentPage);
editorView.setState( editorView.setState(
this.createEditorState(this.currentPage, editorView.state.sliceDoc()), this.createEditorState(
this.currentPage,
editorView.state.sliceDoc(),
this.viewState.currentPageMeta?.perm === "ro",
),
); );
if (editorView.contentDOM) { if (editorView.contentDOM) {
this.tweakEditorDOM( this.tweakEditorDOM(
editorView.contentDOM, 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); editorView.setState(editorState);
if (editorView.contentDOM) { if (editorView.contentDOM) {
this.tweakEditorDOM(editorView.contentDOM, doc.meta.perm === "ro"); this.tweakEditorDOM(editorView.contentDOM);
} }
const stateRestored = this.restoreState(pageName); const stateRestored = this.restoreState(pageName);
this.space.watchPage(pageName); this.space.watchPage(pageName);
@ -860,14 +871,10 @@ export class Editor {
return stateRestored; return stateRestored;
} }
tweakEditorDOM(contentDOM: HTMLElement, readOnly: boolean) { tweakEditorDOM(contentDOM: HTMLElement) {
contentDOM.spellcheck = true; contentDOM.spellcheck = true;
contentDOM.setAttribute("autocorrect", "on"); contentDOM.setAttribute("autocorrect", "on");
contentDOM.setAttribute("autocapitalize", "on"); contentDOM.setAttribute("autocapitalize", "on");
contentDOM.setAttribute(
"contenteditable",
readOnly || this.viewState.uiOptions.forcedROMode ? "false" : "true",
);
} }
private restoreState(pageName: string): boolean { private restoreState(pageName: string): boolean {
@ -919,7 +926,6 @@ export class Editor {
if (editor.editorView) { if (editor.editorView) {
editor.tweakEditorDOM( editor.tweakEditorDOM(
editor.editorView.contentDOM, editor.editorView.contentDOM,
viewState.perm === "ro",
); );
} }
}, [viewState.uiOptions.forcedROMode]); }, [viewState.uiOptions.forcedROMode]);

View File

@ -23,8 +23,8 @@ export default function reducer(
: pageMeta : pageMeta
), ),
), ),
perm: action.meta.perm,
currentPage: action.meta.name, currentPage: action.meta.name,
currentPageMeta: action.meta,
}; };
case "page-changed": case "page-changed":
return { return {

View File

@ -25,8 +25,7 @@ export type PanelConfig = {
export type AppViewState = { export type AppViewState = {
currentPage?: string; currentPage?: string;
editingPageName: boolean; currentPageMeta?: PageMeta;
perm: EditorMode;
isLoading: boolean; isLoading: boolean;
showPageNavigator: boolean; showPageNavigator: boolean;
showCommandPalette: boolean; showCommandPalette: boolean;
@ -65,8 +64,6 @@ export type AppViewState = {
}; };
export const initialViewState: AppViewState = { export const initialViewState: AppViewState = {
perm: "rw",
editingPageName: false,
isLoading: false, isLoading: false,
showPageNavigator: false, showPageNavigator: false,
showCommandPalette: false, showCommandPalette: false,