1
0

Notes -> Nuggets

This commit is contained in:
Zef Hemel 2022-02-25 11:27:58 +01:00
parent 29cbb74508
commit 0527430626
29 changed files with 157 additions and 202 deletions

6
.gitignore vendored
View File

@ -1,5 +1 @@
/webapp/node_modules/ nuggets
/webapp/dist/
/.parcel-cache/
/.idea
/notes

View File

@ -1,5 +0,0 @@
## Lots of
Content #here
@zef.hemel

View File

@ -1 +0,0 @@
Sup yo

View File

@ -1,2 +0,0 @@
Yo!!

View File

@ -1 +0,0 @@
I know he is! **Bold**

View File

@ -1,6 +0,0 @@
Home page
[[Great Parenting]]
[[1:1s]]
Sup

View File

@ -1,3 +0,0 @@
# Sappie
Sup

View File

@ -1,5 +0,0 @@
# Hello
## Second level header
bla

View File

@ -3,3 +3,5 @@ build: *
mkdir -p dist mkdir -p dist
$(DENO_BUNDLE) core/core.plugin.json dist/core.plugin.json $(DENO_BUNDLE) core/core.plugin.json dist/core.plugin.json
entr:
ls core/* | entr make

View File

@ -1,26 +1,9 @@
import { parse } from "https://deno.land/std@0.121.0/flags/mod.ts"; import { parse } from "https://deno.land/std@0.121.0/flags/mod.ts";
// import { mime } from "https://deno.land/x/mimetypes@v1.0.0/mod.ts";
//
// async function dataEncodeUint8Array(path : string, data: Uint8Array): Promise<string> {
// const base64url: string = await new Promise((r) => {
// const reader = new FileReader();
// reader.onload = () => r(reader.result as string);
// reader.readAsDataURL(new Blob([data]))
// })
// let [meta, content] = base64url.split(';');
// let [prefix, mimeType] = meta.split(':');
// return `data:${mime.getType(path)};${content}`;
// }
import * as path from "https://deno.land/std@0.121.0/path/mod.ts"; import * as path from "https://deno.land/std@0.121.0/path/mod.ts";
import { Manifest, FunctionDef } from "../webapp/src/plugins/types.ts"; import { Manifest, FunctionDef } from "../webapp/src/plugins/types.ts";
async function compile( async function compile(filePath: string, sourceMaps: boolean): Promise<string> {
filePath: string,
prettyFunctionName: string,
jsFunctionName: string,
sourceMaps: boolean
): Promise<string> {
// @ts-ignore for Deno.emit (unstable API) // @ts-ignore for Deno.emit (unstable API)
let { files, diagnostics } = await Deno.emit(filePath, { let { files, diagnostics } = await Deno.emit(filePath, {
bundle: "classic", bundle: "classic",
@ -47,18 +30,7 @@ async function compile(
} }
throw new Error("Diagnostics"); throw new Error("Diagnostics");
} }
return `const mod = ${bundleSource} return bundleSource;
self.addEventListener('invoke-function', async e => {
try {
let result = await mod['${jsFunctionName}'](...e.detail.args);
self.dispatchEvent(new CustomEvent('result', {detail: result}));
} catch(e) {
console.error(\`Error while running ${jsFunctionName}\`, e);
self.dispatchEvent(new CustomEvent('app-error', {detail: e.message}));
}
});
`;
} }
async function bundle( async function bundle(
@ -73,23 +45,19 @@ async function bundle(
for (let [name, def] of Object.entries(manifest.functions) as Array< for (let [name, def] of Object.entries(manifest.functions) as Array<
[string, FunctionDef] [string, FunctionDef]
>) { >) {
let jsFunctionName, let jsFunctionName = def.functionName,
filePath = path.join(rootPath, def.path); filePath = path.join(rootPath, def.path);
if (filePath.indexOf(":") !== 0) { if (filePath.indexOf(":") !== -1) {
[filePath, jsFunctionName] = filePath.split(":"); [filePath, jsFunctionName] = filePath.split(":");
} else { } else if (!jsFunctionName) {
jsFunctionName = "default"; jsFunctionName = "default";
} }
def.code = await compile(filePath, name, jsFunctionName, sourceMaps); def.code = await compile(filePath, sourceMaps);
def.path = filePath;
def.functionName = jsFunctionName;
} }
return manifest; return manifest;
// let files: { [key: string]: string } = {};
// for await (const entry of walk(path, {includeDirs: false})) {
// let content = await Deno.readFile(entry.path);
// files[entry.path.substring(path.length + 1)] = await dataEncodeUint8Array(entry.path, content);
// }
// return files;
} }
let commandLineArguments = parse(Deno.args, { let commandLineArguments = parse(Deno.args, {
@ -103,13 +71,3 @@ await Deno.writeFile(
outputPath, outputPath,
new TextEncoder().encode(JSON.stringify(b, null, 2)) new TextEncoder().encode(JSON.stringify(b, null, 2))
); );
/*
const watcher = Deno.watchFs("test_app");
for await (const event of watcher) {
console.log("Updating bundle...");
let b = await bundle("test_app/test.cartridge.json");
await Deno.writeFile("test_app.bundle.json", new TextEncoder().encode(JSON.stringify(b, null, 2)));
}
*/

