diff options
| author | syuilo <4439005+syuilo@users.noreply.github.com> | 2025-05-31 14:15:40 +0900 |
|---|---|---|
| committer | syuilo <4439005+syuilo@users.noreply.github.com> | 2025-05-31 14:15:40 +0900 |
| commit | 743995e4695af1ade073172f87fc91f1c9b37ba8 (patch) | |
| tree | 121e0208eda42498b6b5f3565b11a47bcdcfb1db /packages/frontend/src/preferences/manager.ts | |
| parent | enhance(frontend): 設定の同期をオンにするときに競合したと... (diff) | |
| download | misskey-743995e4695af1ade073172f87fc91f1c9b37ba8.tar.gz misskey-743995e4695af1ade073172f87fc91f1c9b37ba8.tar.bz2 misskey-743995e4695af1ade073172f87fc91f1c9b37ba8.zip | |
enhance(frontend): make pref sync more smart
Diffstat (limited to 'packages/frontend/src/preferences/manager.ts')
| -rw-r--r-- | packages/frontend/src/preferences/manager.ts | 50 |
1 files changed, 38 insertions, 12 deletions
diff --git a/packages/frontend/src/preferences/manager.ts b/packages/frontend/src/preferences/manager.ts index 016e1ad85b..ccb8ea0372 100644 --- a/packages/frontend/src/preferences/manager.ts +++ b/packages/frontend/src/preferences/manager.ts @@ -377,14 +377,12 @@ export class PreferencesManager { public async enableSync<K extends keyof PREF>(key: K): Promise<{ enabled: boolean; } | null> { if (this.isSyncEnabled(key)) return Promise.resolve(null); - const record = this.getMatchedRecordOf(key); - - const existing = await this.storageProvider.cloudGet({ key, scope: record[0] }); - if (existing != null && !deepEqual(existing.value, record[1])) { + // undefined ... cancel + async function resolveConflict(local: ValueOf<K>, remote: ValueOf<K>): Promise<ValueOf<K> | undefined> { const merge = (PREF_DEF as PreferencesDefinition)[key].mergeStrategy; let mergedValue: ValueOf<K> | undefined = undefined; // null と区別したいため try { - if (merge != null) mergedValue = merge(record[1], existing.value); + if (merge != null) mergedValue = merge(local, remote); } catch (err) { // nop } @@ -406,23 +404,51 @@ export class PreferencesManager { }], default: mergedValue !== undefined ? 'merge' : 'remote', }); - if (canceled || choice == null) return { enabled: false }; + if (canceled || choice == null) return undefined; if (choice === 'remote') { - this.commit(key, existing.value); + return remote; } else if (choice === 'local') { - // nop + return local; } else if (choice === 'merge') { - this.commit(key, mergedValue!); + return mergedValue!; } } + const record = this.getMatchedRecordOf(key); + + let newValue = record[1]; + + const existing = await this.storageProvider.cloudGet({ key, scope: record[0] }); + if (existing != null && !deepEqual(record[1], existing.value)) { + const resolvedValue = await resolveConflict(record[1], existing.value); + if (resolvedValue === undefined) return { enabled: false }; // canceled + newValue = resolvedValue; + } + + this.commit(key, newValue); + + const done = os.waiting(); + + try { + await this.storageProvider.cloudSet({ key, scope: record[0], value: newValue }); + } catch (err) { + done(); + + os.alert({ + type: 'error', + title: i18n.ts.somethingHappened, + text: err, + }); + + return { enabled: false }; + } + + done({ success: true }); + record[2].sync = true; this.save(); - // awaitの必要性は無い - this.storageProvider.cloudSet({ key, scope: record[0], value: this.s[key] }); - return { enabled: true }; } |