Making Share Target functional

This commit is contained in:
Fabian 2019-06-03 16:51:11 +02:00
parent 7917a628ef
commit 31d9f99b77
13 changed files with 114 additions and 88 deletions

32
package-lock.json generated
View File

@ -148,6 +148,12 @@
"@types/node": "*" "@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": { "@webassemblyjs/ast": {
"version": "1.8.5", "version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
@ -3231,9 +3237,9 @@
} }
}, },
"fstream": { "fstream": {
"version": "1.0.11", "version": "1.0.12",
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
"integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
"dev": true, "dev": true,
"requires": { "requires": {
"graceful-fs": "^4.1.2", "graceful-fs": "^4.1.2",
@ -7029,13 +7035,13 @@
"dev": true "dev": true
}, },
"tar": { "tar": {
"version": "2.2.1", "version": "2.2.2",
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
"integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
"dev": true, "dev": true,
"requires": { "requires": {
"block-stream": "*", "block-stream": "*",
"fstream": "^1.0.2", "fstream": "^1.0.12",
"inherits": "2" "inherits": "2"
} }
}, },
@ -7964,9 +7970,9 @@
} }
}, },
"webpack-dev-server": { "webpack-dev-server": {
"version": "3.5.0", "version": "3.5.1",
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.5.0.tgz", "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.5.1.tgz",
"integrity": "sha512-Gr4tBz+BRliDy1Jh9YJBOuwf13CipVxf4PCH7alB/rV/heszJ/U8M7KYekzlQn8XvoGgyozw7Uef2GDFd0ZLvg==", "integrity": "sha512-0IdMGddJcnK9zesZOeHWl4uAOVfypn7DSrdNWtclROkVBXy/TcBN+6eEG1wNfLT9dXVfaRZZsLTJt0mJtgTQgw==",
"dev": true, "dev": true,
"requires": { "requires": {
"ansi-html": "0.0.7", "ansi-html": "0.0.7",
@ -8593,8 +8599,7 @@
"workbox-core": { "workbox-core": {
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-4.3.1.tgz", "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-4.3.1.tgz",
"integrity": "sha512-I3C9jlLmMKPxAC1t0ExCq+QoAMd0vAAHULEgRZ7kieCdUd919n53WC0AfvokHNwqRhGn+tIIj7vcb5duCjs2Kg==", "integrity": "sha512-I3C9jlLmMKPxAC1t0ExCq+QoAMd0vAAHULEgRZ7kieCdUd919n53WC0AfvokHNwqRhGn+tIIj7vcb5duCjs2Kg=="
"dev": true
}, },
"workbox-expiration": { "workbox-expiration": {
"version": "4.3.1", "version": "4.3.1",
@ -8630,7 +8635,6 @@
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-4.3.1.tgz", "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-4.3.1.tgz",
"integrity": "sha512-piSg/2csPoIi/vPpp48t1q5JLYjMkmg5gsXBQkh/QYapCdVwwmKlU9mHdmy52KsDGIjVaqEUMFvEzn2LRaigqQ==", "integrity": "sha512-piSg/2csPoIi/vPpp48t1q5JLYjMkmg5gsXBQkh/QYapCdVwwmKlU9mHdmy52KsDGIjVaqEUMFvEzn2LRaigqQ==",
"dev": true,
"requires": { "requires": {
"workbox-core": "^4.3.1" "workbox-core": "^4.3.1"
} }
@ -8648,7 +8652,6 @@
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-4.3.1.tgz", "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-4.3.1.tgz",
"integrity": "sha512-FkbtrODA4Imsi0p7TW9u9MXuQ5P4pVs1sWHK4dJMMChVROsbEltuE79fBoIk/BCztvOJ7yUpErMKa4z3uQLX+g==", "integrity": "sha512-FkbtrODA4Imsi0p7TW9u9MXuQ5P4pVs1sWHK4dJMMChVROsbEltuE79fBoIk/BCztvOJ7yUpErMKa4z3uQLX+g==",
"dev": true,
"requires": { "requires": {
"workbox-core": "^4.3.1" "workbox-core": "^4.3.1"
} }
@ -8657,7 +8660,6 @@
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-4.3.1.tgz", "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-4.3.1.tgz",
"integrity": "sha512-F/+E57BmVG8dX6dCCopBlkDvvhg/zj6VDs0PigYwSN23L8hseSRwljrceU2WzTvk/+BSYICsWmRq5qHS2UYzhw==", "integrity": "sha512-F/+E57BmVG8dX6dCCopBlkDvvhg/zj6VDs0PigYwSN23L8hseSRwljrceU2WzTvk/+BSYICsWmRq5qHS2UYzhw==",
"dev": true,
"requires": { "requires": {
"workbox-core": "^4.3.1" "workbox-core": "^4.3.1"
} }

View File

@ -23,12 +23,16 @@
"lodash.clonedeep": "^4.5.0", "lodash.clonedeep": "^4.5.0",
"secure-file-wrapper": "git+https://git.stamm.me/OpenServer/OSSecureFileWrapper.git", "secure-file-wrapper": "git+https://git.stamm.me/OpenServer/OSSecureFileWrapper.git",
"uikit": "^3.1.5", "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": { "devDependencies": {
"@types/lodash.clonedeep": "^4.5.6", "@types/lodash.clonedeep": "^4.5.6",
"@types/uikit": "^2.27.7", "@types/uikit": "^2.27.7",
"@types/uuid": "^3.4.4", "@types/uuid": "^3.4.4",
"@types/workbox-sw": "^4.2.0",
"copy-webpack-plugin": "^5.0.3", "copy-webpack-plugin": "^5.0.3",
"css-loader": "^2.1.1", "css-loader": "^2.1.1",
"file-loader": "^3.0.1", "file-loader": "^3.0.1",
@ -44,7 +48,7 @@
"webpack": "^4.32.2", "webpack": "^4.32.2",
"webpack-bundle-analyzer": "^3.3.2", "webpack-bundle-analyzer": "^3.3.2",
"webpack-cli": "^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", "webpack-visualizer-plugin": "^0.1.11",
"workbox-webpack-plugin": "^4.3.1", "workbox-webpack-plugin": "^4.3.1",
"worker-loader": "^2.0.0" "worker-loader": "^2.0.0"

View File

@ -3,10 +3,9 @@
"name": "Secure Notes", "name": "Secure Notes",
"decription": "A place to store your notes securly", "decription": "A place to store your notes securly",
"share_target": { "share_target": {
"url_template": "/#/share?title={title}&text={text}&url={url}", "action": "/share",
"method": "GET", "method": "GET",
"enctype": "application/x-www-form-urlencoded", "enctype": "application/x-www-form-urlencoded",
"action": "/",
"params": { "params": {
"title": "title", "title": "title",
"text": "text", "text": "text",

View File

@ -6,6 +6,7 @@ const CACHE = "offline";
let precacheFiles = [ let precacheFiles = [
"/", "/",
"/index.html",
"/main.js", "/main.js",
"/main.css", "/main.css",
"/serviceworker.js" "/serviceworker.js"
@ -46,6 +47,7 @@ var Types;
Types[Types["CACHE"] = 0] = "CACHE"; Types[Types["CACHE"] = 0] = "CACHE";
Types[Types["NOCACHE"] = 1] = "NOCACHE"; Types[Types["NOCACHE"] = 1] = "NOCACHE";
Types[Types["REFRESH"] = 2] = "REFRESH"; Types[Types["REFRESH"] = 2] = "REFRESH";
Types[Types["INDEX"] = 3] = "INDEX";
})(Types || (Types = {})); })(Types || (Types = {}));
let rules = [{ let rules = [{
@ -53,6 +55,11 @@ let rules = [{
return url.indexOf("/api/") >= 0; return url.indexOf("/api/") >= 0;
}, },
type: Types.NOCACHE type: Types.NOCACHE
}, {
match: (url) => {
return url.indexOf("/share") >= 0;
},
type: Types.INDEX
}, },
{ {
match: () => { match: () => {
@ -77,6 +84,11 @@ self.addEventListener('fetch', (evt) => {
}); });
case Types.NOCACHE: case Types.NOCACHE:
return fetch(evt.request); return fetch(evt.request);
case Types.INDEX:
return refresh(new Request("/")).then(r => {
evt.waitUntil(r.refresh.catch(_ => {}));
return r.result;
})
} }
})()); })());
}); });

View File

@ -65,7 +65,7 @@ export class Footer extends Component<{}, { synced: boolean, syncing: boolean }>
Welcome <b>{Notes.name}</b> Welcome <b>{Notes.name}</b>
</span> </span>
<span style="color: lightgrey;"> <span style="color: lightgrey;">
v1.1 v1.2
</span> </span>
</footer> </footer>
} }

