1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-05-15 01:05:42 +02:00

enhance(frontend): preferenceのタブ間同期にBroadcast Channelを使用するように (#16819)

* enhance(frontend): preferenceのタブ間同期にBroadcast Channelを使用するように

* fix

* refactor: EventEmitterをextendする形に変更
This commit is contained in:
かっこかり
2025-11-24 16:52:46 +09:00
committed by GitHub
parent 25afb5d279
commit 2ee04860fb
3 changed files with 59 additions and 28 deletions

View File

@@ -3,6 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { BroadcastChannel } from 'broadcast-channel';
import type { StorageProvider } from '@/preferences/manager.js';
import { cloudBackup } from '@/preferences/utility.js';
import { miLocalStorage } from '@/local-storage.js';
@@ -12,6 +13,7 @@ import { $i } from '@/i.js';
import { misskeyApi } from '@/utility/misskey-api.js';
import { TAB_ID } from '@/tab-id.js';
// クラウド同期用グループ名
const syncGroup = 'default';
const io: StorageProvider = {
@@ -26,7 +28,6 @@ const io: StorageProvider = {
save: (ctx) => {
miLocalStorage.setItem('preferences', JSON.stringify(ctx.profile));
miLocalStorage.setItem('latestPreferencesUpdate', `${TAB_ID}/${Date.now()}`);
},
cloudGet: async (ctx) => {
@@ -99,33 +100,47 @@ const io: StorageProvider = {
export const prefer = new PreferencesManager(io, $i);
let latestSyncedAt = Date.now();
//#region タブ間同期
let latestPreferencesUpdate: {
tabId: string;
timestamp: number;
} | null = null;
function syncBetweenTabs() {
const latest = miLocalStorage.getItem('latestPreferencesUpdate');
if (latest == null) return;
const preferencesChannel = new BroadcastChannel<{
type: 'preferencesUpdate';
tabId: string;
timestamp: number;
}>('preferences');
const latestTab = latest.split('/')[0];
const latestAt = parseInt(latest.split('/')[1]);
if (latestTab === TAB_ID) return;
if (latestAt <= latestSyncedAt) return;
prefer.reloadProfile();
latestSyncedAt = Date.now();
if (_DEV_) console.log('prefer:synced');
}
window.setInterval(syncBetweenTabs, 5000);
window.document.addEventListener('visibilitychange', () => {
if (window.document.visibilityState === 'visible') {
syncBetweenTabs();
}
prefer.on('committed', () => {
latestPreferencesUpdate = {
tabId: TAB_ID,
timestamp: Date.now(),
};
preferencesChannel.postMessage({
type: 'preferencesUpdate',
tabId: TAB_ID,
timestamp: latestPreferencesUpdate.timestamp,
});
});
preferencesChannel.addEventListener('message', (msg) => {
if (msg.type === 'preferencesUpdate') {
if (msg.tabId === TAB_ID) return;
if (latestPreferencesUpdate != null) {
if (msg.timestamp <= latestPreferencesUpdate.timestamp) return;
}
prefer.reloadProfile();
if (_DEV_) console.log('prefer:received update from other tab');
latestPreferencesUpdate = {
tabId: msg.tabId,
timestamp: msg.timestamp,
};
}
});
//#endregion
//#region 定期クラウドバックアップ
let latestBackupAt = 0;
window.setInterval(() => {
@@ -138,6 +153,7 @@ window.setInterval(() => {
latestBackupAt = Date.now();
});
}, 1000 * 60 * 3);
//#endregion
if (_DEV_) {
(window as any).prefer = prefer;