Update to be compatible with new SecureFile version
This commit is contained in:
@ -1,9 +1,13 @@
|
||||
import { h } from "preact";
|
||||
import { useEffect, useRef } from "preact/hooks";
|
||||
|
||||
import * as CM from "codemirror";
|
||||
import "codemirror/lib/codemirror.css";
|
||||
import "codemirror/theme/base16-dark.css";
|
||||
import { EditorView, basicSetup, } from "codemirror";
|
||||
import { EditorState, Text } from "@codemirror/state";
|
||||
import { defaultKeymap } from "@codemirror/commands"
|
||||
|
||||
import { markdown } from "@codemirror/lang-markdown"
|
||||
// import "codemirror/lib/codemirror.css";
|
||||
// import "codemirror/theme/base16-dark.css";
|
||||
|
||||
import "./CodeMirror.scss";
|
||||
import Theme from "../theme";
|
||||
@ -18,27 +22,41 @@ interface ICodeMirrorProps {
|
||||
export default function CodeMirror(props: ICodeMirrorProps) {
|
||||
const ref = useRef<HTMLTextAreaElement>();
|
||||
useEffect(() => {
|
||||
const instance = CM.fromTextArea(ref.current, {
|
||||
value: props.value,
|
||||
mode: "markdown",
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
theme: Theme.isDark.value ? "base16-dark" : "default",
|
||||
viewportMargin: Infinity,
|
||||
// extraKeys: {
|
||||
// "Ctrl-S": (cm) => {
|
||||
// const val = cm.getValue();
|
||||
// props?.onSave(val);
|
||||
// },
|
||||
// Esc: props.onClose,
|
||||
// },
|
||||
const instance = new EditorView({
|
||||
parent: ref.current,
|
||||
extensions: [
|
||||
basicSetup,
|
||||
markdown(),
|
||||
|
||||
],
|
||||
})
|
||||
// const instance = CM.(ref.current, {
|
||||
// value: props.value,
|
||||
// mode: "markdown",
|
||||
// lineNumbers: true,
|
||||
// lineWrapping: true,
|
||||
// theme: Theme.isDark.value ? "base16-dark" : "default",
|
||||
// viewportMargin: Infinity,
|
||||
// // extraKeys: {
|
||||
// // "Ctrl-S": (cm) => {
|
||||
// // const val = cm.getValue();
|
||||
// // props?.onSave(val);
|
||||
// // },
|
||||
// // Esc: props.onClose,
|
||||
// // },
|
||||
// });
|
||||
|
||||
const state = EditorState.create({
|
||||
doc: Text.of([props.value ?? ""]),
|
||||
});
|
||||
|
||||
if (props.value) instance.setValue(props.value);
|
||||
instance.setState(state);
|
||||
instance.focus();
|
||||
state.
|
||||
|
||||
instance.on("change", () => props?.onChange(instance.getValue()));
|
||||
instance.on("change", () => props?.onChange(instance.getValue()));
|
||||
|
||||
return () => {};
|
||||
return () => { };
|
||||
}, [ref]);
|
||||
return <textarea ref={ref}></textarea>;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ export class Footer extends Component<
|
||||
<span>
|
||||
Welcome <b>{Notes.name}</b>
|
||||
</span>
|
||||
<span style="color: lightgrey;">v1.6</span>
|
||||
<span style="color: lightgrey;">v1.7</span>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
27
src/components/routes/vault/EasyMde.tsx
Normal file
27
src/components/routes/vault/EasyMde.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import { h } from "preact";
|
||||
|
||||
import * as EasyMDE from "easymde";
|
||||
import "easymde/dist/easymde.min.css"
|
||||
// import "./easymde.scss"
|
||||
import { useEffect, useRef } from "preact/hooks";
|
||||
|
||||
export default function EasyMDEPreact(props: { value: string, onChange: (value: string) => void }) {
|
||||
const ref = useRef<HTMLTextAreaElement>();
|
||||
useEffect(() => {
|
||||
const mde = new EasyMDE({
|
||||
element: ref.current,
|
||||
initialValue: props.value
|
||||
})
|
||||
|
||||
mde.codemirror.on("change", () => {
|
||||
props.onChange(mde.value());
|
||||
});
|
||||
|
||||
return () => {
|
||||
mde.cleanup();
|
||||
}
|
||||
}, [ref])
|
||||
return <div style="background: white;">
|
||||
<textarea ref={ref}></textarea>
|
||||
</div>
|
||||
}
|
@ -2,12 +2,16 @@ import { h, Component } from "preact";
|
||||
import { IVault, ViewNote } from "../../../notes";
|
||||
import { Trash2 as Trash, X, Save } from "preact-feather";
|
||||
|
||||
import Navigation from "../../../navigation";
|
||||
// import Navigation from "../../../navigation";
|
||||
import { YesNoModal } from "../../modals/YesNoModal";
|
||||
import Notifications, { MessageType } from "../../../notifications";
|
||||
import CodeMirror from "../../CodeMirror";
|
||||
// import CodeMirror from "../../CodeMirror";
|
||||
|
||||
|
||||
|
||||
import { useEffect, useMemo, useState } from "preact/hooks";
|
||||
import { usePromise } from "../../../hooks";
|
||||
import EasyMDEPreact from "./EasyMde";
|
||||
|
||||
interface IEntryProps {
|
||||
vault: IVault;
|
||||
@ -114,14 +118,14 @@ export default function Entry(props: IEntryProps) {
|
||||
</div>
|
||||
</header>
|
||||
<div class="container" style="padding: 0">
|
||||
<CodeMirror
|
||||
<EasyMDEPreact
|
||||
value={text}
|
||||
onChange={(value) => {
|
||||
setChanged(true);
|
||||
setText(value);
|
||||
}}
|
||||
// onSave={save}
|
||||
// onClose={close}
|
||||
// onSave={save}
|
||||
// onClose={close}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -32,7 +32,7 @@ export default class VaultsPage extends Page<
|
||||
|
||||
updateVaults(s?: boolean) {
|
||||
if (s) return;
|
||||
return new Promise((yes) => {
|
||||
return new Promise<void>((yes) => {
|
||||
Notes.getVaults().then((vaults) => this.setState({ vaults }, yes));
|
||||
});
|
||||
}
|
||||
@ -245,6 +245,7 @@ export default class VaultsPage extends Page<
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log({ vaults: this.state.vaults })
|
||||
let elms = this.state.vaults.map((vault) => {
|
||||
return (
|
||||
<li
|
||||
|
@ -1,70 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>SecureNotes</title>
|
||||
<meta charset="utf8" />
|
||||
<meta name="Description" content="Notes app" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="manifest" href="./manifest.webmanifest" />
|
||||
<!-- <link rel="shortcut icon" href="/public/icon-72x72.png"> -->
|
||||
|
||||
<!-- Add to home screen for Safari on iOS -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
<meta name="apple-mobile-web-app-title" content="Secure Notes" />
|
||||
<head>
|
||||
<title>SecureNotes</title>
|
||||
<meta charset="utf8" />
|
||||
<meta name="Description" content="Notes app" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="manifest" href="./manifest.webmanifest" />
|
||||
<!-- <link rel="shortcut icon" href="/public/icon-72x72.png"> -->
|
||||
|
||||
<!-- sizes="180x180" -->
|
||||
<!-- href="/public/apple-touch-icon.png" -->
|
||||
<!-- Add to home screen for Safari on iOS -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
<meta name="apple-mobile-web-app-title" content="Secure Notes" />
|
||||
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="256x256"
|
||||
href="/public/notepad256.png"
|
||||
/>
|
||||
<!-- <link
|
||||
<!-- sizes="180x180" -->
|
||||
<!-- href="/public/apple-touch-icon.png" -->
|
||||
|
||||
<link rel="apple-touch-icon" sizes="256x256" href="./public/notepad256.png" />
|
||||
<!-- <link
|
||||
rel="mask-icon"
|
||||
href="/public/safari-pinned-tab.svg"
|
||||
color="#1E88E5"
|
||||
/> -->
|
||||
<meta name="msapplication-TileColor" content="#1E88E5" />
|
||||
<meta name="theme-color" content="#1E88E5" />
|
||||
</head>
|
||||
<meta name="msapplication-TileColor" content="#1E88E5" />
|
||||
<meta name="theme-color" content="#1E88E5" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript> You have to enable JavaScript to use this site! </noscript>
|
||||
<div id="app"></div>
|
||||
<script>
|
||||
if (navigator.serviceWorker.controller) {
|
||||
if (localStorage.getItem("debug")) {
|
||||
console.warn(
|
||||
"Debuggung and service worker found, make shure to clear cache!"
|
||||
);
|
||||
}
|
||||
console.log("active service worker found, no need to register");
|
||||
} else {
|
||||
if (localStorage.getItem("debug")) {
|
||||
console.warn("Disabling Service Worker in debug mode!");
|
||||
} else {
|
||||
// Register the ServiceWorker
|
||||
navigator.serviceWorker
|
||||
.register("serviceworker.js", {
|
||||
scope: "/",
|
||||
})
|
||||
.then(function (reg) {
|
||||
console.log(
|
||||
"Service worker has been registered for scope:" +
|
||||
reg.scope
|
||||
);
|
||||
navigator.serviceWorker.controller.addEventListener(
|
||||
"cleared_cache",
|
||||
(evt) => {
|
||||
console.log(evt);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script src="index.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
<body>
|
||||
<noscript> You have to enable JavaScript to use this site! </noscript>
|
||||
<div id="app"></div>
|
||||
<script>
|
||||
window.debug = {}
|
||||
</script>
|
||||
<script src="index.tsx" type="module"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,42 +1,3 @@
|
||||
declare global {
|
||||
interface Window {
|
||||
requestIdleCallback: (
|
||||
callback: (deadline: {
|
||||
didTimeout: boolean;
|
||||
timeRemaining: () => number;
|
||||
}) => void,
|
||||
options?: { timeout: number }
|
||||
) => number | NodeJS.Timeout;
|
||||
cancelIdleCallback: (id: number | NodeJS.Timeout) => void;
|
||||
debug: any;
|
||||
}
|
||||
|
||||
// namespace JSX {
|
||||
// interface IntrinsicElements {
|
||||
// "wired-button": HTMLAttributes;
|
||||
// "wired-card": HTMLAttributes;
|
||||
// "wired-checkbox": HTMLAttributes;
|
||||
// "wired-combo": HTMLAttributes;
|
||||
// "wired-fab": HTMLAttributes;
|
||||
// "wired-icon-button": HTMLAttributes;
|
||||
// "wired-input": HTMLAttributes;
|
||||
// "wired-item": HTMLAttributes;
|
||||
// "wired-lib": HTMLAttributes;
|
||||
// "wired-listbox": HTMLAttributes;
|
||||
// "wired-progress": HTMLAttributes;
|
||||
// "wired-radio-group": HTMLAttributes;
|
||||
// "wired-radio": HTMLAttributes;
|
||||
// "wired-slider": HTMLAttributes;
|
||||
// "wired-spinner": HTMLAttributes;
|
||||
// "wired-tabs": HTMLAttributes;
|
||||
// "wired-textarea": HTMLAttributes;
|
||||
// "wired-toggle": HTMLAttributes;
|
||||
// "wired-tooltip": HTMLAttributes;
|
||||
|
||||
// }
|
||||
// }
|
||||
}
|
||||
declare const window: Window;
|
||||
|
||||
window.requestIdleCallback =
|
||||
window.requestIdleCallback ||
|
||||
@ -119,7 +80,7 @@ console.log("Dark mode:", Theme.active);
|
||||
}
|
||||
|
||||
Navigation.default = VaultsPage as typeof Page;
|
||||
Navigation.addPage("/vault", VaultPage as typeof Page);
|
||||
Navigation.addPage("/vault", VaultPage as any as typeof Page);
|
||||
Navigation.addPage("/demo", DemoPage as typeof Page);
|
||||
Navigation.addPage("/share", SharePage as typeof Page);
|
||||
Navigation.addPage("/settings", SettingsPage as typeof Page);
|
||||
@ -137,3 +98,35 @@ console.log("Dark mode:", Theme.active);
|
||||
|
||||
render(<App />, document.body, document.getElementById("app"));
|
||||
})();
|
||||
|
||||
|
||||
if (navigator.serviceWorker.controller) {
|
||||
if (localStorage.getItem("debug")) {
|
||||
console.warn(
|
||||
"Debuggung and service worker found, make shure to clear cache!"
|
||||
);
|
||||
}
|
||||
console.log("active service worker found, no need to register");
|
||||
} else {
|
||||
if (localStorage.getItem("debug")) {
|
||||
console.warn("Disabling Service Worker in debug mode!");
|
||||
} else {
|
||||
// Register the ServiceWorker
|
||||
navigator.serviceWorker
|
||||
.register(new URL("serviceworker.js", import.meta.url), {
|
||||
scope: "/",
|
||||
})
|
||||
.then(function (reg) {
|
||||
console.log(
|
||||
"Service worker has been registered for scope:" +
|
||||
reg.scope
|
||||
);
|
||||
navigator.serviceWorker.controller.addEventListener(
|
||||
"cleared_cache",
|
||||
(evt) => {
|
||||
console.log(evt);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
24
src/notes.ts
24
src/notes.ts
@ -8,6 +8,7 @@ import * as config from "../config.json";
|
||||
import * as b64 from "./helper/base64";
|
||||
import IDB from "./helper/indexeddb";
|
||||
import Notifications, { MessageType } from "./notifications";
|
||||
import { cloneDeep } from "lodash";
|
||||
|
||||
export class HttpError extends Error {
|
||||
constructor(public status: number, public statusText: string) {
|
||||
@ -37,8 +38,6 @@ export interface ViewNote extends BaseNote {
|
||||
__value: string;
|
||||
}
|
||||
|
||||
import clonedeep = require("lodash.clonedeep");
|
||||
|
||||
const Encoder = new TextEncoder();
|
||||
const Decoder = new TextDecoder();
|
||||
|
||||
@ -129,11 +128,10 @@ class NotesProvider {
|
||||
}
|
||||
|
||||
login() {
|
||||
window.location.href = `${config.auth_server}/auth?client_id=${
|
||||
config.client_id
|
||||
}&scope=${config.permission}&redirect_uri=${encodeURIComponent(
|
||||
config.callback_url
|
||||
)}&response_type=code`;
|
||||
window.location.href = `${config.auth_server}/auth?client_id=${config.client_id
|
||||
}&scope=${config.permission}&redirect_uri=${encodeURIComponent(
|
||||
config.callback_url
|
||||
)}&response_type=code`;
|
||||
}
|
||||
|
||||
async getToken(code: string) {
|
||||
@ -193,8 +191,8 @@ class NotesProvider {
|
||||
console.log("Getting JWT");
|
||||
let req = await fetch(
|
||||
config.auth_server +
|
||||
"/api/oauth/jwt?refreshtoken=" +
|
||||
localStorage.getItem("refreshtoken")
|
||||
"/api/oauth/jwt?refreshtoken=" +
|
||||
localStorage.getItem("refreshtoken")
|
||||
);
|
||||
if (req.status !== 200) {
|
||||
Notifications.sendNotification("offline", MessageType.INFO);
|
||||
@ -356,7 +354,7 @@ class NotesProvider {
|
||||
let value = await this._secureFile.get(id);
|
||||
let note: DBNote = {
|
||||
_id: remote._id,
|
||||
folder: remote.folder,
|
||||
folder: remote.active.folder,
|
||||
preview: b64.decode(remote.active.preview || ""),
|
||||
time: remote.active.time,
|
||||
__value: new Uint8Array(value),
|
||||
@ -578,7 +576,7 @@ class NotesProvider {
|
||||
.filter((e) => e.folder === this.vault._id)
|
||||
.sort(this.sort)
|
||||
.map<BaseNote>((e) => {
|
||||
let new_note = clonedeep(<Note>e) as BaseNote;
|
||||
let new_note = cloneDeep(<Note>e) as BaseNote;
|
||||
delete (<any>new_note).__value;
|
||||
new_note.preview = this.decrypt(e.preview);
|
||||
return new_note;
|
||||
@ -610,7 +608,7 @@ class NotesProvider {
|
||||
const tx = Notes.database.transaction(Notes.noteDB, Notes.oplogDB);
|
||||
let old_note = await Notes.noteDB.get(note._id, tx);
|
||||
|
||||
let new_note = clonedeep(<Note>note) as DBNote;
|
||||
let new_note = cloneDeep(<Note>note) as DBNote;
|
||||
new_note.__value = this.encrypt(note.__value);
|
||||
let [title, preview] = note.__value.split("\n");
|
||||
if (preview) preview = "\n" + preview;
|
||||
@ -637,7 +635,7 @@ class NotesProvider {
|
||||
async getNote(id: string): Promise<ViewNote> {
|
||||
let note = await Notes.noteDB.get(id);
|
||||
if (!note) return undefined;
|
||||
let new_note = clonedeep(<Note>note) as ViewNote;
|
||||
let new_note = cloneDeep(<Note>note) as ViewNote;
|
||||
new_note.__value = this.decrypt(note.__value);
|
||||
return new_note;
|
||||
}
|
||||
|
Reference in New Issue
Block a user