mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-07-26 12:08:15 +00:00
Merge PR #11: extract tab management logic into independent module
3-way merge of Kaia-Alenia's tab-manager refactor (PR #11) onto current main (v2.4.3). Only the tab-related service-worker listeners move out of background.js into extension/modules/tab-manager.js via initTabManager({...}) dependency injection; all other recent main changes are preserved untouched. Behavior-preserving; listeners still register synchronously at top level. The unrelated website/assets/NewLogoIcon_64.webp change from the PR was excluded to keep main clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+17
-66
@@ -2,6 +2,7 @@ import { EVENTS, PROTOCOL_VERSION, OFFICIAL_SERVER_URL, OFFICIAL_SERVER_TOKEN, E
|
||||
import { generateUsername } from './shared/names.js';
|
||||
import { loadLocale, getMessage, getSystemLanguage } from './i18n.js';
|
||||
import { sameEpisode } from './episode-utils.js';
|
||||
import { initTabManager } from './modules/tab-manager.js';
|
||||
|
||||
// --- Uninstall URL Initialization ---
|
||||
let uninstallURLInitPromise = null;
|
||||
@@ -1922,72 +1923,22 @@ async function handleAsyncMessage(message, sender, sendResponse) {
|
||||
}
|
||||
}
|
||||
|
||||
chrome.storage.onChanged.addListener(async (changes, area) => {
|
||||
if (area !== 'local' || !changes.audioSettings) return;
|
||||
await ensureState();
|
||||
if (!currentTabId) return;
|
||||
|
||||
chrome.tabs.sendMessage(currentTabId, {
|
||||
action: 'APPLY_AUDIO_SETTINGS',
|
||||
settings: changes.audioSettings.newValue
|
||||
}).catch(() => {});
|
||||
});
|
||||
|
||||
// Tab removal listener
|
||||
chrome.tabs.onRemoved.addListener(async (tabId) => {
|
||||
await ensureState();
|
||||
if (tabId === currentTabId) {
|
||||
const wasInRoom = !!currentRoom;
|
||||
currentTabId = null;
|
||||
currentTabTitle = null;
|
||||
lastContentHeartbeatAt = null;
|
||||
roomIdleSince = Date.now();
|
||||
chrome.storage.session.set({ currentTabId: null, currentTabTitle: null, roomIdleSince, lastContentHeartbeatAt });
|
||||
updateBadgeStatus();
|
||||
addLog('Target tab closed.', 'warn');
|
||||
|
||||
if (wasInRoom) {
|
||||
const roomAtClose = currentRoom;
|
||||
getSettings().then(settings => {
|
||||
if (currentRoom !== roomAtClose) return;
|
||||
|
||||
emit(EVENTS.PEER_STATUS, {
|
||||
peerId,
|
||||
playbackState: 'paused',
|
||||
currentTime: null,
|
||||
mediaTitle: null,
|
||||
username: settings.username,
|
||||
tabTitle: null
|
||||
});
|
||||
|
||||
if (currentRoom && Array.isArray(currentRoom.peers)) {
|
||||
const me = currentRoom.peers.find(p => (p.peerId || p) === peerId);
|
||||
if (me && typeof me === 'object') {
|
||||
me.playbackState = 'paused';
|
||||
me.currentTime = null;
|
||||
me.mediaTitle = null;
|
||||
me.tabTitle = null;
|
||||
me.lastHeartbeat = Date.now();
|
||||
if (storageInitialized) chrome.storage.session.set({ currentRoom });
|
||||
chrome.runtime.sendMessage({ type: 'PEER_UPDATE', peers: currentRoom.peers }).catch(() => {});
|
||||
}
|
||||
}
|
||||
}).catch(() => {});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Re-inject on full page refresh
|
||||
chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, _tab) => {
|
||||
await ensureState();
|
||||
if (currentTabId && tabId === parseInt(currentTabId) && changeInfo.status === 'complete') {
|
||||
chrome.scripting.executeScript({
|
||||
target: { tabId },
|
||||
files: ['content.js']
|
||||
})
|
||||
.then(() => applyAudioSettingsToTab(tabId))
|
||||
.catch(() => {});
|
||||
}
|
||||
initTabManager({
|
||||
getCurrentTabId: () => currentTabId,
|
||||
setCurrentTabId: (val) => { currentTabId = val; },
|
||||
setCurrentTabTitle: (val) => { currentTabTitle = val; },
|
||||
setLastContentHeartbeatAt: (val) => { lastContentHeartbeatAt = val; },
|
||||
setRoomIdleSince: (val) => { roomIdleSince = val; },
|
||||
getCurrentRoom: () => currentRoom,
|
||||
getPeerId: () => peerId,
|
||||
getStorageInitialized: () => storageInitialized,
|
||||
updateBadgeStatus,
|
||||
addLog,
|
||||
getSettings,
|
||||
emit,
|
||||
applyAudioSettingsToTab,
|
||||
ensureState,
|
||||
EVENTS
|
||||
});
|
||||
|
||||
// Initial Connect — only if user has an active room configuration
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
export function initTabManager({
|
||||
getCurrentTabId,
|
||||
setCurrentTabId,
|
||||
setCurrentTabTitle,
|
||||
setLastContentHeartbeatAt,
|
||||
setRoomIdleSince,
|
||||
getCurrentRoom,
|
||||
getPeerId,
|
||||
getStorageInitialized,
|
||||
updateBadgeStatus,
|
||||
addLog,
|
||||
getSettings,
|
||||
emit,
|
||||
applyAudioSettingsToTab,
|
||||
ensureState,
|
||||
EVENTS
|
||||
}) {
|
||||
chrome.storage.onChanged.addListener(async (changes, area) => {
|
||||
if (area !== 'local' || !changes.audioSettings) return;
|
||||
await ensureState();
|
||||
const tabId = getCurrentTabId();
|
||||
if (!tabId) return;
|
||||
|
||||
chrome.tabs.sendMessage(tabId, {
|
||||
action: 'APPLY_AUDIO_SETTINGS',
|
||||
settings: changes.audioSettings.newValue
|
||||
}).catch(() => {});
|
||||
});
|
||||
|
||||
chrome.tabs.onRemoved.addListener(async (tabId) => {
|
||||
await ensureState();
|
||||
if (tabId === getCurrentTabId()) {
|
||||
const wasInRoom = !!getCurrentRoom();
|
||||
setCurrentTabId(null);
|
||||
setCurrentTabTitle(null);
|
||||
setLastContentHeartbeatAt(null);
|
||||
const now = Date.now();
|
||||
setRoomIdleSince(now);
|
||||
chrome.storage.session.set({
|
||||
currentTabId: null,
|
||||
currentTabTitle: null,
|
||||
roomIdleSince: now,
|
||||
lastContentHeartbeatAt: null
|
||||
});
|
||||
updateBadgeStatus();
|
||||
addLog('Target tab closed.', 'warn');
|
||||
|
||||
if (wasInRoom) {
|
||||
const roomAtClose = getCurrentRoom();
|
||||
getSettings().then(settings => {
|
||||
if (getCurrentRoom() !== roomAtClose) return;
|
||||
|
||||
emit(EVENTS.PEER_STATUS, {
|
||||
peerId: getPeerId(),
|
||||
playbackState: 'paused',
|
||||
currentTime: null,
|
||||
mediaTitle: null,
|
||||
username: settings.username,
|
||||
tabTitle: null
|
||||
});
|
||||
|
||||
const room = getCurrentRoom();
|
||||
if (room && Array.isArray(room.peers)) {
|
||||
const me = room.peers.find(p => (p.peerId || p) === getPeerId());
|
||||
if (me && typeof me === 'object') {
|
||||
me.playbackState = 'paused';
|
||||
me.currentTime = null;
|
||||
me.mediaTitle = null;
|
||||
me.tabTitle = null;
|
||||
me.lastHeartbeat = Date.now();
|
||||
if (getStorageInitialized()) {
|
||||
chrome.storage.session.set({ currentRoom: room });
|
||||
}
|
||||
chrome.runtime.sendMessage({ type: 'PEER_UPDATE', peers: room.peers }).catch(() => {});
|
||||
}
|
||||
}
|
||||
}).catch(() => {});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, _tab) => {
|
||||
await ensureState();
|
||||
const curTabId = getCurrentTabId();
|
||||
if (curTabId && tabId === parseInt(curTabId) && changeInfo.status === 'complete') {
|
||||
chrome.scripting.executeScript({
|
||||
target: { tabId },
|
||||
files: ['content.js']
|
||||
})
|
||||
.then(() => applyAudioSettingsToTab(tabId))
|
||||
.catch(() => {});
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user