diff --git a/package-lock.json b/package-lock.json index 63ff31f5..4bc94b17 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3078,9 +3078,9 @@ } }, "comlink": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/comlink/-/comlink-3.1.1.tgz", - "integrity": "sha512-8H9/mrssKE9B4ZMLcN/2bZd1cukP61SrOjm8vhxpRSN8oCw7MSroNNm3Y7/vPUhK5a2AO55vb20rXm3840l3Pw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/comlink/-/comlink-3.2.0.tgz", + "integrity": "sha512-sxkeOmy35tVBsEThqQcUs6KRlLuFSx//oAAm5QGuoRVmqUZtstfntOy/Ao6Lrzz52+an00JRI/FXWofG3ZeH1g==", "dev": true }, "commander": { diff --git a/package.json b/package.json index f86408b0..48e5fb79 100644 --- a/package.json +++ b/package.json @@ -22,12 +22,12 @@ "@webcomponents/custom-elements": "1.2.1", "@webpack-cli/serve": "0.1.3", "assets-webpack-plugin": "3.9.10", - "chokidar": "2.1.2", "chalk": "2.4.2", + "chokidar": "2.1.2", "classnames": "2.2.6", "clean-webpack-plugin": "1.0.1", - "comlink": "3.1.1", "copy-webpack-plugin": "5.0.1", + "comlink": "^3.2.0", "critters-webpack-plugin": "2.3.0", "css-loader": "1.0.1", "ejs": "2.6.1", diff --git a/src/components/App/client-api.ts b/src/components/App/client-api.ts index e093d3f5..be87f5c2 100644 --- a/src/components/App/client-api.ts +++ b/src/components/App/client-api.ts @@ -3,6 +3,11 @@ import { SquooshStartEventType, SquooshSideEventType } from '../compress/index'; import { expose } from 'comlink'; +export interface ReadyMessage { + type: 'READY'; + version: string; +} + export function exposeAPI(app: App) { self.parent.postMessage({ type: 'READY', version: MAJOR_VERSION }, '*'); self.addEventListener('message', (event: MessageEvent) => { @@ -10,7 +15,7 @@ export function exposeAPI(app: App) { return; } event.stopImmediatePropagation(); - self.parent.postMessage({ type: 'READY', version: MAJOR_VERSION }, '*'); + self.parent.postMessage({ type: 'READY', version: MAJOR_VERSION } as ReadyMessage, '*'); }); expose(new API(app), self.parent); } @@ -22,9 +27,20 @@ function addRemovableGlobalListener< return () => document.removeEventListener(name, listener); } -class API { +/** + * The API class contains the methods that are exposed via Comlink to the outside world. + */ +export class API { + /** + * Internal constructor. Do not call. + */ constructor(private _app: App) {} + /** + * Loads a given file into Squoosh. + * @param blob The `Blob` to load + * @param name The name of the file. The extension of this name will be used to deterime which decoder to use. + */ async setFile(blob: Blob, name: string) { return new Promise((resolve) => { document.addEventListener(SquooshStartEventType.START, () => resolve(), { @@ -34,6 +50,10 @@ class API { }); } + /** + * Grabs one side from Squoosh as a `File`. + * @param side The side which to grab. 0 = left, 1 = right. + */ async getBlob(side: 0 | 1) { if (!this._app.state.file || !this._app.compressInstance) { throw new Error('No file has been loaded'); diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index e7819200..4647cda1 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -72,8 +72,7 @@ export default class App extends Component { window.addEventListener('popstate', this.onPopState); import( /* webpackChunkName: "client-api" */ - './client-api', - ).then(m => m.exposeAPI(this)); + './client-api').then(m => m.exposeAPI(this)); } @bind openFile(file: File | Fileish) { diff --git a/src/sdk.ts b/src/sdk.ts new file mode 100644 index 00000000..88b292cb --- /dev/null +++ b/src/sdk.ts @@ -0,0 +1,30 @@ +import {proxy, ProxyResult} from "comlink"; + +import {API, ReadyMessage} from "./components/App/client-api"; + +/** + * This function will load an iFrame + * @param {HTMLIFrameElement} ifr iFrame that will be used to load squoosh + * @param {string} src URL of squoosh instance to use + */ +export default async function loader(ifr: HTMLIFrameElement, src: string = "https://squoosh.app"): Promise> { + ifr.src = src; + await new Promise(resolve => ifr.onload = resolve); + ifr.contentWindow!.postMessage("READY?", "*"); + await new Promise(resolve => { + window.addEventListener("message", function l(ev) { + const msg = ev.data as ReadyMessage; + if(!msg || msg.type !== "READY") { + return; + } + if(msg.version !== MAJOR_VERSION) { + throw Error(`Version mismatch. SDK version ${MAJOR_VERSION}, Squoosh version ${msg.version}`); + } + ev.stopPropagation(); + window.removeEventListener("message", l); + resolve(); + }); + }); + + return proxy(ifr.contentWindow!); +} \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 9e721980..af3f27ed 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -38,7 +38,8 @@ module.exports = async function (_, env) { return { mode: isProd ? 'production' : 'development', entry: { - 'first-interaction': './src/index' + 'first-interaction': './src/index', + 'sdk': './src/sdk' }, devtool: isProd ? 'source-map' : 'inline-source-map', stats: 'minimal',