More work on compress

This commit is contained in:
Jake Archibald
2020-11-09 12:14:16 +00:00
parent c17b5c36c6
commit 9111aa89ae
4 changed files with 86 additions and 19 deletions

View File

@@ -14,7 +14,7 @@ import 'shared/initial-app/custom-els/loading-spinner';
const ROUTE_EDITOR = '/editor'; const ROUTE_EDITOR = '/editor';
//const compressPromise = import('client/lazy-app/Compress'); const compressPromise = import('client/lazy-app/Compress');
const swBridgePromise = import('client/lazy-app/sw-bridge'); const swBridgePromise = import('client/lazy-app/sw-bridge');
function back() { function back() {
@@ -27,7 +27,7 @@ interface State {
awaitingShareTarget: boolean; awaitingShareTarget: boolean;
file?: File; file?: File;
isEditorOpen: Boolean; isEditorOpen: Boolean;
Compress?: undefined; // typeof import('../compress').default; Compress?: typeof import('client/lazy-app/Compress').default;
} }
export default class App extends Component<Props, State> { export default class App extends Component<Props, State> {
@@ -45,13 +45,13 @@ export default class App extends Component<Props, State> {
constructor() { constructor() {
super(); super();
/*compressPromise compressPromise
.then((module) => { .then((module) => {
this.setState({ Compress: module.default }); this.setState({ Compress: module.default });
}) })
.catch(() => { .catch(() => {
this.showSnack('Failed to load app'); this.showSnack('Failed to load app');
});*/ });
swBridgePromise.then(async ({ offliner, getSharedImage }) => { swBridgePromise.then(async ({ offliner, getSharedImage }) => {
offliner(this.showSnack); offliner(this.showSnack);
@@ -123,9 +123,9 @@ export default class App extends Component<Props, State> {
{showSpinner ? ( {showSpinner ? (
<loading-spinner class={style.appLoader} /> <loading-spinner class={style.appLoader} />
) : isEditorOpen ? ( ) : isEditorOpen ? (
Compress && Compress && (
//<Compress file={file!} showSnack={this.showSnack} onBack={back} /> <Compress file={file!} showSnack={this.showSnack} onBack={back} />
'TODO: uncomment above' )
) : ( ) : (
<Intro onFile={this.onIntroPickFile} showSnack={this.showSnack} /> <Intro onFile={this.onIntroPickFile} showSnack={this.showSnack} />
)} )}

View File

@@ -19,11 +19,13 @@ import {
encoderMap, encoderMap,
defaultPreprocessorState, defaultPreprocessorState,
defaultProcessorState, defaultProcessorState,
EncoderType,
EncoderOptions,
} from '../feature-meta'; } from '../feature-meta';
import Output from '../Output'; import Output from '../Output';
import Options from '../Options'; import Options from '../Options';
import ResultCache from './result-cache'; import ResultCache from './result-cache';
import { cleanMerge, cleanSet } from '../../lib/clean-modify'; import { cleanMerge, cleanSet } from '../util/clean-modify';
import './custom-els/MultiPanel'; import './custom-els/MultiPanel';
import Results from '../results'; import Results from '../results';
import { ExpandIcon, CopyAcrossIconProps } from '../../lib/icons'; import { ExpandIcon, CopyAcrossIconProps } from '../../lib/icons';
@@ -31,6 +33,8 @@ import SnackBarElement from '../../lib/SnackBar';
import WorkerBridge from '../worker-bridge'; import WorkerBridge from '../worker-bridge';
import { resize } from 'features/processors/resize/client'; import { resize } from 'features/processors/resize/client';
type OutputType = EncoderType | 'identity';
export interface SourceImage { export interface SourceImage {
file: File; file: File;
decoded: ImageData; decoded: ImageData;
@@ -248,7 +252,6 @@ export default class Compress extends Component<Props, State> {
}; };
private readonly encodeCache = new ResultCache(); private readonly encodeCache = new ResultCache();
// YOU ARE HERE
private readonly leftWorkerBridge = new WorkerBridge(); private readonly leftWorkerBridge = new WorkerBridge();
private readonly rightWorkerBridge = new WorkerBridge(); private readonly rightWorkerBridge = new WorkerBridge();
// For debouncing calls to updateImage for each side. // For debouncing calls to updateImage for each side.
@@ -262,34 +265,36 @@ 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/sw-bridge').then(({ mainAppLoaded }) => mainAppLoaded()); import('../sw-bridge').then(({ mainAppLoaded }) => mainAppLoaded());
} }
private onMobileWidthChange = () => { private onMobileWidthChange = () => {
this.setState({ mobileView: this.widthQuery.matches }); this.setState({ mobileView: this.widthQuery.matches });
}; };
private onEncoderTypeChange(index: 0 | 1, newType: EncoderType): void { private onEncoderTypeChange(index: 0 | 1, newType: OutputType): void {
this.setState({ this.setState({
sides: cleanSet( sides: cleanSet(
this.state.sides, this.state.sides,
`${index}.latestSettings.encoderState`, `${index}.latestSettings.encoderState`,
{ newType === 'identity'
type: newType, ? undefined
options: encoderMap[newType].defaultOptions, : {
}, type: newType,
options: encoderMap[newType].meta.defaultOptions,
},
), ),
}); });
} }
private onPreprocessorOptionsChange( private onProcessorOptionsChange(
index: 0 | 1, index: 0 | 1,
options: PreprocessorState, options: ProcessorState,
): void { ): void {
this.setState({ this.setState({
sides: cleanSet( sides: cleanSet(
this.state.sides, this.state.sides,
`${index}.latestSettings.preprocessorState`, `${index}.latestSettings.processorState`,
options, options,
), ),
}); });
@@ -654,7 +659,7 @@ export default class Compress extends Component<Props, State> {
this, this,
index as 0 | 1, index as 0 | 1,
)} )}
onPreprocessorOptionsChange={this.onPreprocessorOptionsChange.bind( onPreprocessorOptionsChange={this.onProcessorOptionsChange.bind(
this, this,
index as 0 | 1, index as 0 | 1,
)} )}

View File

@@ -0,0 +1,62 @@
function cleanSetOrMerge<A extends any[] | object>(
source: A,
keys: string | number | string[],
toSetOrMerge: any[] | object,
merge: boolean,
): A {
const splitKeys = Array.isArray(keys) ? keys : ('' + keys).split('.');
// Going off road in terms of types, otherwise TypeScript doesn't like the access-by-index.
// The assumptions in this code break if the object contains things which aren't arrays or
// plain objects.
let last = copy(source) as any;
const newObject = last;
const lastIndex = splitKeys.length - 1;
for (const [i, key] of splitKeys.entries()) {
if (i !== lastIndex) {
// Copy everything along the path.
last = last[key] = copy(last[key]);
} else {
// Merge or set.
last[key] = merge
? Object.assign(copy(last[key]), toSetOrMerge)
: toSetOrMerge;
}
}
return newObject;
}
function copy<A extends any[] | object>(source: A): A {
// Some type cheating here, as TypeScript can't infer between generic types.
if (Array.isArray(source)) return [...source] as any;
return { ...(source as any) };
}
/**
* @param source Object to copy from.
* @param keys Path to modify, eg "foo.bar.baz".
* @param toMerge A value to merge into the value at the path.
*/
export function cleanMerge<A extends any[] | object>(
source: A,
keys: string | number | string[],
toMerge: any[] | object,
): A {
return cleanSetOrMerge(source, keys, toMerge, true);
}
/**
* @param source Object to copy from.
* @param keys Path to modify, eg "foo.bar.baz".
* @param newValue A value to set at the path.
*/
export function cleanSet<A extends any[] | object>(
source: A,
keys: string | number | string[],
newValue: any,
): A {
return cleanSetOrMerge(source, keys, newValue, false);
}