mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-11 16:26:20 +00:00
Merge pull request #1359 from harsh26shah03/save-and-import-side-settings
Feat : Save and import side settings
This commit is contained in:
@@ -17,7 +17,7 @@ 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 { SwapIcon } from 'client/lazy-app/icons';
|
import { ImportIcon, SaveIcon, SwapIcon } from 'client/lazy-app/icons';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
index: 0 | 1;
|
index: 0 | 1;
|
||||||
@@ -29,10 +29,14 @@ interface Props {
|
|||||||
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;
|
onCopyToOtherSideClick(index: 0 | 1): void;
|
||||||
|
onSaveSideSettingsClick(index: 0 | 1): void;
|
||||||
|
onImportSideSettingsClick(index: 0 | 1): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
supportedEncoderMap?: PartialButNotUndefined<typeof encoderMap>;
|
supportedEncoderMap?: PartialButNotUndefined<typeof encoderMap>;
|
||||||
|
leftSideSettings?: string | null;
|
||||||
|
rightSideSettings?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
type PartialButNotUndefined<T> = {
|
type PartialButNotUndefined<T> = {
|
||||||
@@ -60,6 +64,8 @@ const supportedEncoderMapP: Promise<PartialButNotUndefined<typeof encoderMap>> =
|
|||||||
export default class Options extends Component<Props, State> {
|
export default class Options extends Component<Props, State> {
|
||||||
state: State = {
|
state: State = {
|
||||||
supportedEncoderMap: undefined,
|
supportedEncoderMap: undefined,
|
||||||
|
leftSideSettings: localStorage.getItem('leftSideSettings'),
|
||||||
|
rightSideSettings: localStorage.getItem('rightSideSettings'),
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -69,6 +75,29 @@ export default class Options extends Component<Props, State> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private setLeftSideSettings = () => {
|
||||||
|
this.setState({
|
||||||
|
leftSideSettings: localStorage.getItem('leftSideSettings'),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
private setRightSideSettings = () => {
|
||||||
|
this.setState({
|
||||||
|
rightSideSettings: localStorage.getItem('rightSideSettings'),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount(): void {
|
||||||
|
// Changing the state when side setting is stored in localstorage
|
||||||
|
window.addEventListener('leftSideSettings', this.setLeftSideSettings);
|
||||||
|
window.addEventListener('rightSideSettings', this.setRightSideSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount(): void {
|
||||||
|
window.removeEventListener('leftSideSettings', this.setLeftSideSettings);
|
||||||
|
window.removeEventListener('removeSideSettings', this.setRightSideSettings);
|
||||||
|
}
|
||||||
|
|
||||||
private onEncoderTypeChange = (event: Event) => {
|
private onEncoderTypeChange = (event: Event) => {
|
||||||
const el = event.currentTarget as HTMLSelectElement;
|
const el = event.currentTarget as HTMLSelectElement;
|
||||||
|
|
||||||
@@ -110,6 +139,14 @@ export default class Options extends Component<Props, State> {
|
|||||||
this.props.onCopyToOtherSideClick(this.props.index);
|
this.props.onCopyToOtherSideClick(this.props.index);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private onSaveSideSettingClick = () => {
|
||||||
|
this.props.onSaveSideSettingsClick(this.props.index);
|
||||||
|
};
|
||||||
|
|
||||||
|
private onImportSideSettingsClick = () => {
|
||||||
|
this.props.onImportSideSettingsClick(this.props.index);
|
||||||
|
};
|
||||||
|
|
||||||
render(
|
render(
|
||||||
{ source, encoderState, processorState }: Props,
|
{ source, encoderState, processorState }: Props,
|
||||||
{ supportedEncoderMap }: State,
|
{ supportedEncoderMap }: State,
|
||||||
@@ -139,6 +176,30 @@ export default class Options extends Component<Props, State> {
|
|||||||
>
|
>
|
||||||
<SwapIcon />
|
<SwapIcon />
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
class={style.saveButton}
|
||||||
|
title="Save side settings"
|
||||||
|
onClick={this.onSaveSideSettingClick}
|
||||||
|
>
|
||||||
|
<SaveIcon />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class={
|
||||||
|
style.importButton +
|
||||||
|
' ' +
|
||||||
|
(!this.state.leftSideSettings && this.props.index === 0
|
||||||
|
? style.buttonOpacity
|
||||||
|
: '') +
|
||||||
|
' ' +
|
||||||
|
(!this.state.rightSideSettings && this.props.index === 1
|
||||||
|
? style.buttonOpacity
|
||||||
|
: '')
|
||||||
|
}
|
||||||
|
title="Import saved side settings"
|
||||||
|
onClick={this.onImportSideSettingsClick}
|
||||||
|
>
|
||||||
|
<ImportIcon />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</h3>
|
</h3>
|
||||||
<label class={style.sectionEnabler}>
|
<label class={style.sectionEnabler}>
|
||||||
|
|||||||
@@ -119,3 +119,20 @@
|
|||||||
fill: var(--header-text-color);
|
fill: var(--header-text-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.save-button,
|
||||||
|
.import-button {
|
||||||
|
composes: title-button;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
stroke: var(--header-text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-opacity {
|
||||||
|
pointer-events: none;
|
||||||
|
cursor: not-allowed;
|
||||||
|
svg {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -281,24 +281,35 @@ export default class Compress extends Component<Props, State> {
|
|||||||
source: undefined,
|
source: undefined,
|
||||||
loading: false,
|
loading: false,
|
||||||
preprocessorState: defaultPreprocessorState,
|
preprocessorState: defaultPreprocessorState,
|
||||||
|
// Tasking catched side settings if available otherwise taking default settings
|
||||||
sides: [
|
sides: [
|
||||||
{
|
localStorage.getItem('leftSideSettings')
|
||||||
latestSettings: {
|
? {
|
||||||
processorState: defaultProcessorState,
|
...JSON.parse(localStorage.getItem('leftSideSettings') as string),
|
||||||
encoderState: undefined,
|
loading: false,
|
||||||
},
|
}
|
||||||
loading: false,
|
: {
|
||||||
},
|
latestSettings: {
|
||||||
{
|
processorState: defaultProcessorState,
|
||||||
latestSettings: {
|
encoderState: undefined,
|
||||||
processorState: defaultProcessorState,
|
},
|
||||||
encoderState: {
|
loading: false,
|
||||||
type: 'mozJPEG',
|
},
|
||||||
options: encoderMap.mozJPEG.meta.defaultOptions,
|
localStorage.getItem('rightSideSettings')
|
||||||
|
? {
|
||||||
|
...JSON.parse(localStorage.getItem('rightSideSettings') as string),
|
||||||
|
loading: false,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
latestSettings: {
|
||||||
|
processorState: defaultProcessorState,
|
||||||
|
encoderState: {
|
||||||
|
type: 'mozJPEG',
|
||||||
|
options: encoderMap.mozJPEG.meta.defaultOptions,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
loading: false,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
loading: false,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
mobileView: this.widthQuery.matches,
|
mobileView: this.widthQuery.matches,
|
||||||
};
|
};
|
||||||
@@ -428,6 +439,99 @@ export default class Compress extends Component<Props, State> {
|
|||||||
sides: cleanSet(this.state.sides, otherIndex, oldSettings),
|
sides: cleanSet(this.state.sides, otherIndex, oldSettings),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* This function saves encodedSettings and latestSettings of
|
||||||
|
* particular side in browser local storage
|
||||||
|
* @param index : (0|1)
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
private onSaveSideSettingsClick = async (index: 0 | 1) => {
|
||||||
|
if (index === 0) {
|
||||||
|
const leftSideSettings = JSON.stringify({
|
||||||
|
encodedSettings: this.state.sides[index].encodedSettings,
|
||||||
|
latestSettings: this.state.sides[index].latestSettings,
|
||||||
|
});
|
||||||
|
localStorage.setItem('leftSideSettings', leftSideSettings);
|
||||||
|
// Firing an event when we save side settings in localstorage
|
||||||
|
window.dispatchEvent(new CustomEvent('leftSideSettings'));
|
||||||
|
await this.props.showSnack('Left side settings saved', {
|
||||||
|
timeout: 1500,
|
||||||
|
actions: ['dismiss'],
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index === 1) {
|
||||||
|
const rightSideSettings = JSON.stringify({
|
||||||
|
encodedSettings: this.state.sides[index].encodedSettings,
|
||||||
|
latestSettings: this.state.sides[index].latestSettings,
|
||||||
|
});
|
||||||
|
localStorage.setItem('rightSideSettings', rightSideSettings);
|
||||||
|
// Firing an event when we save side settings in localstorage
|
||||||
|
window.dispatchEvent(new CustomEvent('rightSideSettings'));
|
||||||
|
await this.props.showSnack('Right side settings saved', {
|
||||||
|
timeout: 1500,
|
||||||
|
actions: ['dismiss'],
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function sets the side state with catched localstorage
|
||||||
|
* value as per side index provided
|
||||||
|
* @param index : (0|1)
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
private onImportSideSettingsClick = async (index: 0 | 1) => {
|
||||||
|
const leftSideSettingsString = localStorage.getItem('leftSideSettings');
|
||||||
|
const rightSideSettingsString = localStorage.getItem('rightSideSettings');
|
||||||
|
|
||||||
|
if (index === 0 && leftSideSettingsString) {
|
||||||
|
const oldLeftSideSettings = this.state.sides[index];
|
||||||
|
const newLeftSideSettings = {
|
||||||
|
...this.state.sides[index],
|
||||||
|
...JSON.parse(leftSideSettingsString),
|
||||||
|
};
|
||||||
|
this.setState({
|
||||||
|
sides: cleanSet(this.state.sides, index, newLeftSideSettings),
|
||||||
|
});
|
||||||
|
const result = await this.props.showSnack('Left side settings imported', {
|
||||||
|
timeout: 3000,
|
||||||
|
actions: ['undo', 'dismiss'],
|
||||||
|
});
|
||||||
|
if (result === 'undo') {
|
||||||
|
this.setState({
|
||||||
|
sides: cleanSet(this.state.sides, index, oldLeftSideSettings),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index === 1 && rightSideSettingsString) {
|
||||||
|
const oldRightSideSettings = this.state.sides[index];
|
||||||
|
const newRightSideSettings = {
|
||||||
|
...this.state.sides[index],
|
||||||
|
...JSON.parse(rightSideSettingsString),
|
||||||
|
};
|
||||||
|
this.setState({
|
||||||
|
sides: cleanSet(this.state.sides, index, newRightSideSettings),
|
||||||
|
});
|
||||||
|
const result = await this.props.showSnack(
|
||||||
|
'Right side settings imported',
|
||||||
|
{
|
||||||
|
timeout: 3000,
|
||||||
|
actions: ['undo', 'dismiss'],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result === 'undo') {
|
||||||
|
this.setState({
|
||||||
|
sides: cleanSet(this.state.sides, index, oldRightSideSettings),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private onPreprocessorChange = async (
|
private onPreprocessorChange = async (
|
||||||
preprocessorState: PreprocessorState,
|
preprocessorState: PreprocessorState,
|
||||||
@@ -829,6 +933,8 @@ export default class Compress extends Component<Props, State> {
|
|||||||
onEncoderOptionsChange={this.onEncoderOptionsChange}
|
onEncoderOptionsChange={this.onEncoderOptionsChange}
|
||||||
onProcessorOptionsChange={this.onProcessorOptionsChange}
|
onProcessorOptionsChange={this.onProcessorOptionsChange}
|
||||||
onCopyToOtherSideClick={this.onCopyToOtherClick}
|
onCopyToOtherSideClick={this.onCopyToOtherClick}
|
||||||
|
onSaveSideSettingsClick={this.onSaveSideSettingsClick}
|
||||||
|
onImportSideSettingsClick={this.onImportSideSettingsClick}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|||||||
@@ -97,3 +97,31 @@ export const SwapIcon = () => (
|
|||||||
<path d="M5.5 3.6v6.8L2.1 7l3.4-3.4M7 0L0 7l7 7V0zm4 0v14l7-7-7-7z" />
|
<path d="M5.5 3.6v6.8L2.1 7l3.4-3.4M7 0L0 7l7 7V0zm4 0v14l7-7-7-7z" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const SaveIcon = () => (
|
||||||
|
<svg viewBox="0 0 24 24">
|
||||||
|
<g
|
||||||
|
fill="none"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
>
|
||||||
|
<path d="M12.501 20.93c-.866.25-1.914-.166-2.176-1.247a1.724 1.724 0 0 0-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 0 0-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 0 0 1.066-2.573c-.94-1.543.826-3.31 2.37-2.37c1 .608 2.296.07 2.572-1.065c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.074.26 1.49 1.296 1.252 2.158M19 22v-6m3 3l-3-3l-3 3" />
|
||||||
|
<path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0-6 0" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const ImportIcon = () => (
|
||||||
|
<svg viewBox="0 0 24 24">
|
||||||
|
<g
|
||||||
|
fill="none"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
>
|
||||||
|
<path d="M12.52 20.924c-.87.262-1.93-.152-2.195-1.241a1.724 1.724 0 0 0-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 0 0-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 0 0 1.066-2.573c-.94-1.543.826-3.31 2.37-2.37c1 .608 2.296.07 2.572-1.065c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.088.264 1.502 1.323 1.242 2.192M19 16v6m3-3l-3 3l-3-3" />
|
||||||
|
<path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0-6 0" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user