From 31d9f99b77cd9387c1f266819e31671b723344f0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 3 Jun 2019 16:51:11 +0200 Subject: [PATCH] Making Share Target functional --- package-lock.json | 32 +++++++------ package.json | 8 +++- public/manifest.json | 3 +- public/serviceworker.js | 12 +++++ src/components/Footer.tsx | 2 +- src/components/notifications.tsx | 5 +- src/components/routes/404/index.tsx | 5 ++ src/components/routes/share/Share.tsx | 6 ++- src/components/routes/vault/EntryList.tsx | 25 +++++++--- src/components/routes/vaults/Vaults.tsx | 2 +- src/index.tsx | 57 +++++++++++++---------- src/navigation.ts | 9 ++-- webpack.config.js | 36 ++++---------- 13 files changed, 114 insertions(+), 88 deletions(-) create mode 100644 src/components/routes/404/index.tsx diff --git a/package-lock.json b/package-lock.json index 6590360..007b7aa 100755 --- a/package-lock.json +++ b/package-lock.json @@ -148,6 +148,12 @@ "@types/node": "*" } }, + "@types/workbox-sw": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/workbox-sw/-/workbox-sw-4.2.0.tgz", + "integrity": "sha512-eKk2yrlCuLNmBInQ08FqIcRlMT1ghIo2P7wZW/jAQw0l9ozPYrebcqxnsg2NN+TGRVcMEYGfP05AxmIaxQIArg==", + "dev": true + }, "@webassemblyjs/ast": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", @@ -3231,9 +3237,9 @@ } }, "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -7029,13 +7035,13 @@ "dev": true }, "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", "dev": true, "requires": { "block-stream": "*", - "fstream": "^1.0.2", + "fstream": "^1.0.12", "inherits": "2" } }, @@ -7964,9 +7970,9 @@ } }, "webpack-dev-server": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.5.0.tgz", - "integrity": "sha512-Gr4tBz+BRliDy1Jh9YJBOuwf13CipVxf4PCH7alB/rV/heszJ/U8M7KYekzlQn8XvoGgyozw7Uef2GDFd0ZLvg==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.5.1.tgz", + "integrity": "sha512-0IdMGddJcnK9zesZOeHWl4uAOVfypn7DSrdNWtclROkVBXy/TcBN+6eEG1wNfLT9dXVfaRZZsLTJt0mJtgTQgw==", "dev": true, "requires": { "ansi-html": "0.0.7", @@ -8593,8 +8599,7 @@ "workbox-core": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-4.3.1.tgz", - "integrity": "sha512-I3C9jlLmMKPxAC1t0ExCq+QoAMd0vAAHULEgRZ7kieCdUd919n53WC0AfvokHNwqRhGn+tIIj7vcb5duCjs2Kg==", - "dev": true + "integrity": "sha512-I3C9jlLmMKPxAC1t0ExCq+QoAMd0vAAHULEgRZ7kieCdUd919n53WC0AfvokHNwqRhGn+tIIj7vcb5duCjs2Kg==" }, "workbox-expiration": { "version": "4.3.1", @@ -8630,7 +8635,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-4.3.1.tgz", "integrity": "sha512-piSg/2csPoIi/vPpp48t1q5JLYjMkmg5gsXBQkh/QYapCdVwwmKlU9mHdmy52KsDGIjVaqEUMFvEzn2LRaigqQ==", - "dev": true, "requires": { "workbox-core": "^4.3.1" } @@ -8648,7 +8652,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-4.3.1.tgz", "integrity": "sha512-FkbtrODA4Imsi0p7TW9u9MXuQ5P4pVs1sWHK4dJMMChVROsbEltuE79fBoIk/BCztvOJ7yUpErMKa4z3uQLX+g==", - "dev": true, "requires": { "workbox-core": "^4.3.1" } @@ -8657,7 +8660,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-4.3.1.tgz", "integrity": "sha512-F/+E57BmVG8dX6dCCopBlkDvvhg/zj6VDs0PigYwSN23L8hseSRwljrceU2WzTvk/+BSYICsWmRq5qHS2UYzhw==", - "dev": true, "requires": { "workbox-core": "^4.3.1" } diff --git a/package.json b/package.json index f1ef740..b9911ed 100755 --- a/package.json +++ b/package.json @@ -23,12 +23,16 @@ "lodash.clonedeep": "^4.5.0", "secure-file-wrapper": "git+https://git.stamm.me/OpenServer/OSSecureFileWrapper.git", "uikit": "^3.1.5", - "uuid": "^3.3.2" + "uuid": "^3.3.2", + "workbox-precaching": "^4.3.1", + "workbox-routing": "^4.3.1", + "workbox-strategies": "^4.3.1" }, "devDependencies": { "@types/lodash.clonedeep": "^4.5.6", "@types/uikit": "^2.27.7", "@types/uuid": "^3.4.4", + "@types/workbox-sw": "^4.2.0", "copy-webpack-plugin": "^5.0.3", "css-loader": "^2.1.1", "file-loader": "^3.0.1", @@ -44,7 +48,7 @@ "webpack": "^4.32.2", "webpack-bundle-analyzer": "^3.3.2", "webpack-cli": "^3.3.2", - "webpack-dev-server": "^3.5.0", + "webpack-dev-server": "^3.5.1", "webpack-visualizer-plugin": "^0.1.11", "workbox-webpack-plugin": "^4.3.1", "worker-loader": "^2.0.0" diff --git a/public/manifest.json b/public/manifest.json index e418643..2e0fd38 100755 --- a/public/manifest.json +++ b/public/manifest.json @@ -3,10 +3,9 @@ "name": "Secure Notes", "decription": "A place to store your notes securly", "share_target": { - "url_template": "/#/share?title={title}&text={text}&url={url}", + "action": "/share", "method": "GET", "enctype": "application/x-www-form-urlencoded", - "action": "/", "params": { "title": "title", "text": "text", diff --git a/public/serviceworker.js b/public/serviceworker.js index 8eaf4f9..0301b94 100644 --- a/public/serviceworker.js +++ b/public/serviceworker.js @@ -6,6 +6,7 @@ const CACHE = "offline"; let precacheFiles = [ "/", + "/index.html", "/main.js", "/main.css", "/serviceworker.js" @@ -46,6 +47,7 @@ var Types; Types[Types["CACHE"] = 0] = "CACHE"; Types[Types["NOCACHE"] = 1] = "NOCACHE"; Types[Types["REFRESH"] = 2] = "REFRESH"; + Types[Types["INDEX"] = 3] = "INDEX"; })(Types || (Types = {})); let rules = [{ @@ -53,6 +55,11 @@ let rules = [{ return url.indexOf("/api/") >= 0; }, type: Types.NOCACHE + }, { + match: (url) => { + return url.indexOf("/share") >= 0; + }, + type: Types.INDEX }, { match: () => { @@ -77,6 +84,11 @@ self.addEventListener('fetch', (evt) => { }); case Types.NOCACHE: return fetch(evt.request); + case Types.INDEX: + return refresh(new Request("/")).then(r => { + evt.waitUntil(r.refresh.catch(_ => {})); + return r.result; + }) } })()); }); diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 87a9393..5006aaa 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -65,7 +65,7 @@ export class Footer extends Component<{}, { synced: boolean, syncing: boolean }> Welcome {Notes.name} - v1.1 + v1.2 } diff --git a/src/components/notifications.tsx b/src/components/notifications.tsx index 926718e..763b33e 100644 --- a/src/components/notifications.tsx +++ b/src/components/notifications.tsx @@ -1,5 +1,4 @@ import { h, Component } from "preact"; -import Notes from "../notes"; import "./notifications.scss" import Notifications, { MessageType } from "../notifications"; @@ -37,11 +36,11 @@ export default class NotificationsComponent extends Component<{}, { this.setState({ notifications: n }); setTimeout(() => { this.removeNot(not); - }, 3000); + }, 20000); } removeNot(not: { message: string }) { - let n = this.state.notifications.slice(0).filter(e => e !== not); + let n = this.state.notifications.filter(e => e !== not); this.setState({ notifications: n }); } diff --git a/src/components/routes/404/index.tsx b/src/components/routes/404/index.tsx new file mode 100644 index 0000000..499f288 --- /dev/null +++ b/src/components/routes/404/index.tsx @@ -0,0 +1,5 @@ +import { h } from "preact"; + +export default function Error404Page() { + return

Page not found!

; +} \ No newline at end of file diff --git a/src/components/routes/share/Share.tsx b/src/components/routes/share/Share.tsx index 34c19e5..f777ad3 100644 --- a/src/components/routes/share/Share.tsx +++ b/src/components/routes/share/Share.tsx @@ -6,7 +6,7 @@ import Navigation from "../../../navigation"; export default class SharePage extends Page<{ state: any }, { vault: string }> { text: string; componentWillMount() { - let { title, text, url } = Navigation.getQuery() || {} as any; + let { title, text, url } = this.props.state; let note = ""; if (title) { note += title + "\n" @@ -24,7 +24,9 @@ export default class SharePage extends Page<{ state: any }, { vault: string }> { render() { return { - Navigation.setPage("/vault", { id: vault }, { entry: "true", note: this.text }, true); + Navigation.setPage("/", undefined, undefined, true); + Navigation.setPage("/vault", { id: vault }); + Navigation.setPage("/vault", { id: vault }, { entry: "true", note: this.text }); }} /> } } diff --git a/src/components/routes/vault/EntryList.tsx b/src/components/routes/vault/EntryList.tsx index 129cee6..5df4d94 100755 --- a/src/components/routes/vault/EntryList.tsx +++ b/src/components/routes/vault/EntryList.tsx @@ -74,17 +74,30 @@ export default class EntryList extends Component<{ vault: Promise }, { n } } + const deleteNote = async () => { + Notes.delete(note._id).then(() => { + Notifications.sendSuccess("Deleted") + this.rawNotes = this.rawNotes.filter(e => e._id !== note._id); + this.setState({ notes: this.state.notes.filter(e => e._id !== note._id) }); + }).catch(err => { + Notifications.sendError(err); + }) + + } + let share; if ((window.navigator as any).share) { - share = - let context = - {share} - - - this.setState({ context }); } + + let context = + {share} + + + + this.setState({ context }); return false; } diff --git a/src/components/routes/vaults/Vaults.tsx b/src/components/routes/vaults/Vaults.tsx index 26313f8..7aed7ab 100644 --- a/src/components/routes/vaults/Vaults.tsx +++ b/src/components/routes/vaults/Vaults.tsx @@ -218,7 +218,7 @@ export default class VaultsPage extends Page -

