mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-13 01:07:18 +00:00
Add share target (#469)
* Quick test * More testing * More testing * Removing transfer for now * Changing name so it's easier to tell them apart when installed * Disable minification to ease debugging * Adding navigate lock * lol oops * Add minifying back * Removing minification again, for debugging * Removing broadcast channel bits, to simplify the code * Revert "Removing broadcast channel bits, to simplify the code" This reverts commit 0b2a3ecf2986aae0dd65fdd1ddda2bd9e4e1eac7. * I think this fixes it * Refactor * Suppress flash of home screen during share target * Almost ready, so switching to real name * Removing log * Ahh yes the trailing comma thing * Removing use of BroadcastChannel * Reducing ternary
This commit is contained in:
51
package-lock.json
generated
51
package-lock.json
generated
@@ -2649,7 +2649,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"get-stream": {
|
"get-stream": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
|
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
@@ -5465,8 +5465,7 @@
|
|||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
@@ -5487,14 +5486,12 @@
|
|||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -5509,20 +5506,17 @@
|
|||||||
"code-point-at": {
|
"code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@@ -5639,8 +5633,7 @@
|
|||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
@@ -5652,7 +5645,6 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
@@ -5667,7 +5659,6 @@
|
|||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
@@ -5675,14 +5666,12 @@
|
|||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.3.5",
|
"version": "2.3.5",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.2",
|
"safe-buffer": "^5.1.2",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
@@ -5701,7 +5690,6 @@
|
|||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
@@ -5782,8 +5770,7 @@
|
|||||||
"number-is-nan": {
|
"number-is-nan": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
@@ -5795,7 +5782,6 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
@@ -5881,8 +5867,7 @@
|
|||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"safer-buffer": {
|
"safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
@@ -5918,7 +5903,6 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
@@ -5938,7 +5922,6 @@
|
|||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^2.0.0"
|
"ansi-regex": "^2.0.0"
|
||||||
}
|
}
|
||||||
@@ -5982,14 +5965,12 @@
|
|||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -6096,7 +6077,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"get-stream": {
|
"get-stream": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
|
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
@@ -6286,7 +6267,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"get-stream": {
|
"get-stream": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
|
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
@@ -7353,7 +7334,7 @@
|
|||||||
},
|
},
|
||||||
"is-obj": {
|
"is-obj": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
|
"resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
|
||||||
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
|
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
@@ -12054,7 +12035,7 @@
|
|||||||
},
|
},
|
||||||
"query-string": {
|
"query-string": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz",
|
"resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz",
|
||||||
"integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==",
|
"integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
|||||||
@@ -14,9 +14,10 @@ const ROUTE_EDITOR = '/editor';
|
|||||||
const compressPromise = import(
|
const compressPromise = import(
|
||||||
/* webpackChunkName: "main-app" */
|
/* webpackChunkName: "main-app" */
|
||||||
'../compress');
|
'../compress');
|
||||||
const offlinerPromise = import(
|
|
||||||
/* webpackChunkName: "offliner" */
|
const swBridgePromise = import(
|
||||||
'../../lib/offliner');
|
/* webpackChunkName: "sw-bridge" */
|
||||||
|
'../../lib/sw-bridge');
|
||||||
|
|
||||||
function back() {
|
function back() {
|
||||||
window.history.back();
|
window.history.back();
|
||||||
@@ -25,6 +26,7 @@ function back() {
|
|||||||
interface Props {}
|
interface Props {}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
|
awaitingShareTarget: boolean;
|
||||||
file?: File | Fileish;
|
file?: File | Fileish;
|
||||||
isEditorOpen: Boolean;
|
isEditorOpen: Boolean;
|
||||||
Compress?: typeof import('../compress').default;
|
Compress?: typeof import('../compress').default;
|
||||||
@@ -32,6 +34,7 @@ interface State {
|
|||||||
|
|
||||||
export default class App extends Component<Props, State> {
|
export default class App extends Component<Props, State> {
|
||||||
state: State = {
|
state: State = {
|
||||||
|
awaitingShareTarget: new URL(location.href).searchParams.has('share-target'),
|
||||||
isEditorOpen: false,
|
isEditorOpen: false,
|
||||||
file: undefined,
|
file: undefined,
|
||||||
Compress: undefined,
|
Compress: undefined,
|
||||||
@@ -48,7 +51,15 @@ export default class App extends Component<Props, State> {
|
|||||||
this.showSnack('Failed to load app');
|
this.showSnack('Failed to load app');
|
||||||
});
|
});
|
||||||
|
|
||||||
offlinerPromise.then(({ offliner }) => offliner(this.showSnack));
|
swBridgePromise.then(async ({ offliner, getSharedImage }) => {
|
||||||
|
offliner(this.showSnack);
|
||||||
|
if (!this.state.awaitingShareTarget) return;
|
||||||
|
const file = await getSharedImage();
|
||||||
|
// Remove the ?share-target from the URL
|
||||||
|
history.replaceState('', '', '/');
|
||||||
|
this.openEditor();
|
||||||
|
this.setState({ file, awaitingShareTarget: false });
|
||||||
|
});
|
||||||
|
|
||||||
// In development, persist application state across hot reloads:
|
// In development, persist application state across hot reloads:
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
@@ -103,15 +114,18 @@ export default class App extends Component<Props, State> {
|
|||||||
this.setState({ isEditorOpen: true });
|
this.setState({ isEditorOpen: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
render({}: Props, { file, isEditorOpen, Compress }: State) {
|
render({}: Props, { file, isEditorOpen, Compress, awaitingShareTarget }: State) {
|
||||||
|
const showSpinner = awaitingShareTarget || (isEditorOpen && !Compress);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="app" class={style.app}>
|
<div id="app" class={style.app}>
|
||||||
<file-drop accept="image/*" onfiledrop={this.onFileDrop} class={style.drop}>
|
<file-drop accept="image/*" onfiledrop={this.onFileDrop} class={style.drop}>
|
||||||
{!isEditorOpen
|
{
|
||||||
? <Intro onFile={this.onIntroPickFile} showSnack={this.showSnack} />
|
showSpinner
|
||||||
: (Compress)
|
? <loading-spinner class={style.appLoader}/>
|
||||||
? <Compress file={file!} showSnack={this.showSnack} onBack={back} />
|
: isEditorOpen
|
||||||
: <loading-spinner class={style.appLoader}/>
|
? Compress && <Compress file={file!} showSnack={this.showSnack} onBack={back} />
|
||||||
|
: <Intro onFile={this.onIntroPickFile} showSnack={this.showSnack} />
|
||||||
}
|
}
|
||||||
<snack-bar ref={linkRef(this, 'snackbar')} />
|
<snack-bar ref={linkRef(this, 'snackbar')} />
|
||||||
</file-drop>
|
</file-drop>
|
||||||
|
|||||||
@@ -178,6 +178,7 @@ export default class Options extends Component<Props, State> {
|
|||||||
{encoderSupportMap ?
|
{encoderSupportMap ?
|
||||||
<Select value={encoderState.type} onChange={this.onEncoderTypeChange} large>
|
<Select value={encoderState.type} onChange={this.onEncoderTypeChange} large>
|
||||||
{encoders.filter(encoder => encoderSupportMap[encoder.type]).map(encoder => (
|
{encoders.filter(encoder => encoderSupportMap[encoder.type]).map(encoder => (
|
||||||
|
// tslint:disable-next-line:jsx-key
|
||||||
<option value={encoder.type}>{encoder.label}</option>
|
<option value={encoder.type}>{encoder.label}</option>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ export default class Compress extends Component<Props, State> {
|
|||||||
this.widthQuery.addListener(this.onMobileWidthChange);
|
this.widthQuery.addListener(this.onMobileWidthChange);
|
||||||
this.updateFile(props.file);
|
this.updateFile(props.file);
|
||||||
|
|
||||||
import('../../lib/offliner').then(({ mainAppLoaded }) => mainAppLoaded());
|
import('../../lib/sw-bridge').then(({ mainAppLoaded }) => mainAppLoaded());
|
||||||
}
|
}
|
||||||
|
|
||||||
@bind
|
@bind
|
||||||
@@ -567,6 +567,7 @@ export default class Compress extends Component<Props, State> {
|
|||||||
const [leftImageData, rightImageData] = sides.map(i => i.data);
|
const [leftImageData, rightImageData] = sides.map(i => i.data);
|
||||||
|
|
||||||
const options = sides.map((side, index) => (
|
const options = sides.map((side, index) => (
|
||||||
|
// tslint:disable-next-line:jsx-key
|
||||||
<Options
|
<Options
|
||||||
source={source}
|
source={source}
|
||||||
mobileView={mobileView}
|
mobileView={mobileView}
|
||||||
@@ -582,6 +583,7 @@ export default class Compress extends Component<Props, State> {
|
|||||||
(mobileView ? ['down', 'up'] : ['right', 'left']) as CopyAcrossIconProps['copyDirection'][];
|
(mobileView ? ['down', 'up'] : ['right', 'left']) as CopyAcrossIconProps['copyDirection'][];
|
||||||
|
|
||||||
const results = sides.map((side, index) => (
|
const results = sides.map((side, index) => (
|
||||||
|
// tslint:disable-next-line:jsx-key
|
||||||
<Results
|
<Results
|
||||||
downloadUrl={side.downloadUrl}
|
downloadUrl={side.downloadUrl}
|
||||||
imageFile={side.file}
|
imageFile={side.file}
|
||||||
|
|||||||
@@ -40,6 +40,23 @@ async function updateReady(reg: ServiceWorkerRegistration): Promise<void> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Wait for a shared image */
|
||||||
|
export function getSharedImage(): Promise<File> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const onmessage = (event: MessageEvent) => {
|
||||||
|
if (event.data.action !== 'load-image') return;
|
||||||
|
resolve(event.data.file);
|
||||||
|
navigator.serviceWorker.removeEventListener('message', onmessage);
|
||||||
|
};
|
||||||
|
|
||||||
|
navigator.serviceWorker.addEventListener('message', onmessage);
|
||||||
|
|
||||||
|
// This message is picked up by the service worker - it's how it knows we're ready to receive
|
||||||
|
// the file.
|
||||||
|
navigator.serviceWorker.controller!.postMessage('share-ready');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** Set up the service worker and monitor changes */
|
/** Set up the service worker and monitor changes */
|
||||||
export async function offliner(showSnack: SnackBarElement['showSnackbar']) {
|
export async function offliner(showSnack: SnackBarElement['showSnackbar']) {
|
||||||
// This needs to be a typeof because Webpack.
|
// This needs to be a typeof because Webpack.
|
||||||
@@ -12,5 +12,18 @@
|
|||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"sizes": "1024x1024"
|
"sizes": "1024x1024"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"share_target": {
|
||||||
|
"action": "/?share-target",
|
||||||
|
"method": "POST",
|
||||||
|
"enctype": "multipart/form-data",
|
||||||
|
"params": {
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"name": "file",
|
||||||
|
"accept": ["image/*"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
cacheOrNetworkAndCache, cleanupCache, cacheOrNetwork, cacheBasics, cacheAdditionalProcessors,
|
cacheOrNetworkAndCache, cleanupCache, cacheOrNetwork, cacheBasics, cacheAdditionalProcessors,
|
||||||
|
serveShareTarget,
|
||||||
} from './util';
|
} from './util';
|
||||||
import { get } from 'idb-keyval';
|
import { get } from 'idb-keyval';
|
||||||
|
|
||||||
@@ -40,14 +41,23 @@ self.addEventListener('activate', (event) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
self.addEventListener('fetch', (event) => {
|
self.addEventListener('fetch', (event) => {
|
||||||
// We only care about GET.
|
|
||||||
if (event.request.method !== 'GET') return;
|
|
||||||
|
|
||||||
const url = new URL(event.request.url);
|
const url = new URL(event.request.url);
|
||||||
|
|
||||||
// Don't care about other-origin URLs
|
// Don't care about other-origin URLs
|
||||||
if (url.origin !== location.origin) return;
|
if (url.origin !== location.origin) return;
|
||||||
|
|
||||||
|
if (
|
||||||
|
url.pathname === '/' &&
|
||||||
|
url.searchParams.has('share-target') &&
|
||||||
|
event.request.method === 'POST'
|
||||||
|
) {
|
||||||
|
serveShareTarget(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only care about GET from here on in.
|
||||||
|
if (event.request.method !== 'GET') return;
|
||||||
|
|
||||||
if (url.pathname.startsWith('/demo-') || url.pathname.startsWith('/wc-polyfill')) {
|
if (url.pathname.startsWith('/demo-') || url.pathname.startsWith('/wc-polyfill')) {
|
||||||
cacheOrNetworkAndCache(event, dynamicCache);
|
cacheOrNetworkAndCache(event, dynamicCache);
|
||||||
cleanupCache(event, dynamicCache, BUILD_ASSETS);
|
cleanupCache(event, dynamicCache, BUILD_ASSETS);
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import webpDataUrl from 'url-loader!../codecs/tiny.webp';
|
import webpDataUrl from 'url-loader!../codecs/tiny.webp';
|
||||||
|
|
||||||
|
// Give TypeScript the correct global.
|
||||||
|
declare var self: ServiceWorkerGlobalScope;
|
||||||
|
|
||||||
export function cacheOrNetwork(event: FetchEvent): void {
|
export function cacheOrNetwork(event: FetchEvent): void {
|
||||||
event.respondWith(async function () {
|
event.respondWith(async function () {
|
||||||
const cachedResponse = await caches.match(event.request);
|
const cachedResponse = await caches.match(event.request, { ignoreSearch: true });
|
||||||
return cachedResponse || fetch(event.request);
|
return cachedResponse || fetch(event.request);
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
@@ -29,6 +32,23 @@ export function cacheOrNetworkAndCache(event: FetchEvent, cacheName: string): vo
|
|||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function serveShareTarget(event: FetchEvent): void {
|
||||||
|
const dataPromise = event.request.formData();
|
||||||
|
|
||||||
|
// Redirect so the user can refresh the page without resending data.
|
||||||
|
// @ts-ignore It doesn't like me giving a response to respondWith, although it's allowed.
|
||||||
|
event.respondWith(Response.redirect('/?share-target'));
|
||||||
|
|
||||||
|
event.waitUntil(async function () {
|
||||||
|
// The page sends this message to tell the service worker it's ready to receive the file.
|
||||||
|
await nextMessage('share-ready');
|
||||||
|
const client = await self.clients.get(event.resultingClientId);
|
||||||
|
const data = await dataPromise;
|
||||||
|
const file = data.get('file');
|
||||||
|
client.postMessage({ file, action: 'load-image' });
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
|
||||||
export function cleanupCache(event: FetchEvent, cacheName: string, keepAssets: string[]) {
|
export function cleanupCache(event: FetchEvent, cacheName: string, keepAssets: string[]) {
|
||||||
event.waitUntil(async function () {
|
event.waitUntil(async function () {
|
||||||
const cache = await caches.open(cacheName);
|
const cache = await caches.open(cacheName);
|
||||||
@@ -104,3 +124,26 @@ export async function cacheAdditionalProcessors(cacheName: string, buildAssets:
|
|||||||
const cache = await caches.open(cacheName);
|
const cache = await caches.open(cacheName);
|
||||||
await cache.addAll(toCache);
|
await cache.addAll(toCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nextMessageResolveMap = new Map<string, (() => void)[]>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait on a message with a particular event.data value.
|
||||||
|
*
|
||||||
|
* @param dataVal The event.data value.
|
||||||
|
*/
|
||||||
|
function nextMessage(dataVal: string): Promise<void> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if (!nextMessageResolveMap.has(dataVal)) {
|
||||||
|
nextMessageResolveMap.set(dataVal, []);
|
||||||
|
}
|
||||||
|
nextMessageResolveMap.get(dataVal)!.push(resolve);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
self.addEventListener('message', (event) => {
|
||||||
|
const resolvers = nextMessageResolveMap.get(event.data);
|
||||||
|
if (!resolvers) return;
|
||||||
|
nextMessageResolveMap.delete(event.data);
|
||||||
|
for (const resolve of resolvers) resolve();
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user