forked from external-repos/squoosh
Remove decorators and bundler workarounds
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { h, Component } from 'preact';
|
||||
|
||||
import { bind, linkRef, Fileish } from '../../lib/initial-util';
|
||||
import { linkRef, Fileish } from '../../lib/initial-util';
|
||||
import * as style from './style.module.scss';
|
||||
import { FileDropEvent } from 'file-drop-element';
|
||||
import 'file-drop-element';
|
||||
@@ -43,6 +43,12 @@ export default class App extends Component<Props, State> {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.onFileDrop = this.onFileDrop.bind(this);
|
||||
this.onIntroPickFile = this.onIntroPickFile.bind(this);
|
||||
this.showSnack = this.showSnack.bind(this);
|
||||
this.onPopState = this.onPopState.bind(this);
|
||||
this.openEditor = this.openEditor.bind(this);
|
||||
|
||||
compressPromise.then((module) => {
|
||||
this.setState({ Compress: module.default });
|
||||
}).catch((e) => {
|
||||
@@ -61,7 +67,8 @@ export default class App extends Component<Props, State> {
|
||||
});
|
||||
|
||||
// In development, persist application state across hot reloads:
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// if (process.env.NODE_ENV === 'development') {
|
||||
if (module.hot) {
|
||||
this.setState(window.STATE);
|
||||
const oldCDU = this.componentDidUpdate;
|
||||
this.componentDidUpdate = (props, state, prev) => {
|
||||
@@ -81,7 +88,6 @@ export default class App extends Component<Props, State> {
|
||||
window.addEventListener('popstate', this.onPopState);
|
||||
}
|
||||
|
||||
@bind
|
||||
private onFileDrop({ files }: FileDropEvent) {
|
||||
if (!files || files.length === 0) return;
|
||||
const file = files[0];
|
||||
@@ -89,24 +95,20 @@ export default class App extends Component<Props, State> {
|
||||
this.setState({ file });
|
||||
}
|
||||
|
||||
@bind
|
||||
private onIntroPickFile(file: File | Fileish) {
|
||||
this.openEditor();
|
||||
this.setState({ file });
|
||||
}
|
||||
|
||||
@bind
|
||||
private showSnack(message: string, options: SnackOptions = {}): Promise<string> {
|
||||
if (!this.snackbar) throw Error('Snackbar missing');
|
||||
return this.snackbar.showSnackbar(message, options);
|
||||
}
|
||||
|
||||
@bind
|
||||
private onPopState() {
|
||||
this.setState({ isEditorOpen: location.pathname === ROUTE_EDITOR });
|
||||
}
|
||||
|
||||
@bind
|
||||
private openEditor() {
|
||||
if (this.state.isEditorOpen) return;
|
||||
// Change path, but preserve query string.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { h, Component } from 'preact';
|
||||
|
||||
import * as style from './style.module.scss';
|
||||
import { bind } from '../../lib/initial-util';
|
||||
import { cleanSet, cleanMerge } from '../../lib/clean-modify';
|
||||
import OxiPNGEncoderOptions from '../../codecs/oxipng/options';
|
||||
import MozJpegEncoderOptions from '../../codecs/mozjpeg/options';
|
||||
@@ -82,8 +81,7 @@ export default class Options extends Component<Props, State> {
|
||||
encodersSupported.then(encoderSupportMap => this.setState({ encoderSupportMap }));
|
||||
}
|
||||
|
||||
@bind
|
||||
private onEncoderTypeChange(event: Event) {
|
||||
private onEncoderTypeChange = (event: Event) => {
|
||||
const el = event.currentTarget as HTMLSelectElement;
|
||||
|
||||
// The select element only has values matching encoder types,
|
||||
@@ -92,8 +90,7 @@ export default class Options extends Component<Props, State> {
|
||||
this.props.onEncoderTypeChange(type);
|
||||
}
|
||||
|
||||
@bind
|
||||
private onPreprocessorEnabledChange(event: Event) {
|
||||
private onPreprocessorEnabledChange = (event: Event) => {
|
||||
const el = event.currentTarget as HTMLInputElement;
|
||||
const preprocessor = el.name.split('.')[0] as keyof PreprocessorState;
|
||||
|
||||
@@ -102,15 +99,13 @@ export default class Options extends Component<Props, State> {
|
||||
);
|
||||
}
|
||||
|
||||
@bind
|
||||
private onQuantizerOptionsChange(opts: QuantizeOptions) {
|
||||
private onQuantizerOptionsChange = (opts: QuantizeOptions) => {
|
||||
this.props.onPreprocessorOptionsChange(
|
||||
cleanMerge(this.props.preprocessorState, 'quantizer', opts),
|
||||
);
|
||||
}
|
||||
|
||||
@bind
|
||||
private onResizeOptionsChange(opts: ResizeOptions) {
|
||||
private onResizeOptionsChange = (opts: ResizeOptions) => {
|
||||
this.props.onPreprocessorOptionsChange(
|
||||
cleanMerge(this.props.preprocessorState, 'resize', opts),
|
||||
);
|
||||
|
||||
@@ -3,7 +3,7 @@ import PinchZoom, { ScaleToOpts } from './custom-els/PinchZoom';
|
||||
import './custom-els/PinchZoom';
|
||||
import './custom-els/TwoUp';
|
||||
import * as style from './style.module.scss';
|
||||
import { bind, linkRef } from '../../lib/initial-util';
|
||||
import { linkRef } from '../../lib/initial-util';
|
||||
import { shallowEqual, drawDataToCanvas } from '../../lib/util';
|
||||
import {
|
||||
ToggleBackgroundIcon,
|
||||
@@ -135,29 +135,25 @@ export default class Output extends Component<Props, State> {
|
||||
return props.rightCompressed || (props.source && props.source.processed);
|
||||
}
|
||||
|
||||
@bind
|
||||
private toggleBackground() {
|
||||
private toggleBackground = () => {
|
||||
this.setState({
|
||||
altBackground: !this.state.altBackground,
|
||||
});
|
||||
}
|
||||
|
||||
@bind
|
||||
private zoomIn() {
|
||||
private zoomIn = () => {
|
||||
if (!this.pinchZoomLeft) throw Error('Missing pinch-zoom element');
|
||||
|
||||
this.pinchZoomLeft.scaleTo(this.state.scale * 1.25, scaleToOpts);
|
||||
}
|
||||
|
||||
@bind
|
||||
private zoomOut() {
|
||||
private zoomOut = () => {
|
||||
if (!this.pinchZoomLeft) throw Error('Missing pinch-zoom element');
|
||||
|
||||
this.pinchZoomLeft.scaleTo(this.state.scale / 1.25, scaleToOpts);
|
||||
}
|
||||
|
||||
@bind
|
||||
private onRotateClick() {
|
||||
private onRotateClick = () => {
|
||||
const { inputProcessorState } = this.props;
|
||||
if (!inputProcessorState) return;
|
||||
|
||||
@@ -170,8 +166,7 @@ export default class Output extends Component<Props, State> {
|
||||
this.props.onInputProcessorChange(newState);
|
||||
}
|
||||
|
||||
@bind
|
||||
private onScaleValueFocus() {
|
||||
private onScaleValueFocus = () => {
|
||||
this.setState({ editingScale: true }, () => {
|
||||
if (this.scaleInput) {
|
||||
// Firefox unfocuses the input straight away unless I force a style calculation here. I have
|
||||
@@ -182,13 +177,11 @@ export default class Output extends Component<Props, State> {
|
||||
});
|
||||
}
|
||||
|
||||
@bind
|
||||
private onScaleInputBlur() {
|
||||
private onScaleInputBlur = () => {
|
||||
this.setState({ editingScale: false });
|
||||
}
|
||||
|
||||
@bind
|
||||
private onScaleInputChanged(event: Event) {
|
||||
private onScaleInputChanged = (event: Event) => {
|
||||
const target = event.target as HTMLInputElement;
|
||||
const percent = parseFloat(target.value);
|
||||
if (isNaN(percent)) return;
|
||||
@@ -197,8 +190,7 @@ export default class Output extends Component<Props, State> {
|
||||
this.pinchZoomLeft.scaleTo(percent / 100, scaleToOpts);
|
||||
}
|
||||
|
||||
@bind
|
||||
private onPinchZoomLeftChange(event: Event) {
|
||||
private onPinchZoomLeftChange = (event: Event) => {
|
||||
if (!this.pinchZoomRight || !this.pinchZoomLeft) throw Error('Missing pinch-zoom element');
|
||||
this.setState({
|
||||
scale: this.pinchZoomLeft.scale,
|
||||
@@ -218,8 +210,7 @@ export default class Output extends Component<Props, State> {
|
||||
*
|
||||
* @param event Event to redirect
|
||||
*/
|
||||
@bind
|
||||
private onRetargetableEvent(event: Event) {
|
||||
private onRetargetableEvent = (event: Event) => {
|
||||
const targetEl = event.target as HTMLElement;
|
||||
if (!this.pinchZoomLeft) throw Error('Missing pinch-zoom element');
|
||||
// If the event is on the handle of the two-up, let it through,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { h, Component } from 'preact';
|
||||
|
||||
import { bind, Fileish } from '../../lib/initial-util';
|
||||
import { Fileish } from '../../lib/initial-util';
|
||||
import { blobToImg, drawableToImageData, blobToText } from '../../lib/util';
|
||||
import * as style from './style.module.scss';
|
||||
import Output from '../Output';
|
||||
@@ -254,8 +254,7 @@ export default class Compress extends Component<Props, State> {
|
||||
import('../../lib/sw-bridge').then(({ mainAppLoaded }) => mainAppLoaded());
|
||||
}
|
||||
|
||||
@bind
|
||||
private onMobileWidthChange() {
|
||||
private onMobileWidthChange = () => {
|
||||
this.setState({ mobileView: this.widthQuery.matches });
|
||||
}
|
||||
|
||||
@@ -344,8 +343,7 @@ export default class Compress extends Component<Props, State> {
|
||||
});
|
||||
}
|
||||
|
||||
@bind
|
||||
private async onInputProcessorChange(options: InputProcessorState): Promise<void> {
|
||||
private onInputProcessorChange = async (options: InputProcessorState): Promise<void> => {
|
||||
const source = this.state.source;
|
||||
if (!source) return;
|
||||
|
||||
@@ -396,8 +394,7 @@ export default class Compress extends Component<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
@bind
|
||||
private async updateFile(file: File | Fileish) {
|
||||
private updateFile = async (file: File | Fileish) => {
|
||||
const loadingCounter = this.state.loadingCounter + 1;
|
||||
// Either processor is good enough here.
|
||||
const processor = this.leftProcessor;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { h, Component } from 'preact';
|
||||
|
||||
import { bind, linkRef, Fileish } from '../../lib/initial-util';
|
||||
import { linkRef, Fileish } from '../../lib/initial-util';
|
||||
import '../custom-els/LoadingSpinner';
|
||||
|
||||
import logo from 'url:./imgs/logo.svg';
|
||||
@@ -67,13 +67,11 @@ export default class Intro extends Component<Props, State> {
|
||||
window.addEventListener('appinstalled', this.onAppInstalled);
|
||||
}
|
||||
|
||||
@bind
|
||||
private resetFileInput() {
|
||||
private resetFileInput = () => {
|
||||
this.fileInput!.value = '';
|
||||
}
|
||||
|
||||
@bind
|
||||
private onFileChange(event: Event): void {
|
||||
private onFileChange = (event: Event) => {
|
||||
const fileInput = event.target as HTMLInputElement;
|
||||
const file = fileInput.files && fileInput.files[0];
|
||||
if (!file) return;
|
||||
@@ -81,13 +79,11 @@ export default class Intro extends Component<Props, State> {
|
||||
this.props.onFile(file);
|
||||
}
|
||||
|
||||
@bind
|
||||
private onButtonClick() {
|
||||
private onButtonClick = () => {
|
||||
this.fileInput!.click();
|
||||
}
|
||||
|
||||
@bind
|
||||
private async onDemoClick(index: number, event: Event) {
|
||||
private onDemoClick = async (index: number, event: Event) => {
|
||||
try {
|
||||
this.setState({ fetchingDemoIndex: index });
|
||||
const demo = demos[index];
|
||||
@@ -104,8 +100,7 @@ export default class Intro extends Component<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
@bind
|
||||
private onBeforeInstallPromptEvent(event: BeforeInstallPromptEvent) {
|
||||
private onBeforeInstallPromptEvent = (event: BeforeInstallPromptEvent) => {
|
||||
// Don't show the mini-infobar on mobile
|
||||
event.preventDefault();
|
||||
|
||||
@@ -121,8 +116,7 @@ export default class Intro extends Component<Props, State> {
|
||||
ga('send', 'event', gaEventInfo);
|
||||
}
|
||||
|
||||
@bind
|
||||
private async onInstallClick(event: Event) {
|
||||
private onInstallClick = async (event: Event) => {
|
||||
// Get the deferred beforeinstallprompt event
|
||||
const beforeInstallEvent = this.state.beforeInstallEvent;
|
||||
// If there's no deferred prompt, bail.
|
||||
@@ -150,8 +144,7 @@ export default class Intro extends Component<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
@bind
|
||||
private onAppInstalled() {
|
||||
private onAppInstalled = () => {
|
||||
// We don't need the install button, if it's shown
|
||||
this.setState({ beforeInstallEvent: undefined });
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { h, Component } from 'preact';
|
||||
import * as style from './style.module.scss';
|
||||
import RangeInputElement from '../../custom-els/RangeInput';
|
||||
import '../../custom-els/RangeInput';
|
||||
import { linkRef, bind } from '../../lib/initial-util';
|
||||
import { linkRef } from '../../lib/initial-util';
|
||||
|
||||
interface Props extends JSX.HTMLAttributes {}
|
||||
interface State {}
|
||||
@@ -10,8 +10,7 @@ interface State {}
|
||||
export default class Range extends Component<Props, State> {
|
||||
rangeWc?: RangeInputElement;
|
||||
|
||||
@bind
|
||||
private onTextInput(event: Event) {
|
||||
private onTextInput = (event: Event) => {
|
||||
const input = event.target as HTMLInputElement;
|
||||
const value = input.value.trim();
|
||||
if (!value) return;
|
||||
|
||||
@@ -5,7 +5,7 @@ import FileSize from './FileSize';
|
||||
import { DownloadIcon, CopyAcrossIcon, CopyAcrossIconProps } from '../../lib/icons';
|
||||
import '../custom-els/LoadingSpinner';
|
||||
import { SourceImage } from '../compress';
|
||||
import { Fileish, bind } from '../../lib/initial-util';
|
||||
import { Fileish } from '../../lib/initial-util';
|
||||
|
||||
interface Props {
|
||||
loading: boolean;
|
||||
@@ -52,14 +52,12 @@ export default class Results extends Component<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
@bind
|
||||
private onCopyToOtherClick(event: Event) {
|
||||
private onCopyToOtherClick = (event: Event) => {
|
||||
event.preventDefault();
|
||||
this.props.onCopyToOtherClick();
|
||||
}
|
||||
|
||||
@bind
|
||||
onDownload() {
|
||||
onDownload = () => {
|
||||
// GA can’t do floats. So we round to ints. We're deliberately rounding to nearest kilobyte to
|
||||
// avoid cases where exact image sizes leak something interesting about the user.
|
||||
const before = Math.round(this.props.source!.file.size / 1024);
|
||||
|
||||
Reference in New Issue
Block a user