Fix "discard changes" appearing on deck options (#3689)

* patch original config after a preset is selected for the first time

* update comment
This commit is contained in:
llama 2025-01-07 22:41:52 +08:00 committed by GitHub
parent d01d83e2c6
commit 769f302ea8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -76,6 +76,10 @@ export class DeckOptionsState {
private removedConfigs: DeckOptionsId[] = []; private removedConfigs: DeckOptionsId[] = [];
private schemaModified: boolean; private schemaModified: boolean;
private _presetAssignmentsChanged = false; private _presetAssignmentsChanged = false;
// tracks presets that have already been
// selected/loaded once, via their ids.
// needed for proper change detection
private loadedPresets: Set<DeckConfig["id"]> = new Set();
constructor(targetDeckId: DeckOptionsId, data: DeckConfigsForUpdate) { constructor(targetDeckId: DeckOptionsId, data: DeckConfigsForUpdate) {
this.targetDeckId = targetDeckId; this.targetDeckId = targetDeckId;
@ -122,17 +126,46 @@ export class DeckOptionsState {
this.currentConfig.subscribe((val) => this.onCurrentConfigChanged(val)); this.currentConfig.subscribe((val) => this.onCurrentConfigChanged(val));
this.currentAuxData.subscribe((val) => this.onCurrentAuxDataChanged(val)); this.currentAuxData.subscribe((val) => this.onCurrentAuxDataChanged(val));
// no need to call markCurrentPresetAsLoaded here
// since any changes components make will be before
// originalConfigsResolve is called on mount
this.loadedPresets.add(this.configs[this.selectedIdx].config.id);
// Must be resolved after all components are mounted, as some components // Must be resolved after all components are mounted, as some components
// may modify the config during their initialization. // may modify the config during their initialization.
[this.originalConfigsPromise, this.originalConfigsResolve] = promiseWithResolver<AllConfigs>(); [this.originalConfigsPromise, this.originalConfigsResolve] = promiseWithResolver<AllConfigs>();
} }
/**
* Patch the original config if components change it after preset select
* `EasyDays` and `DateInput` both do this when their settings are blank
* We only need to patch when the preset is first selected.
*/
async markCurrentPresetAsLoaded(): Promise<void> {
const id = this.configs[this.selectedIdx].config.id;
const loaded = this.loadedPresets;
// ignore new presets with an id of 0
if (id && !loaded.has(id)) {
// preset was loaded for the first time, patch original config
loaded.add(id);
const original = await this.originalConfigsPromise;
// can't index into `original` with `this.selectedIdx` due to `sortConfigs`
const idx = original.configs.findIndex((conf) => conf.id === id);
// this should never be -1, since new presets are excluded, and removed presets aren't considered
if (idx !== -1) {
original.configs[idx] = cloneDeep(this.configs[this.selectedIdx].config);
}
}
}
setCurrentIndex(index: number): void { setCurrentIndex(index: number): void {
this.selectedIdx = index; this.selectedIdx = index;
this._presetAssignmentsChanged = true; this._presetAssignmentsChanged = true;
this.updateCurrentConfig(); this.updateCurrentConfig();
// use counts have changed // use counts have changed
this.updateConfigList(); this.updateConfigList();
// wait for components that modify config on preset select
tick().then(() => this.markCurrentPresetAsLoaded());
} }
getCurrentName(): string { getCurrentName(): string {
@ -203,10 +236,8 @@ export class DeckOptionsState {
this.schemaModified = true; this.schemaModified = true;
} }
this.configs.splice(this.selectedIdx, 1); this.configs.splice(this.selectedIdx, 1);
this.selectedIdx = Math.max(0, this.selectedIdx - 1); const newIdx = Math.max(0, this.selectedIdx - 1);
this._presetAssignmentsChanged = true; this.setCurrentIndex(newIdx);
this.updateCurrentConfig();
this.updateConfigList();
} }
dataForSaving( dataForSaving(