Navigation.setPage("/")}>Your vaults:

+

Navigation.setPage("/")}>{this.props.selectVault ? "Select Vault for share" : "Your vaults:"}

this.addButtonClick()} /> diff --git a/src/index.tsx b/src/index.tsx index 98dcb8d..8348c2e 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -5,32 +5,32 @@ declare global { 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; + // 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; +declare const window: Window; window.requestIdleCallback = window.requestIdleCallback || @@ -77,6 +77,7 @@ import DemoPage from './components/demo'; import VaultPage from './components/routes/vault/Vault'; import SharePage from './components/routes/share/Share'; import Notifications from './notifications'; +import Error404Page from './components/routes/404'; window.debug.notes = Notes; (async () => { @@ -104,6 +105,14 @@ window.debug.notes = Notes; Navigation.addPage("/vault", VaultPage as typeof Page) Navigation.addPage("/demo", DemoPage as typeof Page) Navigation.addPage("/share", SharePage as typeof Page) + Navigation.addPage("/404", Error404Page); + const trad = window.location.pathname; + if (trad && trad !== "/" && trad !== "") { + let p: any = {}; + new URL(window.location.href).searchParams.forEach((val, key) => p[key] = val); + Navigation.setPage(trad, p, undefined, true); + // window.location.href = "/#/" + trad; + } Navigation.start(); render(, document.body, document.getElementById('app')); diff --git a/src/navigation.ts b/src/navigation.ts index 1d1bee9..5126982 100755 --- a/src/navigation.ts +++ b/src/navigation.ts @@ -23,9 +23,10 @@ function parseQuery(query: string) { return data } +type PageFunction = () => JSX.Element; export default class Navigation { - private static _pages: Map = new Map(); + private static _pages: Map = new Map(); private static _page: { route: string, page: JSX.Element }; private static pageObservableServer = new Observable(); public static pageObservable = Navigation.pageObservableServer.getPublicApi(); @@ -34,7 +35,7 @@ export default class Navigation { private static _page_cache = new Map>(); - public static addPage(route: string, comp: typeof Page) { + public static addPage(route: string, comp: typeof Page | PageFunction) { Navigation._pages.set(route, comp); } @@ -69,9 +70,9 @@ export default class Navigation { let oldkey = whash + serializQuery(history.state); if (newkey !== oldkey) { if (replace) - window.history.replaceState(hidden, document.title, newhash); + window.history.replaceState(hidden, document.title, "./" + newhash); else - window.history.pushState(hidden, document.title, newhash); + window.history.pushState(hidden, document.title, "./" + newhash); } let page = this._page_cache.get(newkey); if (!page) { diff --git a/webpack.config.js b/webpack.config.js index c6e7ccf..7a3ffed 100755 --- a/webpack.config.js +++ b/webpack.config.js @@ -25,7 +25,9 @@ module.exports = { public: url.parse(config.callback_url).hostname }, plugins: [ - new CopyWebpackPlugin([{ from: "public" }]), + new CopyWebpackPlugin([{ + from: "public" + }]), new HtmlWebpackPlugin({ title: 'SecureNotes', template: "./src/index.html" @@ -39,40 +41,18 @@ module.exports = { openAnalyzer: false }), new Visualizer(), - // new WorkboxPlugin.GenerateSW({ - // swDest: "sw.js", - // importWorkboxFrom: 'local', - // clientsClaim: true, - // // importsDirectory: "/dist", - // directoryIndex: 'index.html', - // ignoreURLParametersMatching: [/./], - // runtimeCaching: [{ - // urlPattern: /images/, - // handler: 'CacheFirst', - // options: { - // cacheName: 'images', - // expiration: { - // maxEntries: 1000, - // //Recheck after 30 Days - // maxAgeSeconds: 30 * 24 * 60 * 60 - // }, - // }, - // }, { - // urlPattern: /api/, - // handler: 'NetworkOnly' - // }] - // }) ], - entry: "./src/index.tsx", + 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"] + extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js", ".mjs"] }, module: { - rules: [ - { + rules: [{ test: /\.tsx?$/, use: 'ts-loader', exclude: /node_modules/