Work
This commit is contained in:
@@ -10,7 +10,7 @@ export function StatusBar({ editorView }: { editorView?: EditorView }) {
|
||||
readingTime = util.readingTime(wordCount);
|
||||
}
|
||||
return (
|
||||
<div id="bottom">
|
||||
<div id="status-bar">
|
||||
<div className="inner">
|
||||
{wordCount} words | {readingTime} min
|
||||
</div>
|
||||
|
||||
+54
-50
@@ -58,13 +58,10 @@ import { FilterOption } from "@silverbulletmd/common/types";
|
||||
import { syntaxTree } from "@codemirror/language";
|
||||
|
||||
class PageState {
|
||||
scrollTop: number;
|
||||
selection: EditorSelection;
|
||||
|
||||
constructor(scrollTop: number, selection: EditorSelection) {
|
||||
this.scrollTop = scrollTop;
|
||||
this.selection = selection;
|
||||
}
|
||||
constructor(
|
||||
readonly scrollTop: number,
|
||||
readonly selection: EditorSelection
|
||||
) {}
|
||||
}
|
||||
|
||||
const saveInterval = 1000;
|
||||
@@ -123,7 +120,7 @@ export class Editor {
|
||||
this.system.registerSyscalls([], editorSyscalls(this));
|
||||
this.system.registerSyscalls([], spaceSyscalls(this));
|
||||
this.system.registerSyscalls([], indexerSyscalls(this.space));
|
||||
this.system.registerSyscalls([], systemSyscalls(this.space));
|
||||
this.system.registerSyscalls([], systemSyscalls(this));
|
||||
this.system.registerSyscalls(
|
||||
[],
|
||||
markdownSyscalls(buildMarkdown(this.mdExtensions))
|
||||
@@ -153,10 +150,6 @@ export class Editor {
|
||||
}
|
||||
});
|
||||
|
||||
let throttledRebuildEditorState = throttle(() => {
|
||||
this.rebuildEditorState();
|
||||
}, 100);
|
||||
|
||||
this.space.on({
|
||||
pageChanged: (meta) => {
|
||||
if (this.currentPage === meta.name) {
|
||||
@@ -171,22 +164,10 @@ export class Editor {
|
||||
pages: pages,
|
||||
});
|
||||
},
|
||||
plugLoaded: (plugName, plug) => {
|
||||
safeRun(async () => {
|
||||
console.log("Plug load", plugName);
|
||||
await this.system.load(plugName, plug, createIFrameSandbox);
|
||||
throttledRebuildEditorState();
|
||||
});
|
||||
},
|
||||
plugUnloaded: (plugName) => {
|
||||
safeRun(async () => {
|
||||
console.log("Plug unload", plugName);
|
||||
await this.system.unload(plugName);
|
||||
throttledRebuildEditorState();
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
await this.reloadPlugs();
|
||||
|
||||
if (this.pageNavigator.getCurrentPage() === "") {
|
||||
await this.pageNavigator.navigate("start");
|
||||
}
|
||||
@@ -359,7 +340,7 @@ export class Editor {
|
||||
mac: "Cmd-k",
|
||||
run: (): boolean => {
|
||||
this.viewDispatch({ type: "start-navigate" });
|
||||
this.space.updatePageListAsync();
|
||||
this.space.updatePageList();
|
||||
return true;
|
||||
},
|
||||
},
|
||||
@@ -427,6 +408,17 @@ export class Editor {
|
||||
});
|
||||
}
|
||||
|
||||
async reloadPlugs() {
|
||||
await this.space.updatePageList();
|
||||
await this.system.unloadAll();
|
||||
console.log("(Re)loading plugs");
|
||||
for (let pageInfo of this.space.listPlugs()) {
|
||||
let { text } = await this.space.readPage(pageInfo.name);
|
||||
await this.system.load(JSON.parse(text), createIFrameSandbox);
|
||||
}
|
||||
this.rebuildEditorState();
|
||||
}
|
||||
|
||||
rebuildEditorState() {
|
||||
const editorView = this.editorView;
|
||||
if (editorView && this.currentPage) {
|
||||
@@ -438,13 +430,16 @@ export class Editor {
|
||||
markdownSyscalls(buildMarkdown(this.mdExtensions))
|
||||
);
|
||||
|
||||
this.saveState();
|
||||
|
||||
editorView.setState(
|
||||
this.createEditorState(this.currentPage, editorView.state.sliceDoc())
|
||||
);
|
||||
if (editorView.contentDOM) {
|
||||
editorView.contentDOM.spellcheck = true;
|
||||
}
|
||||
editorView.focus();
|
||||
|
||||
this.restoreState(this.currentPage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,12 +484,7 @@ export class Editor {
|
||||
|
||||
// Persist current page state and nicely close page
|
||||
if (this.currentPage) {
|
||||
let pageState = this.openPages.get(this.currentPage);
|
||||
if (pageState) {
|
||||
pageState.selection = this.editorView!.state.selection;
|
||||
pageState.scrollTop = this.editorView!.scrollDOM.scrollTop;
|
||||
// console.log("Saved pageState", this.currentPage, pageState);
|
||||
}
|
||||
this.saveState();
|
||||
this.space.unwatchPage(this.currentPage);
|
||||
await this.save(true);
|
||||
}
|
||||
@@ -513,26 +503,11 @@ export class Editor {
|
||||
}
|
||||
|
||||
let editorState = this.createEditorState(pageName, doc.text);
|
||||
let pageState = this.openPages.get(pageName);
|
||||
editorView.setState(editorState);
|
||||
if (editorView.contentDOM) {
|
||||
editorView.contentDOM.spellcheck = true;
|
||||
}
|
||||
if (!pageState) {
|
||||
pageState = new PageState(0, editorState.selection);
|
||||
this.openPages.set(pageName, pageState!);
|
||||
editorView.dispatch({
|
||||
selection: { anchor: 0 },
|
||||
});
|
||||
} else {
|
||||
// Restore state
|
||||
// console.log("Restoring selection state", pageState);
|
||||
editorView.dispatch({
|
||||
selection: pageState.selection,
|
||||
});
|
||||
editorView.scrollDOM.scrollTop = pageState!.scrollTop;
|
||||
}
|
||||
|
||||
this.restoreState(pageName);
|
||||
this.space.watchPage(pageName);
|
||||
|
||||
this.viewDispatch({
|
||||
@@ -543,6 +518,30 @@ export class Editor {
|
||||
await this.eventHook.dispatchEvent("editor:pageSwitched");
|
||||
}
|
||||
|
||||
private restoreState(pageName: string) {
|
||||
let pageState = this.openPages.get(pageName);
|
||||
const editorView = this.editorView!;
|
||||
if (pageState) {
|
||||
// Restore state
|
||||
// console.log("Restoring selection state", pageState);
|
||||
editorView.dispatch({
|
||||
selection: pageState.selection,
|
||||
});
|
||||
editorView.scrollDOM.scrollTop = pageState!.scrollTop;
|
||||
}
|
||||
editorView.focus();
|
||||
}
|
||||
|
||||
private saveState() {
|
||||
this.openPages.set(
|
||||
this.currentPage!,
|
||||
new PageState(
|
||||
this.editorView!.scrollDOM.scrollTop,
|
||||
this.editorView!.state.selection
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
ViewComponent(): React.ReactElement {
|
||||
const [viewState, dispatch] = useReducer(reducer, initialViewState);
|
||||
this.viewState = viewState;
|
||||
@@ -625,6 +624,11 @@ export class Editor {
|
||||
<Panel html={viewState.rhsHTML} flex={viewState.showRHS} />
|
||||
)}
|
||||
</div>
|
||||
{!!viewState.showBHS && (
|
||||
<div id="bhs">
|
||||
<Panel html={viewState.bhsHTML} flex={1} />
|
||||
</div>
|
||||
)}
|
||||
<StatusBar editorView={editor.editorView} />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -102,6 +102,18 @@ export default function reducer(
|
||||
showLHS: 0,
|
||||
lhsHTML: "",
|
||||
};
|
||||
case "show-bhs":
|
||||
return {
|
||||
...state,
|
||||
showBHS: action.flex,
|
||||
bhsHTML: action.html,
|
||||
};
|
||||
case "hide-bhs":
|
||||
return {
|
||||
...state,
|
||||
showBHS: 0,
|
||||
bhsHTML: "",
|
||||
};
|
||||
case "show-filterbox":
|
||||
return {
|
||||
...state,
|
||||
|
||||
@@ -110,13 +110,26 @@ body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#bottom {
|
||||
#bhs {
|
||||
height: 200px;
|
||||
width: 100%;
|
||||
|
||||
.panel {
|
||||
iframe {
|
||||
border: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#status-bar {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding: 0 10px;
|
||||
text-align: right;
|
||||
background-color: rgb(213, 213, 213);
|
||||
border-top: rgb(193, 193, 193) 1px solid;
|
||||
.inner {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +92,18 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
|
||||
type: "hide-lhs",
|
||||
});
|
||||
},
|
||||
"editor.showBhs": (ctx, html: string, flex: number) => {
|
||||
editor.viewDispatch({
|
||||
type: "show-bhs",
|
||||
flex,
|
||||
html,
|
||||
});
|
||||
},
|
||||
"editor.hideBhs": (ctx) => {
|
||||
editor.viewDispatch({
|
||||
type: "hide-bhs",
|
||||
});
|
||||
},
|
||||
"editor.insertAtPos": (ctx, text: string, pos: number) => {
|
||||
editor.editorView!.dispatch({
|
||||
changes: {
|
||||
|
||||
@@ -4,8 +4,8 @@ import { PageMeta } from "@silverbulletmd/common/types";
|
||||
|
||||
export function spaceSyscalls(editor: Editor): SysCallMapping {
|
||||
return {
|
||||
"space.listPages": async (): Promise<PageMeta[]> => {
|
||||
return [...(await editor.space.listPages())];
|
||||
"space.listPages": async (ctx, unfiltered = false): Promise<PageMeta[]> => {
|
||||
return [...(await editor.space.listPages(unfiltered))];
|
||||
},
|
||||
"space.readPage": async (
|
||||
ctx,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { SysCallMapping } from "@plugos/plugos/system";
|
||||
import { Space } from "@silverbulletmd/common/spaces/space";
|
||||
import type { Editor } from "../editor";
|
||||
|
||||
export function systemSyscalls(space: Space): SysCallMapping {
|
||||
export function systemSyscalls(editor: Editor): SysCallMapping {
|
||||
return {
|
||||
"system.invokeFunction": async (
|
||||
ctx,
|
||||
@@ -17,7 +17,10 @@ export function systemSyscalls(space: Space): SysCallMapping {
|
||||
return ctx.plug.invoke(name, args);
|
||||
}
|
||||
|
||||
return space.invokeFunction(ctx.plug, env, name, args);
|
||||
return editor.space.invokeFunction(ctx.plug, env, name, args);
|
||||
},
|
||||
"system.reloadPlugs": async () => {
|
||||
return editor.reloadPlugs();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,8 +16,10 @@ export type AppViewState = {
|
||||
unsavedChanges: boolean;
|
||||
showLHS: number; // 0 = hide, > 0 = flex
|
||||
showRHS: number; // 0 = hide, > 0 = flex
|
||||
showBHS: number;
|
||||
rhsHTML: string;
|
||||
lhsHTML: string;
|
||||
bhsHTML: string;
|
||||
allPages: Set<PageMeta>;
|
||||
commands: Map<string, AppCommand>;
|
||||
notifications: Notification[];
|
||||
@@ -36,8 +38,10 @@ export const initialViewState: AppViewState = {
|
||||
unsavedChanges: false,
|
||||
showLHS: 0,
|
||||
showRHS: 0,
|
||||
showBHS: 0,
|
||||
rhsHTML: "",
|
||||
lhsHTML: "",
|
||||
bhsHTML: "",
|
||||
allPages: new Set(),
|
||||
commands: new Map(),
|
||||
notifications: [],
|
||||
@@ -65,6 +69,8 @@ export type Action =
|
||||
| { type: "hide-rhs" }
|
||||
| { type: "show-lhs"; html: string; flex: number }
|
||||
| { type: "hide-lhs" }
|
||||
| { type: "show-bhs"; html: string; flex: number }
|
||||
| { type: "hide-bhs" }
|
||||
| {
|
||||
type: "show-filterbox";
|
||||
options: FilterOption[];
|
||||
|
||||
Reference in New Issue
Block a user