Merge pull request #1359 from harsh26shah03/save-and-import-side-settings

Feat : Save and import side settings
This commit is contained in:
Adam Argyle
2023-04-04 15:41:45 -07:00
committed by GitHub
4 changed files with 229 additions and 17 deletions

View File

@@ -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}>

View File

@@ -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;
}
}

View File

@@ -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}
/> />
)); ));

View File

@@ -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>
);