Update to be compatible with new SecureFile version

This commit is contained in:
Fabian Stamm 2024-06-22 20:37:15 +02:00
parent 944e3d2f11
commit bca3049c27
13 changed files with 3890 additions and 6528 deletions

6272
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -13,26 +13,33 @@
"last 2 Chrome versions"
],
"dependencies": {
"@hibas123/secure-file-wrapper": "^2.5.1",
"@hibas123/theme": "^1.0.5",
"@hibas123/utils": "^2.2.17",
"@codemirror/commands": "^6.6.0",
"@codemirror/lang-markdown": "^6.2.5",
"@hibas123/secure-file-wrapper": "^2.5.3",
"@hibas123/theme": "^2.0.7",
"@hibas123/utils": "^2.2.18",
"aes-js": "^3.1.2",
"codemirror": "^5.58.3",
"feather-icons": "^4.28.0",
"idb": "^5.0.7",
"js-sha256": "^0.9.0",
"codemirror": "^6.0.1",
"easymde": "^2.18.0",
"feather-icons": "^4.29.2",
"idb": "^5.0.8",
"js-sha256": "^0.11.0",
"lodash": "^4.17.21",
"lodash.clonedeep": "^4.5.0",
"parcel": "^1.12.4",
"preact": "^10.5.7",
"preact-feather": "^4.1.0",
"secure-file-wrapper": "git+https://git.stamm.me/OpenServer/OSSecureFileWrapper.git",
"uuid": "^8.3.1"
"parcel": "^2.12.0",
"preact": "^10.22.0",
"preact-feather": "^4.2.1",
"uuid": "^10.0.0"
},
"devDependencies": {
"@types/codemirror": "0.0.99",
"@types/lodash.clonedeep": "^4.5.6",
"@types/uuid": "^8.3.0",
"sass": "^1.29.0",
"typescript": "^4.1.2"
"@parcel/packager-raw-url": "2.12.0",
"@parcel/transformer-sass": "^2.12.0",
"@parcel/transformer-webmanifest": "^2.12.0",
"@types/codemirror": "5.60.15",
"@types/lodash.clonedeep": "^4.5.9",
"@types/uuid": "^10.0.0",
"process": "^0.11.10",
"sass": "^1.77.6",
"typescript": "^5.5.2"
}
}
}

3701
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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>;
}

View File

@ -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>
);
}

View 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>
}

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -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);
}
);
});
}
}

View File

@ -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;
}

View File

@ -1,23 +1,15 @@
{
"compilerOptions": {
"outDir": "./public",
"target": "es6",
"module": "commonjs",
"noImplicitAny": false,
"removeComments": true,
"sourceMap": true,
"jsx": "react",
"jsxFactory": "h",
"lib": [
"es2015",
"dom",
"esnext"
],
"resolveJsonModule": true
},
"include": [
"./src/types.d.ts",
"./src/**/*.tsx",
"./src/**/*.ts"
]
}
"compilerOptions": {
"outDir": "./public",
"target": "ES2022",
"module": "commonjs",
"noImplicitAny": false,
"removeComments": true,
"sourceMap": true,
"jsx": "react",
"jsxFactory": "h",
"lib": ["es2015", "dom", "esnext"],
"resolveJsonModule": true
},
"include": ["./src/types.d.ts", "./src/**/*.tsx", "./src/**/*.ts"]
}

View File

@ -1,76 +0,0 @@
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const Visualizer = require('webpack-visualizer-plugin');
const path = require("path");
const fs = require("fs");
const config = require("./config.json");
const url = require("url");
module.exports = {
devServer: {
host: "0.0.0.0", // Defaults to `localhost`
open: false, // Open the page in browser,
contentBase: path.join(__dirname, 'dist'),
disableHostCheck: true,
headers: {
"Access-Control-Allow-Origin": "*"
},
watchOptions: {
aggregateTimeout: 300,
poll: 500
},
public: url.parse(config.callback_url).hostname
},
plugins: [
new CopyWebpackPlugin([{
from: "public"
}]),
new HtmlWebpackPlugin({
title: 'SecureNotes',
template: "./src/index.html"
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
}),
new BundleAnalyzerPlugin({
analyzerMode: "static",
openAnalyzer: false
}),
new Visualizer(),
],
entry: {
main: "./src/index.tsx"
},
// Enable sourcemaps for debugging webpack's output.
devtool: "eval",
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js", ".mjs"]
},
module: {
rules: [{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}, {
test: /\.(png|jpg)$/,
loader: "file-loader",
}, {
test: /\.(scss|css)$/,
use: [
"style-loader", // creates style nodes from JS strings
MiniCssExtractPlugin.loader,
"css-loader", // translates CSS into CommonJS
"sass-loader" // compiles Sass to CSS, using Node Sass by default
]
},
{
test: /\.svg$/,
use: ['preact-svg-loader'],
}
]
}
};