View File

@ -1,5 +1,4 @@
import { h, Component } from "preact"; import { h, Component } from "preact";
import Notes from "../notes";
import "./notifications.scss" import "./notifications.scss"
import Notifications, { MessageType } from "../notifications"; import Notifications, { MessageType } from "../notifications";
@ -37,11 +36,11 @@ export default class NotificationsComponent extends Component<{}, {
this.setState({ notifications: n }); this.setState({ notifications: n });
setTimeout(() => { setTimeout(() => {
this.removeNot(not); this.removeNot(not);
}, 3000); }, 20000);
} }
removeNot(not: { message: string }) { 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 }); this.setState({ notifications: n });
} }

View File

@ -0,0 +1,5 @@
import { h } from "preact";
export default function Error404Page() {
return <h1>Page not found!</h1>;
}

View File

@ -6,7 +6,7 @@ import Navigation from "../../../navigation";
export default class SharePage extends Page<{ state: any }, { vault: string }> { export default class SharePage extends Page<{ state: any }, { vault: string }> {
text: string; text: string;
componentWillMount() { componentWillMount() {
let { title, text, url } = Navigation.getQuery() || {} as any; let { title, text, url } = this.props.state;
let note = ""; let note = "";
if (title) { if (title) {
note += title + "\n" note += title + "\n"
@ -24,7 +24,9 @@ export default class SharePage extends Page<{ state: any }, { vault: string }> {
render() { render() {
return <VaultsPage state={undefined} selectVault onSelected={vault => { return <VaultsPage state={undefined} selectVault onSelected={vault => {
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 });
}} /> }} />
} }
} }

View File

@ -74,17 +74,30 @@ export default class EntryList extends Component<{ vault: Promise<IVault> }, { 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; let share;
if ((window.navigator as any).share) { if ((window.navigator as any).share) {
share = <button class="uk-button" onClick={() => shareNote()}> share = <button class="uk-button" onClick={shareNote}>
share share
</button> </button>
let context = <ContextMenu event={evt} >
{share}
</ContextMenu>
this.setState({ context });
} }
let context = <ContextMenu event={evt} >
{share}
<button class="uk-button" onClick={deleteNote}>delete</button>
</ContextMenu>
this.setState({ context });
return false; return false;
} }

View File

@ -218,7 +218,7 @@ export default class VaultsPage extends Page<VaultsProps, { vaults: VaultList, m
{this.state.context} {this.state.context}
<header class="uk-background-primary"> <header class="uk-background-primary">
<span></span> <span></span>
<h3 style="display:inline" onClick={() => Navigation.setPage("/")}>Your vaults:</h3> <h3 style="display:inline" onClick={() => Navigation.setPage("/")}>{this.props.selectVault ? "Select Vault for share" : "Your vaults:"}</h3>
<span></span> <span></span>
</header> </header>
<AddButton onClick={() => this.addButtonClick()} /> <AddButton onClick={() => this.addButtonClick()} />

View File

@ -5,32 +5,32 @@ declare global {
debug: any; debug: any;
} }
namespace JSX { // namespace JSX {
interface IntrinsicElements { // interface IntrinsicElements {
"wired-button": HTMLAttributes; // "wired-button": HTMLAttributes;
"wired-card": HTMLAttributes; // "wired-card": HTMLAttributes;
"wired-checkbox": HTMLAttributes; // "wired-checkbox": HTMLAttributes;
"wired-combo": HTMLAttributes; // "wired-combo": HTMLAttributes;
"wired-fab": HTMLAttributes; // "wired-fab": HTMLAttributes;
"wired-icon-button": HTMLAttributes; // "wired-icon-button": HTMLAttributes;
"wired-input": HTMLAttributes; // "wired-input": HTMLAttributes;
"wired-item": HTMLAttributes; // "wired-item": HTMLAttributes;
"wired-lib": HTMLAttributes; // "wired-lib": HTMLAttributes;
"wired-listbox": HTMLAttributes; // "wired-listbox": HTMLAttributes;
"wired-progress": HTMLAttributes; // "wired-progress": HTMLAttributes;
"wired-radio-group": HTMLAttributes; // "wired-radio-group": HTMLAttributes;
"wired-radio": HTMLAttributes; // "wired-radio": HTMLAttributes;
"wired-slider": HTMLAttributes; // "wired-slider": HTMLAttributes;
"wired-spinner": HTMLAttributes; // "wired-spinner": HTMLAttributes;
"wired-tabs": HTMLAttributes; // "wired-tabs": HTMLAttributes;
"wired-textarea": HTMLAttributes; // "wired-textarea": HTMLAttributes;
"wired-toggle": HTMLAttributes; // "wired-toggle": HTMLAttributes;
"wired-tooltip": HTMLAttributes; // "wired-tooltip": HTMLAttributes;
} // }
} // }
} }
// declare const window: Window; declare const window: Window;
window.requestIdleCallback = window.requestIdleCallback =
window.requestIdleCallback || window.requestIdleCallback ||
@ -77,6 +77,7 @@ import DemoPage from './components/demo';
import VaultPage from './components/routes/vault/Vault'; import VaultPage from './components/routes/vault/Vault';
import SharePage from './components/routes/share/Share'; import SharePage from './components/routes/share/Share';
import Notifications from './notifications'; import Notifications from './notifications';
import Error404Page from './components/routes/404';
window.debug.notes = Notes; window.debug.notes = Notes;
(async () => { (async () => {
@ -104,6 +105,14 @@ window.debug.notes = Notes;
Navigation.addPage("/vault", VaultPage as typeof Page) Navigation.addPage("/vault", VaultPage as typeof Page)
Navigation.addPage("/demo", DemoPage as typeof Page) Navigation.addPage("/demo", DemoPage as typeof Page)
Navigation.addPage("/share", SharePage 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(); Navigation.start();
render(<App />, document.body, document.getElementById('app')); render(<App />, document.body, document.getElementById('app'));

View File

@ -23,9 +23,10 @@ function parseQuery(query: string) {
return data return data
} }
type PageFunction = () => JSX.Element;
export default class Navigation { export default class Navigation {
private static _pages: Map<string, typeof Page> = new Map(); private static _pages: Map<string, typeof Page | PageFunction> = new Map();
private static _page: { route: string, page: JSX.Element }; private static _page: { route: string, page: JSX.Element };
private static pageObservableServer = new Observable<JSX.Element>(); private static pageObservableServer = new Observable<JSX.Element>();
public static pageObservable = Navigation.pageObservableServer.getPublicApi(); public static pageObservable = Navigation.pageObservableServer.getPublicApi();
@ -34,7 +35,7 @@ export default class Navigation {
private static _page_cache = new Map<string, VNode<any>>(); private static _page_cache = new Map<string, VNode<any>>();
public static addPage(route: string, comp: typeof Page) { public static addPage(route: string, comp: typeof Page | PageFunction) {
Navigation._pages.set(route, comp); Navigation._pages.set(route, comp);
} }
@ -69,9 +70,9 @@ export default class Navigation {
let oldkey = whash + serializQuery(history.state); let oldkey = whash + serializQuery(history.state);
if (newkey !== oldkey) { if (newkey !== oldkey) {
if (replace) if (replace)
window.history.replaceState(hidden, document.title, newhash); window.history.replaceState(hidden, document.title, "./" + newhash);
else else
window.history.pushState(hidden, document.title, newhash); window.history.pushState(hidden, document.title, "./" + newhash);
} }
let page = this._page_cache.get(newkey); let page = this._page_cache.get(newkey);
if (!page) { if (!page) {

View File

@ -25,7 +25,9 @@ module.exports = {
public: url.parse(config.callback_url).hostname public: url.parse(config.callback_url).hostname
}, },
plugins: [ plugins: [
new CopyWebpackPlugin([{ from: "public" }]), new CopyWebpackPlugin([{
from: "public"
}]),
new HtmlWebpackPlugin({ new HtmlWebpackPlugin({
title: 'SecureNotes', title: 'SecureNotes',
template: "./src/index.html" template: "./src/index.html"
@ -39,40 +41,18 @@ module.exports = {
openAnalyzer: false openAnalyzer: false
}), }),
new Visualizer(), 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. // Enable sourcemaps for debugging webpack's output.
devtool: "eval", devtool: "eval",
resolve: { resolve: {
// Add '.ts' and '.tsx' as resolvable extensions. // 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: { module: {
rules: [ rules: [{
{
test: /\.tsx?$/, test: /\.tsx?$/,
use: 'ts-loader', use: 'ts-loader',
exclude: /node_modules/ exclude: /node_modules/