SecureNotes/src/components/routes/vault/Entry.tsx

131 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;">
<div class="header-icon-button" onClick={close}>
<X height={undefined} width={undefined} />
</div>
{changed && (
<div
class="header-icon-button"
style="margin-left: 0.5em;"
onClick={save}
>
<Save height={undefined} width={undefined} />
</div>
)}
<span>{title}</span>
<div class="header-icon-button" onClick={del}>
<Trash height={undefined} width={undefined} />
</div>
</header>
<div class="container" style="padding: 0">
<CodeMirror
value={text}
onChange={(value) => {
setChanged(true);
setText(value);
}}
// onSave={save}
// onClose={close}
/>
</div>
</div>
);
}
}