A whole lot of enhancements

This commit is contained in:
Zef Hemel
2022-04-04 15:25:07 +02:00
parent 16577c8ea2
commit a7cd3ea7e0
26 changed files with 322 additions and 181 deletions
+21
View File
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="panel.scss" rel="stylesheet" />
<base target="_top">
<script type="module">
window.addEventListener("message", (message) => {
const data = message.data;
switch(data.type) {
case "html":
document.body.innerHTML = data.html;
break;
}
})
</script>
</head>
<body>
Send me HTML
</body>
</html>
+4
View File
@@ -0,0 +1,4 @@
body {
background: white;
font-family: "Menlo";
}
+24 -4
View File
@@ -1,12 +1,32 @@
import { useRef } from "react";
import {useEffect, useRef} from "react";
// @ts-ignore
import iframeHtml from "bundle-text:./panel.html";
import {Simulate} from "react-dom/test-utils";
export function Panel({ html }: { html: string }) {
const iFrameRef = useRef<HTMLIFrameElement>(null);
// @ts-ignore
window.iframeRef = iFrameRef;
useEffect(() => {
function loadContent() {
if (iFrameRef.current?.contentWindow) {
iFrameRef.current.contentWindow.postMessage({
type: "html",
html: html,
});
}
}
if (!iFrameRef.current) {
return;
}
let iframe = iFrameRef.current;
iframe.onload = loadContent;
loadContent();
return () => {
iframe.onload = null;
};
}, [html]);
return (
<div className="panel">
<iframe srcDoc={html} ref={iFrameRef} />
<iframe srcDoc={iframeHtml} ref={iFrameRef} />
</div>
);
}
+4 -2
View File
@@ -1,4 +1,4 @@
import { EditorView } from "@codemirror/view";
import {EditorView} from "@codemirror/view";
import * as util from "../util";
export function StatusBar({ editorView }: { editorView?: EditorView }) {
@@ -11,7 +11,9 @@ export function StatusBar({ editorView }: { editorView?: EditorView }) {
}
return (
<div id="bottom">
{wordCount} words | {readingTime} min
<div className="inner">
{wordCount} words | {readingTime} min
</div>
</div>
);
}
+19 -9
View File
@@ -6,18 +6,18 @@ import {bracketMatching} from "@codemirror/matchbrackets";
import {searchKeymap} from "@codemirror/search";
import {EditorSelection, EditorState} from "@codemirror/state";
import {
drawSelection,
dropCursor,
EditorView,
highlightSpecialChars,
KeyBinding,
keymap,
ViewPlugin,
ViewUpdate,
drawSelection,
dropCursor,
EditorView,
highlightSpecialChars,
KeyBinding,
keymap,
ViewPlugin,
ViewUpdate,
} from "@codemirror/view";
import React, {useEffect, useReducer} from "react";
import ReactDOM from "react-dom";
import {createSandbox as createIFrameSandbox} from "../plugos/environments/iframe_sandbox";
import {createSandbox as createIFrameSandbox} from "../plugos/environments/webworker_sandbox";
import {AppEvent, AppEventDispatcher, ClickEvent} from "./app_event";
import * as commands from "./commands";
import {CommandPalette} from "./components/command_palette";
@@ -46,6 +46,8 @@ import {SlashCommandHook} from "./hooks/slash_command";
import {CompleterHook} from "./hooks/completer";
import {pasteLinkExtension} from "./editor_paste";
import {markdownSyscalls} from "../common/syscalls/markdown";
import {clientStoreSyscalls} from "./syscalls/clientStore";
import {StatusBar} from "./components/status_bar";
class PageState {
scrollTop: number;
@@ -71,6 +73,9 @@ export class Editor implements AppEventDispatcher {
pageNavigator: PathPageNavigator;
eventHook: EventHook;
saveTimeout: any;
debouncedUpdateEvent = throttle(() => {
this.eventHook.dispatchEvent("editor:updated");
}, 1000);
private system = new System<SilverBulletHooks>("client");
constructor(space: Space, parent: Element) {
@@ -114,6 +119,7 @@ export class Editor implements AppEventDispatcher {
this.system.registerSyscalls([], indexerSyscalls(this.space));
this.system.registerSyscalls([], systemSyscalls(this.space));
this.system.registerSyscalls([], markdownSyscalls());
this.system.registerSyscalls([], clientStoreSyscalls());
}
get currentPage(): string | undefined {
@@ -357,6 +363,7 @@ export class Editor implements AppEventDispatcher {
update(update: ViewUpdate): void {
if (update.docChanged) {
editor.viewDispatch({ type: "page-changed" });
editor.debouncedUpdateEvent();
editor.save();
}
}
@@ -438,6 +445,8 @@ export class Editor implements AppEventDispatcher {
type: "page-loaded",
name: pageName,
});
await this.eventHook.dispatchEvent("editor:pageSwitched");
}
ViewComponent(): React.ReactElement {
@@ -494,6 +503,7 @@ export class Editor implements AppEventDispatcher {
}}
/>
<div id="editor" />
<StatusBar editorView={editor.editorView} />
</div>
);
}
+5 -2
View File
@@ -1,4 +1,4 @@
import { safeRun } from "./util";
import {safeRun} from "./util";
function encodePageUrl(name: string): string {
return name.replaceAll(" ", "_");
@@ -33,7 +33,10 @@ export class PathPageNavigator {
return;
}
safeRun(async () => {
await pageLoadCallback(this.getCurrentPage(), event && event.state.pos);
await pageLoadCallback(
this.getCurrentPage(),
event?.state && event.state.pos
);
if (this.navigationResolve) {
this.navigationResolve();
}
+3
View File
@@ -0,0 +1,3 @@
$max-editor-width: 800px;
$top-bar-height: 55px;
$bottom-bar-height: 30px;
+7 -1
View File
@@ -1,3 +1,9 @@
@import "constants.scss";
div.rhs-open #editor .cm-editor .cm-content {
max-width: 550px;
}
.cm-editor {
width: 100%;
height: 100%;
@@ -6,7 +12,7 @@
.cm-content {
font-family: var(--editor-font);
margin: auto;
max-width: 800px;
max-width: $max-editor-width;
}
.other-cursor {
+35 -13
View File
@@ -1,5 +1,7 @@
@use "editor.scss";
@use "filter_box.scss";
@import "constants";
:root {
--ident: 18px;
@@ -19,25 +21,24 @@ body {
.panel {
position: absolute;
top: 55px;
bottom: 0;
top: $top-bar-height + 1px;
bottom: $bottom-bar-height;
right: 0;
width: 400px;
width: 50%;
z-index: 20;
background: #efefef;
iframe {
border: 0;
width: 100%;
height: 100%;
padding: 10px;
scroll: auto;
padding: 0px;
margin: 0;
}
}
#top {
height: 55px;
position: absolute;
height: $top-bar-height;
position: fixed;
top: 0;
left: 0;
right: 0;
@@ -47,7 +48,7 @@ body {
.inner {
padding-top: 12px;
max-width: 800px;
max-width: $max-editor-width;
font-size: 28px;
margin: auto;
@@ -82,19 +83,40 @@ body {
#editor {
position: absolute;
top: 55px;
bottom: 50px;
top: $top-bar-height;
bottom: $bottom-bar-height;
left: 0;
right: 0;
overflow-y: hidden;
}
div.rhs-open #editor {
right: 350px;
right: 50%;
}
@media only screen and (max-width: 800px) {
div.rhs-open #top .inner {
max-width: 550px;
padding-right: 50%;
}
@media only screen and (max-width: $max-editor-width) {
.cm-editor .cm-content {
margin: 0 10px !important;
}
}
#bottom {
height: $bottom-bar-height;
background-color: #ccc;
position: fixed;
text-align: right;
bottom: 0;
left: 0;
right: 0;
background-color: rgb(213, 213, 213);
border-top: rgb(193, 193, 193) 1px solid;
.inner {
padding: 5px;
}
}
+13
View File
@@ -0,0 +1,13 @@
import {transportSyscalls} from "../../plugos/syscalls/transport";
import {SysCallMapping} from "../../plugos/system";
import {storeSyscalls} from "../../plugos/syscalls/store.dexie_browser";
export function clientStoreSyscalls(): SysCallMapping {
const storeCalls = storeSyscalls("local", "localData");
return transportSyscalls(
["clientStore.get", "clientStore.set", "clientStore.delete"],
(ctx, name, ...args) => {
return storeCalls[name.replace("clientStore.", "store.")](ctx, ...args);
}
);
}
+6 -34
View File
@@ -1,5 +1,4 @@
import {Editor} from "../editor";
import {syntaxTree} from "@codemirror/language";
import {Transaction} from "@codemirror/state";
import {SysCallMapping} from "../../plugos/system";
@@ -58,6 +57,11 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
html: html,
});
},
"editor.hideRhs": (ctx, html: string) => {
editor.viewDispatch({
type: "hide-rhs",
});
},
"editor.insertAtPos": (ctx, text: string, pos: number) => {
editor.editorView!.dispatch({
changes: {
@@ -95,27 +99,7 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
},
});
},
"editor.getSyntaxNodeUnderCursor": (): SyntaxNode | undefined => {
const editorState = editor.editorView!.state;
let selection = editorState.selection.main;
if (selection.empty) {
let node = syntaxTree(editorState).resolveInner(selection.from);
if (node) {
return {
name: node.name,
text: editorState.sliceDoc(node.from, node.to),
from: node.from,
to: node.to,
};
}
}
},
"editor.getLineUnderCursor": (): string => {
const editorState = editor.editorView!.state;
let selection = editorState.selection.main;
let line = editorState.doc.lineAt(selection.from);
return editorState.sliceDoc(line.from, line.to);
},
"editor.matchBefore": (
ctx,
regexp: string
@@ -135,18 +119,6 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
}
return null;
},
"editor.getSyntaxNodeAtPos": (ctx, pos: number): SyntaxNode | undefined => {
const editorState = editor.editorView!.state;
let node = syntaxTree(editorState).resolveInner(pos);
if (node) {
return {
name: node.name,
text: editorState.sliceDoc(node.from, node.to),
from: node.from,
to: node.to,
};
}
},
"editor.dispatch": (ctx, change: Transaction) => {
editor.editorView!.dispatch(change);
},