diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c11e6e07e..2cebe29d9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ - フロントエンドの読み込みサイズを軽量化しました - ほとんどの言語のハイライトは問題なく行えますが、互換性の問題により一部の言語が正常にハイライトできなくなる可能性があります。詳しくは https://shiki.style/references/engine-js-compat をご覧ください。 - Fix: チャットに動画ファイルを送付すると、動画の表示が崩れてしまい視聴出来ない問題を修正 +- Fix: アカウント依存かつ初期状態である設定値をサーバー同期しようとした際に正しくコンフリクト検出されない問題を修正 - Fix: "時計"ウィジェット(Clock)において、Transparent設定が有効でも、その背景が透過されない問題を修正 - Fix: 一定時間操作がなかったら動画プレイヤーのコントロールを隠すように - Fix: Twitchのクリップがプレイヤーで再生できない問題を修正 diff --git a/packages/frontend/src/preferences/manager.ts b/packages/frontend/src/preferences/manager.ts index ccb8ea0372..cede145e74 100644 --- a/packages/frontend/src/preferences/manager.ts +++ b/packages/frontend/src/preferences/manager.ts @@ -104,6 +104,8 @@ export function getInitialPrefValue(k: K): ValueOf { } } +// TODO: PreferencesManagerForGuest のような非ログイン専用のクラスを分離すれば$iのnullチェックやaccountがnullであるスコープのレコード挿入などが不要になり綺麗になるかもしれない +// NOTE: accountDependentな設定は初期状態であってもアカウントごとのスコープでレコードを作成しておかないと、サーバー同期する際に正しく動作しなくなる export class PreferencesManager { private storageProvider: StorageProvider; public profile: PreferencesProfile; @@ -139,11 +141,11 @@ export class PreferencesManager { // TODO: 定期的にクラウドの値をフェッチ } - private isAccountDependentKey(key: K): boolean { + private static isAccountDependentKey(key: K): boolean { return (PREF_DEF as PreferencesDefinition)[key].accountDependent === true; } - private isServerDependentKey(key: K): boolean { + private static isServerDependentKey(key: K): boolean { return (PREF_DEF as PreferencesDefinition)[key].serverDependent === true; } @@ -166,7 +168,7 @@ export class PreferencesManager { const record = this.getMatchedRecordOf(key); - if (parseScope(record[0]).account == null && this.isAccountDependentKey(key)) { + if (parseScope(record[0]).account == null && PreferencesManager.isAccountDependentKey(key)) { this.profile.preferences[key].push([makeScope({ server: host, account: $i!.id, @@ -175,7 +177,7 @@ export class PreferencesManager { return; } - if (parseScope(record[0]).server == null && this.isServerDependentKey(key)) { + if (parseScope(record[0]).server == null && PreferencesManager.isServerDependentKey(key)) { this.profile.preferences[key].push([makeScope({ server: host, }), v, {}]); @@ -276,7 +278,19 @@ export class PreferencesManager { public static newProfile(): PreferencesProfile { const data = {} as PreferencesProfile['preferences']; for (const key in PREF_DEF) { - data[key] = [[makeScope({}), getInitialPrefValue(key as keyof typeof PREF_DEF), {}]]; + const v = getInitialPrefValue(key as keyof typeof PREF_DEF); + if (PreferencesManager.isAccountDependentKey(key as keyof typeof PREF_DEF)) { + data[key] = $i ? [[makeScope({}), v, {}], [makeScope({ + server: host, + account: $i.id, + }), v, {}]] : [[makeScope({}), v, {}]]; + } else if (PreferencesManager.isServerDependentKey(key as keyof typeof PREF_DEF)) { + data[key] = [[makeScope({ + server: host, + }), v, {}]]; + } else { + data[key] = [[makeScope({}), v, {}]]; + } } return { id: uuid(), @@ -293,18 +307,36 @@ export class PreferencesManager { for (const key in PREF_DEF) { const records = profileLike.preferences[key]; if (records == null || records.length === 0) { - data[key] = [[makeScope({}), getInitialPrefValue(key as keyof typeof PREF_DEF), {}]]; + const v = getInitialPrefValue(key as keyof typeof PREF_DEF); + if (PreferencesManager.isAccountDependentKey(key as keyof typeof PREF_DEF)) { + data[key] = $i ? [[makeScope({}), v, {}], [makeScope({ + server: host, + account: $i.id, + }), v, {}]] : [[makeScope({}), v, {}]]; + } else if (PreferencesManager.isServerDependentKey(key as keyof typeof PREF_DEF)) { + data[key] = [[makeScope({ + server: host, + }), v, {}]]; + } else { + data[key] = [[makeScope({}), v, {}]]; + } continue; } else { - data[key] = records; - - // alpha段階ではmetaが無かったのでマイグレート - // TODO: そのうち消す - for (const record of data[key] as any[][]) { - if (record.length === 2) { - record.push({}); - } + if ($i && PreferencesManager.isAccountDependentKey(key as keyof typeof PREF_DEF) && !records.some(([scope]) => parseScope(scope).server === host && parseScope(scope).account === $i!.id)) { + data[key] = records.concat([[makeScope({ + server: host, + account: $i.id, + }), getInitialPrefValue(key as keyof typeof PREF_DEF), {}]]); + continue; } + if ($i && PreferencesManager.isServerDependentKey(key as keyof typeof PREF_DEF) && !records.some(([scope]) => parseScope(scope).server === host)) { + data[key] = records.concat([[makeScope({ + server: host, + }), getInitialPrefValue(key as keyof typeof PREF_DEF), {}]]); + continue; + } + + data[key] = records; } } @@ -342,7 +374,7 @@ export class PreferencesManager { public setAccountOverride(key: K) { if ($i == null) return; - if (this.isAccountDependentKey(key)) throw new Error('already account-dependent'); + if (PreferencesManager.isAccountDependentKey(key)) throw new Error('already account-dependent'); if (this.isAccountOverrided(key)) return; const records = this.profile.preferences[key]; @@ -356,7 +388,7 @@ export class PreferencesManager { public clearAccountOverride(key: K) { if ($i == null) return; - if (this.isAccountDependentKey(key)) throw new Error('cannot clear override for this account-dependent property'); + if (PreferencesManager.isAccountDependentKey(key)) throw new Error('cannot clear override for this account-dependent property'); const records = this.profile.preferences[key];