View File

@ -10,8 +10,7 @@
"invoke": "link_navigate", "invoke": "link_navigate",
"key": "Ctrl-Enter", "key": "Ctrl-Enter",
"mac": "Cmd-Enter", "mac": "Cmd-Enter",
"requiredContext": { "requiredContext": {}
}
}, },
"Insert Current Date": { "Insert Current Date": {
"invoke": "insert_nice_date" "invoke": "insert_nice_date"

View File

@ -1,3 +1,3 @@
#!/bin/bash #!/bin/bash
deno run --allow-net --allow-read --allow-write server.ts ls | entr -s 'deno run --allow-net --allow-read --allow-write server.ts'

View File

@ -7,14 +7,14 @@ import { readAll } from "https://deno.land/std@0.126.0/streams/mod.ts";
import { exists } from "https://deno.land/std@0.126.0/fs/mod.ts"; import { exists } from "https://deno.land/std@0.126.0/fs/mod.ts";
const fsPrefix = "/fs"; const fsPrefix = "/fs";
const notesPath = "../notes"; const nuggetsPath = "../nuggets";
const fsRouter = new Router(); const fsRouter = new Router();
fsRouter.use(oakCors()); fsRouter.use(oakCors());
fsRouter.get("/", async (context) => { fsRouter.get("/", async (context) => {
const localPath = notesPath; const localPath = nuggetsPath;
let fileNames: string[] = []; let fileNames: string[] = [];
for await (const dirEntry of Deno.readDir(localPath)) { for await (const dirEntry of Deno.readDir(localPath)) {
if (dirEntry.isFile) { if (dirEntry.isFile) {
@ -29,9 +29,9 @@ fsRouter.get("/", async (context) => {
context.response.body = JSON.stringify(fileNames); context.response.body = JSON.stringify(fileNames);
}); });
fsRouter.get("/:note", async (context) => { fsRouter.get("/:nugget", async (context) => {
const noteName = context.params.note; const nuggetName = context.params.nugget;
const localPath = `${notesPath}/${noteName}.md`; const localPath = `${nuggetsPath}/${nuggetName}.md`;
try { try {
const text = await Deno.readTextFile(localPath); const text = await Deno.readTextFile(localPath);
context.response.body = text; context.response.body = text;
@ -41,8 +41,8 @@ fsRouter.get("/:note", async (context) => {
} }
}); });
fsRouter.options("/:note", async (context) => { fsRouter.options("/:nugget", async (context) => {
const localPath = `${notesPath}/${context.params.note}.md`; const localPath = `${nuggetsPath}/${context.params.nugget}.md`;
try { try {
const stat = await Deno.stat(localPath); const stat = await Deno.stat(localPath);
context.response.headers.set("Content-length", `${stat.size}`); context.response.headers.set("Content-length", `${stat.size}`);
@ -52,10 +52,10 @@ fsRouter.options("/:note", async (context) => {
} }
}); });
fsRouter.put("/:note", async (context) => { fsRouter.put("/:nugget", async (context) => {
const noteName = context.params.note; const nuggetName = context.params.nugget;
const localPath = `${notesPath}/${noteName}.md`; const localPath = `${nuggetsPath}/${nuggetName}.md`;
const existingNote = await exists(localPath); const existingNugget = await exists(localPath);
let file; let file;
try { try {
file = await Deno.create(localPath); file = await Deno.create(localPath);
@ -70,7 +70,7 @@ fsRouter.put("/:note", async (context) => {
file.write(text); file.write(text);
file.close(); file.close();
console.log("Wrote to", localPath); console.log("Wrote to", localPath);
context.response.status = existingNote ? 200 : 201; context.response.status = existingNugget ? 200 : 201;
context.response.body = "OK"; context.response.body = "OK";
}); });

3
webapp/.gitignore vendored
View File

@ -1,2 +1,3 @@
.parcel-cache
dist dist
node_modules node_modules

View File

@ -9,6 +9,7 @@
"scripts": { "scripts": {
"start": "cp src/function_worker.js dist/ && parcel", "start": "cp src/function_worker.js dist/ && parcel",
"build": "parcel build && cp src/function_worker.js dist/", "build": "parcel build && cp src/function_worker.js dist/",
"clean": "rm -rf dist",
"check-watch": "tsc --noEmit --watch" "check-watch": "tsc --noEmit --watch"
}, },
"devDependencies": { "devDependencies": {

View File

@ -1,14 +1,14 @@
export function NavigationBar({ export function NavigationBar({
currentNote, currentNugget,
onClick, onClick,
}: { }: {
currentNote?: string; currentNugget?: string;
onClick: () => void; onClick: () => void;
}) { }) {
return ( return (
<div id="top"> <div id="top">
<div className="current-note" onClick={onClick}> <div className="current-nugget" onClick={onClick}>
» {currentNote} » {currentNugget}
</div> </div>
</div> </div>
); );

View File

@ -1,22 +0,0 @@
import { NoteMeta } from "../types";
import { FilterList } from "./filter";
export function NoteNavigator({
allNotes,
onNavigate,
}: {
allNotes: NoteMeta[];
onNavigate: (note: string | undefined) => void;
}) {
return (
<FilterList
placeholder=""
options={allNotes}
allowNew={true}
newHint="Create note"
onSelect={(opt) => {
onNavigate(opt?.name);
}}
/>
);
}

View File

@ -0,0 +1,22 @@
import { NuggetMeta } from "../types";
import { FilterList } from "./filter";
export function NuggetNavigator({
allNuggets: allNuggets,
onNavigate,
}: {
allNuggets: NuggetMeta[];
onNavigate: (nugget: string | undefined) => void;
}) {
return (
<FilterList
placeholder=""
options={allNuggets}
allowNew={true}
newHint="Create nugget"
onSelect={(opt) => {
onNavigate(opt?.name);
}}
/>
);
}

View File

@ -24,9 +24,9 @@ import ReactDOM from "react-dom";
import coreManifest from "../../plugins/dist/core.plugin.json"; import coreManifest from "../../plugins/dist/core.plugin.json";
import { buildContext } from "./buildContext"; import { buildContext } from "./buildContext";
import * as commands from "./commands"; import * as commands from "./commands";
import { CommandPalette } from "./components/commandpalette"; import { CommandPalette } from "./components/command_palette";
import { NavigationBar } from "./components/navigation_bar"; import { NavigationBar } from "./components/navigation_bar";
import { NoteNavigator } from "./components/notenavigator"; import { NuggetNavigator } from "./components/nugget_navigator";
import { StatusBar } from "./components/status_bar"; import { StatusBar } from "./components/status_bar";
import { FileSystem, HttpFileSystem } from "./fs"; import { FileSystem, HttpFileSystem } from "./fs";
import { lineWrapper } from "./lineWrapper"; import { lineWrapper } from "./lineWrapper";
@ -47,7 +47,7 @@ import {
} from "./types"; } from "./types";
import { safeRun } from "./util"; import { safeRun } from "./util";
class NoteState { class NuggetState {
editorState: EditorState; editorState: EditorState;
scrollTop: number; scrollTop: number;
@ -62,13 +62,13 @@ export class Editor {
viewState: AppViewState; viewState: AppViewState;
viewDispatch: React.Dispatch<Action>; viewDispatch: React.Dispatch<Action>;
$hashChange?: () => void; $hashChange?: () => void;
openNotes: Map<string, NoteState>; openNuggets: Map<string, NuggetState>;
fs: FileSystem; fs: FileSystem;
editorCommands: Map<string, AppCommand>; editorCommands: Map<string, AppCommand>;
constructor(fs: FileSystem, parent: Element) { constructor(fs: FileSystem, parent: Element) {
this.editorCommands = new Map(); this.editorCommands = new Map();
this.openNotes = new Map(); this.openNuggets = new Map();
this.fs = fs; this.fs = fs;
this.viewState = initialViewState; this.viewState = initialViewState;
this.viewDispatch = () => {}; this.viewDispatch = () => {};
@ -81,7 +81,7 @@ export class Editor {
} }
async init() { async init() {
await this.loadNoteList(); await this.loadNuggetList();
await this.loadPlugins(); await this.loadPlugins();
this.$hashChange!(); this.$hashChange!();
this.focus(); this.focus();
@ -111,8 +111,8 @@ export class Editor {
}); });
} }
get currentNote(): string | undefined { get currentNugget(): string | undefined {
return this.viewState.currentNote; return this.viewState.currentNugget;
} }
createEditorState(text: string): EditorState { createEditorState(text: string): EditorState {
@ -146,7 +146,7 @@ export class Editor {
bracketMatching(), bracketMatching(),
closeBrackets(), closeBrackets(),
autocompletion({ autocompletion({
override: [this.noteCompleter.bind(this)], override: [this.nuggetCompleter.bind(this)],
}), }),
EditorView.lineWrapping, EditorView.lineWrapping,
lineWrapper([ lineWrapper([
@ -219,18 +219,18 @@ export class Editor {
}); });
} }
noteCompleter(ctx: CompletionContext): CompletionResult | null { nuggetCompleter(ctx: CompletionContext): CompletionResult | null {
let prefix = ctx.matchBefore(/\[\[\w*/); let prefix = ctx.matchBefore(/\[\[\w*/);
if (!prefix) { if (!prefix) {
return null; return null;
} }
// TODO: Lots of optimization potential here // TODO: Lots of optimization potential here
// TODO: put something in the cm-completionIcon-note style // TODO: put something in the cm-completionIcon-nugget style
return { return {
from: prefix.from + 2, from: prefix.from + 2,
options: this.viewState.allNotes.map((noteMeta) => ({ options: this.viewState.allNuggets.map((nuggetMeta) => ({
label: noteMeta.name, label: nuggetMeta.name,
type: "note", type: "nugget",
})), })),
}; };
} }
@ -238,7 +238,7 @@ export class Editor {
update(value: null, transaction: Transaction): null { update(value: null, transaction: Transaction): null {
if (transaction.docChanged) { if (transaction.docChanged) {
this.viewDispatch({ this.viewDispatch({
type: "note-updated", type: "nugget-updated",
}); });
} }
@ -250,8 +250,8 @@ export class Editor {
let coords = view.posAtCoords(event)!; let coords = view.posAtCoords(event)!;
let node = syntaxTree(view.state).resolveInner(coords); let node = syntaxTree(view.state).resolveInner(coords);
if (node && node.name === "WikiLinkPage") { if (node && node.name === "WikiLinkPage") {
let noteName = view.state.sliceDoc(node.from, node.to); let nuggetName = view.state.sliceDoc(node.from, node.to);
this.navigate(noteName); this.navigate(nuggetName);
} }
if (node && node.name === "TaskMarker") { if (node && node.name === "TaskMarker") {
let checkBoxText = view.state.sliceDoc(node.from, node.to); let checkBoxText = view.state.sliceDoc(node.from, node.to);
@ -272,35 +272,35 @@ export class Editor {
async save() { async save() {
const editorState = this.editorView!.state; const editorState = this.editorView!.state;
if (!this.currentNote) { if (!this.currentNugget) {
return; return;
} }
// Write to file system // Write to file system
const created = await this.fs.writeNote( const created = await this.fs.writeNugget(
this.currentNote, this.currentNugget,
editorState.sliceDoc() editorState.sliceDoc()
); );
// Update in open note cache // Update in open nugget cache
this.openNotes.set( this.openNuggets.set(
this.currentNote, this.currentNugget,
new NoteState(editorState, this.editorView!.scrollDOM.scrollTop) new NuggetState(editorState, this.editorView!.scrollDOM.scrollTop)
); );
// Dispatch update to view // Dispatch update to view
this.viewDispatch({ type: "note-saved" }); this.viewDispatch({ type: "nugget-saved" });
// If a new note was created, let's refresh the note list // If a new nugget was created, let's refresh the nugget list
if (created) { if (created) {
await this.loadNoteList(); await this.loadNuggetList();
} }
} }
async loadNoteList() { async loadNuggetList() {
let notesMeta = await this.fs.listNotes(); let nuggetsMeta = await this.fs.listNuggets();
this.viewDispatch({ this.viewDispatch({
type: "notes-listed", type: "nuggets-listed",
notes: notesMeta, nuggets: nuggetsMeta,
}); });
} }
@ -316,25 +316,25 @@ export class Editor {
Promise.resolve() Promise.resolve()
.then(async () => { .then(async () => {
await this.save(); await this.save();
const noteName = decodeURIComponent(location.hash.substring(1)); const nuggetName = decodeURIComponent(location.hash.substring(1));
console.log("Now navigating to", noteName); console.log("Now navigating to", nuggetName);
if (!this.editorView) { if (!this.editorView) {
return; return;
} }
let noteState = this.openNotes.get(noteName); let nuggetState = this.openNuggets.get(nuggetName);
if (!noteState) { if (!nuggetState) {
let text = await this.fs.readNote(noteName); let text = await this.fs.readNugget(nuggetName);
noteState = new NoteState(this.createEditorState(text), 0); nuggetState = new NuggetState(this.createEditorState(text), 0);
} }
this.openNotes.set(noteName, noteState!); this.openNuggets.set(nuggetName, nuggetState!);
this.editorView!.setState(noteState!.editorState); this.editorView!.setState(nuggetState!.editorState);
this.editorView.scrollDOM.scrollTop = noteState!.scrollTop; this.editorView.scrollDOM.scrollTop = nuggetState!.scrollTop;
this.viewDispatch({ this.viewDispatch({
type: "note-loaded", type: "nugget-loaded",
name: noteName, name: nuggetName,
}); });
}) })
.catch((e) => { .catch((e) => {
@ -378,24 +378,28 @@ export class Editor {
let editor = this; let editor = this;
useEffect(() => {}, []); useEffect(() => {
if (viewState.currentNugget) {
document.title = viewState.currentNugget;
}
}, [viewState.currentNugget]);
return ( return (
<> <>
{viewState.showNoteNavigator && ( {viewState.showNuggetNavigator && (
<NoteNavigator <NuggetNavigator
allNotes={viewState.allNotes} allNuggets={viewState.allNuggets}
onNavigate={(note) => { onNavigate={(nugget) => {
dispatch({ type: "stop-navigate" }); dispatch({ type: "stop-navigate" });
editor!.focus(); editor!.focus();
if (note) { if (nugget) {
editor editor
?.save() ?.save()
.then(() => { .then(() => {
editor!.navigate(note); editor!.navigate(nugget);
}) })
.catch((e) => { .catch((e) => {
alert("Could not save note, not switching"); alert("Could not save nugget, not switching");
}); });
} }
}} }}
@ -417,7 +421,7 @@ export class Editor {
/> />
)} )}
<NavigationBar <NavigationBar
currentNote={viewState.currentNote} currentNugget={viewState.currentNugget}
onClick={() => { onClick={() => {
dispatch({ type: "start-navigate" }); dispatch({ type: "start-navigate" });
}} }}

View File

@ -1,10 +1,10 @@
import { NoteMeta } from "./types"; import { NuggetMeta } from "./types";
export interface FileSystem { export interface FileSystem {
listNotes(): Promise<NoteMeta[]>; listNuggets(): Promise<NuggetMeta[]>;
readNote(name: string): Promise<string>; readNugget(name: string): Promise<string>;
// @return whether a new note was created for this // @return whether a new nugget was created for this
writeNote(name: string, text: string): Promise<boolean>; writeNugget(name: string, text: string): Promise<boolean>;
} }
export class HttpFileSystem implements FileSystem { export class HttpFileSystem implements FileSystem {
@ -12,25 +12,25 @@ export class HttpFileSystem implements FileSystem {
constructor(url: string) { constructor(url: string) {
this.url = url; this.url = url;
} }
async listNotes(): Promise<NoteMeta[]> { async listNuggets(): Promise<NuggetMeta[]> {
let req = await fetch(this.url, { let req = await fetch(this.url, {
method: "GET", method: "GET",
}); });
return (await req.json()).map((name: string) => ({ name })); return (await req.json()).map((name: string) => ({ name }));
} }
async readNote(name: string): Promise<string> { async readNugget(name: string): Promise<string> {
let req = await fetch(`${this.url}/${name}`, { let req = await fetch(`${this.url}/${name}`, {
method: "GET", method: "GET",
}); });
return await req.text(); return await req.text();
} }
async writeNote(name: string, text: string): Promise<boolean> { async writeNugget(name: string, text: string): Promise<boolean> {
let req = await fetch(`${this.url}/${name}`, { let req = await fetch(`${this.url}/${name}`, {
method: "PUT", method: "PUT",
body: text, body: text,
}); });
// 201 (Created) means a new note was created // 201 (Created) means a new nugget was created
return req.status === 201; return req.status === 201;
} }
} }

View File

@ -1,3 +1,5 @@
// Nugget: this file is not built by Parcel, it's simply copied to the distribution
// The reason is that somehow Parcel cannot accept using importScripts otherwise
function safeRun(fn) { function safeRun(fn) {
fn().catch((e) => { fn().catch((e) => {
console.error(e); console.error(e);

View File

@ -2,7 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>Noot</title> <title>Nugget</title>
<link rel="stylesheet" href="styles.css" /> <link rel="stylesheet" href="styles.css" />
<script type="module" src="editor.tsx"></script> <script type="module" src="editor.tsx"></script>
<meta charset="UTF-8" /> <meta charset="UTF-8" />

View File

@ -25,7 +25,6 @@ self.addEventListener("install", (event) => {
console.log("Installing"); console.log("Installing");
// @ts-ignore // @ts-ignore
self.skipWaiting(); self.skipWaiting();
// event.waitUntil(fetchBundle());
}); });
async function handlePut(req: Request, path: string) { async function handlePut(req: Request, path: string) {
@ -36,6 +35,21 @@ async function handlePut(req: Request, path: string) {
return new Response("ok"); return new Response("ok");
} }
function wrapScript(functionName: string, code: string): string {
return `const mod = ${code}
self.addEventListener('invoke-function', async e => {
try {
let result = await mod['${functionName}'](...e.detail.args);
self.dispatchEvent(new CustomEvent('result', {detail: result}));
} catch(e) {
console.error(\`Error while running ${functionName}\`, e);
self.dispatchEvent(new CustomEvent('app-error', {detail: e.message}));
}
});
`;
}
self.addEventListener("fetch", (event: any) => { self.addEventListener("fetch", (event: any) => {
const req = event.request; const req = event.request;
if (req.url.startsWith(rootUrl)) { if (req.url.startsWith(rootUrl)) {
@ -75,7 +89,7 @@ self.addEventListener("fetch", (event: any) => {
status: 404, status: 404,
}); });
} }
return new Response(func.code, { return new Response(wrapScript(func.functionName!, func.code!), {
status: 200, status: 200,
headers: { headers: {
"Content-type": "application/javascript", "Content-type": "application/javascript",

View File

@ -23,5 +23,6 @@ export interface CommandDef {
export interface FunctionDef { export interface FunctionDef {
path: string; path: string;
functionName?: string;
code?: string; code?: string;
} }

View File

@ -6,18 +6,18 @@ export default function reducer(
): AppViewState { ): AppViewState {
console.log("Got action", action); console.log("Got action", action);
switch (action.type) { switch (action.type) {
case "note-loaded": case "nugget-loaded":
return { return {
...state, ...state,
currentNote: action.name, currentNugget: action.name,
isSaved: true, isSaved: true,
}; };
case "note-saved": case "nugget-saved":
return { return {
...state, ...state,
isSaved: true, isSaved: true,
}; };
case "note-updated": case "nugget-updated":
// Minor rerender optimization, this is triggered a lot // Minor rerender optimization, this is triggered a lot
if (!state.isSaved) { if (!state.isSaved) {
return state; return state;
@ -29,17 +29,17 @@ export default function reducer(
case "start-navigate": case "start-navigate":
return { return {
...state, ...state,
showNoteNavigator: true, showNuggetNavigator: true,
}; };
case "stop-navigate": case "stop-navigate":
return { return {
...state, ...state,
showNoteNavigator: false, showNuggetNavigator: false,
}; };
case "notes-listed": case "nuggets-listed":
return { return {
...state, ...state,
allNotes: action.notes, allNuggets: action.nuggets,
}; };
case "show-palette": case "show-palette":
return { return {

View File

@ -164,7 +164,7 @@ body {
background-color: #ddd; background-color: #ddd;
} }
.current-note { .current-nugget {
font-family: var(--editor-font); font-family: var(--editor-font);
margin-left: 10px; margin-left: 10px;
margin-top: 10px; margin-top: 10px;

View File

@ -1,6 +1,6 @@
import { CommandDef } from "./plugins/types"; import { CommandDef } from "./plugins/types";
export type NoteMeta = { export type NuggetMeta = {
name: string; name: string;
}; };
@ -14,27 +14,27 @@ export type AppCommand = {
}; };
export type AppViewState = { export type AppViewState = {
currentNote?: string; currentNugget?: string;
isSaved: boolean; isSaved: boolean;
showNoteNavigator: boolean; showNuggetNavigator: boolean;
showCommandPalette: boolean; showCommandPalette: boolean;
allNotes: NoteMeta[]; allNuggets: NuggetMeta[];
commands: Map<string, AppCommand>; commands: Map<string, AppCommand>;
}; };
export const initialViewState: AppViewState = { export const initialViewState: AppViewState = {
isSaved: false, isSaved: false,
showNoteNavigator: false, showNuggetNavigator: false,
showCommandPalette: false, showCommandPalette: false,
allNotes: [], allNuggets: [],
commands: new Map(), commands: new Map(),
}; };
export type Action = export type Action =
| { type: "note-loaded"; name: string } | { type: "nugget-loaded"; name: string }
| { type: "note-saved" } | { type: "nugget-saved" }
| { type: "note-updated" } | { type: "nugget-updated" }
| { type: "notes-listed"; notes: NoteMeta[] } | { type: "nuggets-listed"; nuggets: NuggetMeta[] }
| { type: "start-navigate" } | { type: "start-navigate" }
| { type: "stop-navigate" } | { type: "stop-navigate" }
| { type: "update-commands"; commands: Map<string, AppCommand> } | { type: "update-commands"; commands: Map<string, AppCommand> }