133 lines
3.9 KiB
TypeScript
Executable File
133 lines
3.9 KiB
TypeScript
Executable File
import { h, Component } from "preact";
|
|
import { IVault, ViewNote } from "../../../notes";
|
|
import { Trash2 as Trash, X, Save } from "preact-feather";
|
|
|
|
import Navigation from "../../../navigation";
|
|
import { YesNoModal } from "../../modals/YesNoModal";
|
|
import Notifications, { MessageType } from "../../../notifications";
|
|
import CodeMirror from "../../CodeMirror";
|
|
import { useEffect, useMemo, useState } from "preact/hooks";
|
|
import { usePromise } from "../../../hooks";
|
|
|
|
interface IEntryProps {
|
|
vault: IVault;
|
|
id?: string;
|
|
note?: string;
|
|
}
|
|
|
|
export default function Entry(props: IEntryProps) {
|
|
const [changed, setChanged] = useState(false);
|
|
|
|
const [text, setText] = useState("");
|
|
const title = useMemo(() => text?.split("\n", 1)[0], [text]);
|
|
|
|
const [loading, error, note] = usePromise(async () => {
|
|
let note: ViewNote;
|
|
if (props.id) {
|
|
note = await props.vault.getNote(props.id);
|
|
} else {
|
|
note = props.vault.newNote();
|
|
if (props.note) {
|
|
note.__value = props.note;
|
|
setChanged(true);
|
|
}
|
|
}
|
|
|
|
if (!note) {
|
|
Notifications.sendNotification("Note not found!", MessageType.ERROR);
|
|
history.back();
|
|
} else {
|
|
setText(note.__value);
|
|
}
|
|
|
|
return note;
|
|
}, [props.vault, props.id]);
|
|
|
|
if (loading) {
|
|
return <div>Loading entry</div>;
|
|
} else {
|
|
const save = async () => {
|
|
try {
|
|
if (changed) {
|
|
note.__value = text;
|
|
await props.vault.saveNote(note);
|
|
setChanged(false);
|
|
}
|
|
} catch (err) {
|
|
Notifications.sendError(err);
|
|
}
|
|
};
|
|
|
|
const del = async () => {
|
|
await props.vault.deleteNote(props.id);
|
|
history.back();
|
|
};
|
|
|
|
const close = async () => {
|
|
if (changed) {
|
|
let modal = new YesNoModal("Really want to quit?");
|
|
let res = await modal.getResult();
|
|
if (!res) return;
|
|
}
|
|
history.back();
|
|
};
|
|
|
|
// TODO: Add warning on possibly unwanted exit
|
|
useEffect(() => {
|
|
const keyevent = (evt: KeyboardEvent) => {
|
|
if (evt.key === "s" && evt.ctrlKey) {
|
|
evt.preventDefault();
|
|
save();
|
|
return false;
|
|
} else if (evt.key === "Escape") {
|
|
evt.preventDefault();
|
|
close();
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
document.addEventListener("keydown", keyevent);
|
|
return () => {
|
|
document.removeEventListener("keydown", keyevent);
|
|
};
|
|
});
|
|
|
|
return (
|
|
<div>
|
|
<header class="header" style="margin-bottom: 0;">
|
|
<a class="header-icon-button" onClick={close}>
|
|
<X height={undefined} width={undefined} />
|
|
</a>
|
|
{changed && (
|
|
<a
|
|
class="header-icon-button"
|
|
style="margin-left: 0.5em;"
|
|
onClick={save}
|
|
>
|
|
<Save height={undefined} width={undefined} />
|
|
</a>
|
|
)}
|
|
<h3 style="display:inline" class="button header-title">
|
|
{title}
|
|
</h3>
|
|
<a class="header-icon-button" onClick={del}>
|
|
<Trash height={undefined} width={undefined} />
|
|
</a>
|
|
</header>
|
|
<div class="container" style="padding: 0">
|
|
<CodeMirror
|
|
value={text}
|
|
onChange={(value) => {
|
|
setChanged(true);
|
|
setText(value);
|
|
}}
|
|
// onSave={save}
|
|
// onClose={close}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
}
|