mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-12 08:47:31 +00:00
Merge upstream
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@ node_modules
|
|||||||
*.css.d.ts
|
*.css.d.ts
|
||||||
build
|
build
|
||||||
*.o
|
*.o
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
# Auto-generated by lib/feature-plugin.js
|
# Auto-generated by lib/feature-plugin.js
|
||||||
src/features-worker/index.ts
|
src/features-worker/index.ts
|
||||||
|
|||||||
BIN
cli/.DS_Store
vendored
BIN
cli/.DS_Store
vendored
Binary file not shown.
1
cli/.gitignore
vendored
1
cli/.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
node_modules
|
node_modules
|
||||||
build
|
build
|
||||||
|
.DS_Store
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ The default values for each `config` option can be found in the [`codecs.js`][co
|
|||||||
|
|
||||||
Squoosh CLI has an _experimental_ auto optimizer that compresses an image as much as possible, trying to hit a specific [Butteraugli] target value. The higher the Butteraugli target value, the more artifacts can be introduced.
|
Squoosh CLI has an _experimental_ auto optimizer that compresses an image as much as possible, trying to hit a specific [Butteraugli] target value. The higher the Butteraugli target value, the more artifacts can be introduced.
|
||||||
|
|
||||||
You can make use of the auto optimizer buy using “auto” as the config object.
|
You can make use of the auto optimizer by using “auto” as the config object.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ npx @squoosh/cli --wp2 auto test.png
|
$ npx @squoosh/cli --wp2 auto test.png
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 35 KiB |
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 65 KiB |
2
cli/package-lock.json
generated
2
cli/package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@squoosh/cli",
|
"name": "@squoosh/cli",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@squoosh/cli",
|
"name": "@squoosh/cli",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"description": "A CLI for Squoosh",
|
"description": "A CLI for Squoosh",
|
||||||
"public": true,
|
"public": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { isMainThread } from 'worker_threads';
|
|||||||
import { cpus } from 'os';
|
import { cpus } from 'os';
|
||||||
import { extname, join, basename } from 'path';
|
import { extname, join, basename } from 'path';
|
||||||
import { promises as fsp } from 'fs';
|
import { promises as fsp } from 'fs';
|
||||||
|
import { resolve as resolvePath } from 'path';
|
||||||
import { version } from 'json:../package.json';
|
import { version } from 'json:../package.json';
|
||||||
import ora from 'ora';
|
import ora from 'ora';
|
||||||
import kleur from 'kleur';
|
import kleur from 'kleur';
|
||||||
@@ -182,7 +183,32 @@ function progressTracker(results) {
|
|||||||
return tracker;
|
return tracker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function checkInputFilesValid(files) {
|
||||||
|
const validFiles = [];
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
try {
|
||||||
|
await fsp.stat(file);
|
||||||
|
} catch (err) {
|
||||||
|
if (err.code === 'ENOENT') {
|
||||||
|
console.warn(
|
||||||
|
`Warning: Input file does not exist: ${resolvePath(file)}`,
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
validFiles.push(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return validFiles;
|
||||||
|
}
|
||||||
|
|
||||||
async function processFiles(files) {
|
async function processFiles(files) {
|
||||||
|
files = await checkInputFilesValid(files);
|
||||||
|
|
||||||
const parallelism = cpus().length;
|
const parallelism = cpus().length;
|
||||||
|
|
||||||
const results = new Map();
|
const results = new Map();
|
||||||
|
|||||||
12
cli/tmp.txt
12
cli/tmp.txt
File diff suppressed because one or more lines are too long
@@ -112,7 +112,9 @@ export default async function ({ watch }) {
|
|||||||
plugins: [
|
plugins: [
|
||||||
{ resolveFileUrl, resolveImportMeta },
|
{ resolveFileUrl, resolveImportMeta },
|
||||||
OMT({ loader: await omtLoaderPromise }),
|
OMT({ loader: await omtLoaderPromise }),
|
||||||
serviceWorkerPlugin({ output: 'static/sw.js' }),
|
serviceWorkerPlugin({
|
||||||
|
output: 'static/serviceworker.js',
|
||||||
|
}),
|
||||||
...commonPlugins(),
|
...commonPlugins(),
|
||||||
commonjs(),
|
commonjs(),
|
||||||
resolve(),
|
resolve(),
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ import {
|
|||||||
encoderMap,
|
encoderMap,
|
||||||
} from '../../feature-meta';
|
} from '../../feature-meta';
|
||||||
import Expander from './Expander';
|
import Expander from './Expander';
|
||||||
import Checkbox from './Checkbox';
|
|
||||||
import Toggle from './Toggle';
|
import Toggle from './Toggle';
|
||||||
import Select from './Select';
|
import Select from './Select';
|
||||||
import { Options as QuantOptionsComponent } from 'features/processors/quantize/client';
|
import { Options as QuantOptionsComponent } from 'features/processors/quantize/client';
|
||||||
import { Options as ResizeOptionsComponent } from 'features/processors/resize/client';
|
import { Options as ResizeOptionsComponent } from 'features/processors/resize/client';
|
||||||
|
import { CLIIcon, SwapIcon } from 'client/lazy-app/icons';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
index: 0 | 1;
|
index: 0 | 1;
|
||||||
@@ -28,6 +28,8 @@ interface Props {
|
|||||||
onEncoderTypeChange(index: 0 | 1, newType: OutputType): void;
|
onEncoderTypeChange(index: 0 | 1, newType: OutputType): void;
|
||||||
onEncoderOptionsChange(index: 0 | 1, newOptions: EncoderOptions): void;
|
onEncoderOptionsChange(index: 0 | 1, newOptions: EncoderOptions): void;
|
||||||
onProcessorOptionsChange(index: 0 | 1, newOptions: ProcessorState): void;
|
onProcessorOptionsChange(index: 0 | 1, newOptions: ProcessorState): void;
|
||||||
|
onCopyToOtherSideClick(index: 0 | 1): void;
|
||||||
|
onCopyCliClick(index: 0 | 1): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
@@ -106,6 +108,14 @@ export default class Options extends Component<Props, State> {
|
|||||||
this.props.onEncoderOptionsChange(this.props.index, newOptions);
|
this.props.onEncoderOptionsChange(this.props.index, newOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private onCopyCliClick = () => {
|
||||||
|
this.props.onCopyCliClick(this.props.index);
|
||||||
|
};
|
||||||
|
|
||||||
|
private onCopyToOtherSideClick = () => {
|
||||||
|
this.props.onCopyToOtherSideClick(this.props.index);
|
||||||
|
};
|
||||||
|
|
||||||
render(
|
render(
|
||||||
{ source, encoderState, processorState }: Props,
|
{ source, encoderState, processorState }: Props,
|
||||||
{ supportedEncoderMap }: State,
|
{ supportedEncoderMap }: State,
|
||||||
@@ -125,7 +135,25 @@ export default class Options extends Component<Props, State> {
|
|||||||
<Expander>
|
<Expander>
|
||||||
{!encoderState ? null : (
|
{!encoderState ? null : (
|
||||||
<div>
|
<div>
|
||||||
<h3 class={style.optionsTitle}>Edit</h3>
|
<h3 class={style.optionsTitle}>
|
||||||
|
<div class={style.titleAndButtons}>
|
||||||
|
Edit
|
||||||
|
<button
|
||||||
|
class={style.cliButton}
|
||||||
|
title="Copy npx command"
|
||||||
|
onClick={this.onCopyCliClick}
|
||||||
|
>
|
||||||
|
<CLIIcon />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class={style.copyOverButton}
|
||||||
|
title="Copy settings to other side"
|
||||||
|
onClick={this.onCopyToOtherSideClick}
|
||||||
|
>
|
||||||
|
<SwapIcon />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</h3>
|
||||||
<label class={style.sectionEnabler}>
|
<label class={style.sectionEnabler}>
|
||||||
Resize
|
Resize
|
||||||
<Toggle
|
<Toggle
|
||||||
|
|||||||
@@ -81,3 +81,37 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.title-and-buttons {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-auto-columns: max-content;
|
||||||
|
grid-auto-flow: column;
|
||||||
|
display: grid;
|
||||||
|
gap: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-button {
|
||||||
|
composes: unbutton from global;
|
||||||
|
svg {
|
||||||
|
--size: 20px;
|
||||||
|
display: block;
|
||||||
|
width: var(--size);
|
||||||
|
height: var(--size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cli-button {
|
||||||
|
composes: title-button;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
stroke: var(--header-text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-over-button {
|
||||||
|
composes: title-button;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
fill: var(--header-text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ export default class Output extends Component<Props, State> {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class={style.controls} hidden={hidden}>
|
<div class={style.controls} hidden={hidden}>
|
||||||
<div class={style.zoomControls}>
|
<div class={style.buttonGroup}>
|
||||||
<button class={style.button} onClick={this.zoomOut}>
|
<button class={style.button} onClick={this.zoomOut}>
|
||||||
<RemoveIcon />
|
<RemoveIcon />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -66,7 +66,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.zoom-controls {
|
.button-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
|||||||
@@ -411,7 +411,7 @@ export default class Compress extends Component<Props, State> {
|
|||||||
this.queueUpdateImage();
|
this.queueUpdateImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async onCopyToOtherClick(index: 0 | 1) {
|
private onCopyToOtherClick = async (index: 0 | 1) => {
|
||||||
const otherIndex = index ? 0 : 1;
|
const otherIndex = index ? 0 : 1;
|
||||||
const oldSettings = this.state.sides[otherIndex];
|
const oldSettings = this.state.sides[otherIndex];
|
||||||
const newSettings = { ...this.state.sides[index] };
|
const newSettings = { ...this.state.sides[index] };
|
||||||
@@ -436,7 +436,7 @@ export default class Compress extends Component<Props, State> {
|
|||||||
this.setState({
|
this.setState({
|
||||||
sides: cleanSet(this.state.sides, otherIndex, oldSettings),
|
sides: cleanSet(this.state.sides, otherIndex, oldSettings),
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
private onPreprocessorChange = async (
|
private onPreprocessorChange = async (
|
||||||
preprocessorState: PreprocessorState,
|
preprocessorState: PreprocessorState,
|
||||||
@@ -483,6 +483,29 @@ export default class Compress extends Component<Props, State> {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private onCopyCliClick = async (index: 0 | 1) => {
|
||||||
|
try {
|
||||||
|
const cliInvocation = generateCliInvocation(
|
||||||
|
this.state.sides[index].latestSettings.encoderState!,
|
||||||
|
this.state.sides[index].latestSettings.processorState,
|
||||||
|
);
|
||||||
|
await navigator.clipboard.writeText(cliInvocation);
|
||||||
|
const result = await this.props.showSnack(
|
||||||
|
'CLI command copied to clipboard',
|
||||||
|
{
|
||||||
|
timeout: 8000,
|
||||||
|
actions: ['usage', 'dismiss'],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result === 'usage') {
|
||||||
|
open('https://github.com/GoogleChromeLabs/squoosh/tree/dev/cli');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.props.showSnack(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Debounce the heavy lifting of updateImage.
|
* Debounce the heavy lifting of updateImage.
|
||||||
* Otherwise, the thrashing causes jank, and sometimes crashes iOS Safari.
|
* Otherwise, the thrashing causes jank, and sometimes crashes iOS Safari.
|
||||||
@@ -860,6 +883,8 @@ export default class Compress extends Component<Props, State> {
|
|||||||
onEncoderTypeChange={this.onEncoderTypeChange}
|
onEncoderTypeChange={this.onEncoderTypeChange}
|
||||||
onEncoderOptionsChange={this.onEncoderOptionsChange}
|
onEncoderOptionsChange={this.onEncoderOptionsChange}
|
||||||
onProcessorOptionsChange={this.onProcessorOptionsChange}
|
onProcessorOptionsChange={this.onProcessorOptionsChange}
|
||||||
|
onCopyCliClick={this.onCopyCliClick}
|
||||||
|
onCopyToOtherSideClick={this.onCopyToOtherClick}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|||||||
@@ -124,3 +124,14 @@ export const DownloadIcon = () => (
|
|||||||
<path d="M6.6 2.7h-4v13.2h2.7A2.7 2.7 0 018 18.6a2.7 2.7 0 002.6 2.6h2.7a2.7 2.7 0 002.6-2.6 2.7 2.7 0 012.7-2.7h2.6V2.7h-4a1.3 1.3 0 110-2.7h4A2.7 2.7 0 0124 2.7v18.5a2.7 2.7 0 01-2.7 2.7H2.7A2.7 2.7 0 010 21.2V2.7A2.7 2.7 0 012.7 0h4a1.3 1.3 0 010 2.7zm4 7.4V1.3a1.3 1.3 0 112.7 0v8.8L15 8.4a1.3 1.3 0 011.9 1.8l-4 4a1.3 1.3 0 01-1.9 0l-4-4A1.3 1.3 0 019 8.4z" />
|
<path d="M6.6 2.7h-4v13.2h2.7A2.7 2.7 0 018 18.6a2.7 2.7 0 002.6 2.6h2.7a2.7 2.7 0 002.6-2.6 2.7 2.7 0 012.7-2.7h2.6V2.7h-4a1.3 1.3 0 110-2.7h4A2.7 2.7 0 0124 2.7v18.5a2.7 2.7 0 01-2.7 2.7H2.7A2.7 2.7 0 010 21.2V2.7A2.7 2.7 0 012.7 0h4a1.3 1.3 0 010 2.7zm4 7.4V1.3a1.3 1.3 0 112.7 0v8.8L15 8.4a1.3 1.3 0 011.9 1.8l-4 4a1.3 1.3 0 01-1.9 0l-4-4A1.3 1.3 0 019 8.4z" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const CLIIcon = () => (
|
||||||
|
<svg viewBox="0 0 81.3 68.8">
|
||||||
|
<path
|
||||||
|
fill="none"
|
||||||
|
stroke-miterlimit="15.6"
|
||||||
|
stroke-width="6.3"
|
||||||
|
d="M3.1 3.1h75v62.5h-75zm18.8 43.8l12.5-12.5-12.5-12.5m18.7 25h18.8"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|||||||
51
src/client/lazy-app/util/cli.ts
Normal file
51
src/client/lazy-app/util/cli.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2020 Google Inc. All Rights Reserved.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { EncoderState, ProcessorState } from '../feature-meta';
|
||||||
|
|
||||||
|
// Maps our encoder.type values to CLI parameter names
|
||||||
|
const typeMap = new Map<string, string>([
|
||||||
|
['avif', '--avif'],
|
||||||
|
['jxl', '--jxl'],
|
||||||
|
['mozJPEG', '--mozjpeg'],
|
||||||
|
['oxiPNG', '--oxipng'],
|
||||||
|
['webP', '--webp'],
|
||||||
|
['wp2', '--wp2'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Same as JSON.stringify, but with single quotes around the entire value
|
||||||
|
// so that shells don’t do weird stuff.
|
||||||
|
function cliJson<T>(v: T): string {
|
||||||
|
return "'" + JSON.stringify(v) + "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateCliInvocation(
|
||||||
|
encoder: EncoderState,
|
||||||
|
processor: ProcessorState,
|
||||||
|
): string {
|
||||||
|
if (!typeMap.has(encoder.type)) {
|
||||||
|
throw Error(`Encoder ${encoder.type} is unsupported in the CLI`);
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
'npx',
|
||||||
|
'@squoosh/cli',
|
||||||
|
...(processor.resize.enabled
|
||||||
|
? ['--resize', cliJson(processor.resize)]
|
||||||
|
: []),
|
||||||
|
...(processor.quantize.enabled
|
||||||
|
? ['--quant', cliJson(processor.quantize)]
|
||||||
|
: []),
|
||||||
|
typeMap.get(encoder.type)!,
|
||||||
|
cliJson(encoder.options),
|
||||||
|
].join(' ');
|
||||||
|
}
|
||||||
137
src/copy/sw-bridge.894ac.js
Normal file
137
src/copy/sw-bridge.894ac.js
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
(self.webpackJsonp = self.webpackJsonp || []).push([
|
||||||
|
[0],
|
||||||
|
{
|
||||||
|
54: function (e, t, n) {
|
||||||
|
'use strict';
|
||||||
|
n.d(t, 'a', function () {
|
||||||
|
return o;
|
||||||
|
}),
|
||||||
|
n.d(t, 'b', function () {
|
||||||
|
return s;
|
||||||
|
});
|
||||||
|
class r {
|
||||||
|
constructor(e = 'keyval-store', t = 'keyval') {
|
||||||
|
(this.storeName = t),
|
||||||
|
(this._dbp = new Promise((n, r) => {
|
||||||
|
const a = indexedDB.open(e, 1);
|
||||||
|
(a.onerror = () => r(a.error)),
|
||||||
|
(a.onsuccess = () => n(a.result)),
|
||||||
|
(a.onupgradeneeded = () => {
|
||||||
|
a.result.createObjectStore(t);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
_withIDBStore(e, t) {
|
||||||
|
return this._dbp.then(
|
||||||
|
(n) =>
|
||||||
|
new Promise((r, a) => {
|
||||||
|
const i = n.transaction(this.storeName, e);
|
||||||
|
(i.oncomplete = () => r()),
|
||||||
|
(i.onabort = i.onerror = () => a(i.error)),
|
||||||
|
t(i.objectStore(this.storeName));
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let a;
|
||||||
|
function i() {
|
||||||
|
return a || (a = new r()), a;
|
||||||
|
}
|
||||||
|
function o(e, t = i()) {
|
||||||
|
let n;
|
||||||
|
return t
|
||||||
|
._withIDBStore('readonly', (t) => {
|
||||||
|
n = t.get(e);
|
||||||
|
})
|
||||||
|
.then(() => n.result);
|
||||||
|
}
|
||||||
|
function s(e, t, n = i()) {
|
||||||
|
return n._withIDBStore('readwrite', (n) => {
|
||||||
|
n.put(t, e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
56: function (e, t, n) {
|
||||||
|
'use strict';
|
||||||
|
n.r(t),
|
||||||
|
function (e) {
|
||||||
|
n.d(t, 'getSharedImage', function () {
|
||||||
|
return i;
|
||||||
|
}),
|
||||||
|
n.d(t, 'offliner', function () {
|
||||||
|
return o;
|
||||||
|
}),
|
||||||
|
n.d(t, 'mainAppLoaded', function () {
|
||||||
|
return s;
|
||||||
|
});
|
||||||
|
var r = n(54);
|
||||||
|
async function a(e) {
|
||||||
|
if (e.waiting) return;
|
||||||
|
const t = await (async function (e) {
|
||||||
|
return e.installing
|
||||||
|
? e.installing
|
||||||
|
: new Promise((t) => {
|
||||||
|
e.addEventListener('updatefound', () => t(e.installing), {
|
||||||
|
once: !0,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})(e);
|
||||||
|
return new Promise((e) => {
|
||||||
|
t.addEventListener('statechange', () => {
|
||||||
|
'installed' === t.state && e();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function i() {
|
||||||
|
return new Promise((e) => {
|
||||||
|
const t = (n) => {
|
||||||
|
'load-image' === n.data.action &&
|
||||||
|
(e(n.data.file),
|
||||||
|
navigator.serviceWorker.removeEventListener('message', t));
|
||||||
|
};
|
||||||
|
navigator.serviceWorker.addEventListener('message', t),
|
||||||
|
navigator.serviceWorker.controller.postMessage('share-ready');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async function o(t) {
|
||||||
|
if ('boolean' == typeof PRERENDER) return;
|
||||||
|
navigator.serviceWorker.register(e);
|
||||||
|
const n = !!navigator.serviceWorker.controller;
|
||||||
|
if (
|
||||||
|
(navigator.serviceWorker.addEventListener(
|
||||||
|
'controllerchange',
|
||||||
|
async () => {
|
||||||
|
n
|
||||||
|
? location.reload()
|
||||||
|
: t('Ready to work offline', { timeout: 5e3 });
|
||||||
|
},
|
||||||
|
),
|
||||||
|
!n)
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
const r = await navigator.serviceWorker.getRegistration();
|
||||||
|
r &&
|
||||||
|
(await a(r),
|
||||||
|
'reload' ===
|
||||||
|
(await t('Update available', {
|
||||||
|
actions: ['reload', 'dismiss'],
|
||||||
|
})) &&
|
||||||
|
(async function () {
|
||||||
|
const e = await navigator.serviceWorker.getRegistration();
|
||||||
|
e && e.waiting && e.waiting.postMessage('skip-waiting');
|
||||||
|
})());
|
||||||
|
}
|
||||||
|
async function s() {
|
||||||
|
if (await Object(r.a)('user-interacted')) return;
|
||||||
|
Object(r.b)('user-interacted', !0);
|
||||||
|
const e = await (async function () {
|
||||||
|
const e = await navigator.serviceWorker.getRegistration();
|
||||||
|
return e ? e.active || e.waiting || e.installing : null;
|
||||||
|
})();
|
||||||
|
e && e.postMessage('cache-all');
|
||||||
|
}
|
||||||
|
}.call(this, n.p + 'serviceworker.js');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
//# sourceMappingURL=sw-bridge.894ac.js.map
|
||||||
4
src/copy/sw.js
Normal file
4
src/copy/sw.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// I accidentally shipped with the wrong service worker name.
|
||||||
|
// This picks up users that still might be using that version.
|
||||||
|
// We'll be able to delete this file eventually.
|
||||||
|
skipWaiting();
|
||||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
@@ -351,6 +351,12 @@ export default class Intro extends Component<Props, State> {
|
|||||||
>
|
>
|
||||||
Privacy
|
Privacy
|
||||||
</a>
|
</a>
|
||||||
|
<a
|
||||||
|
class={style.footerLink}
|
||||||
|
href="https://github.com/GoogleChromeLabs/squoosh/tree/dev/cli"
|
||||||
|
>
|
||||||
|
Squoosh CLI
|
||||||
|
</a>
|
||||||
<a
|
<a
|
||||||
class={style.footerLinkWithLogo}
|
class={style.footerLinkWithLogo}
|
||||||
href="https://github.com/GoogleChromeLabs/squoosh"
|
href="https://github.com/GoogleChromeLabs/squoosh"
|
||||||
|
|||||||
@@ -133,12 +133,18 @@
|
|||||||
|
|
||||||
.footer-items {
|
.footer-items {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|
||||||
|
grid-auto-rows: max-content;
|
||||||
|
justify-items: center;
|
||||||
|
gap: 2rem;
|
||||||
|
|
||||||
|
@media (min-width: 480px) {
|
||||||
justify-content: end;
|
justify-content: end;
|
||||||
grid-auto-columns: max-content;
|
|
||||||
grid-auto-flow: column;
|
grid-auto-flow: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4rem;
|
gap: 4rem;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.footer-link {
|
.footer-link {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const branchOriginTrialIds = new Map([
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'live',
|
'live',
|
||||||
'AgoKiDqjr0GVPtrwV/vuVlrrSvbDa5Yb99s+q66ly816DrrAQ8Cdas33NgDtmhxM4BtDP9PEdyuxHPyTQHD5ZAcAAABUeyJvcmlnaW4iOiJodHRwczovL3NxdW9vc2guYXBwOjQ0MyIsImZlYXR1cmUiOiJXZWJBc3NlbWJseVNpbWQiLCJleHBpcnkiOjE2MDg2NzI5OTR9',
|
'Ak9YMaDZyWUUZFbVJng8FM2LWWNeBcWaHTtHzzaTAq044kMlQH5/hsMb/90Ii2I7m/lPx8EpgOIUMWkWeoaKfgIAAABUeyJvcmlnaW4iOiJodHRwczovL3NxdW9vc2guYXBwOjQ0MyIsImZlYXR1cmUiOiJXZWJBc3NlbWJseVNpbWQiLCJleHBpcnkiOjE2MTExNTkwNjZ9',
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user