mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-09-03 22:45:21 +00:00
v1.8.10: fix description length, solo peer detection, tab-close peer notify, lastHeartbeat guard, time interpolation stale guard
This commit is contained in:
+35
-2
@@ -706,7 +706,9 @@ function handleServerEvent(event, data) {
|
|||||||
if (!ignoreStatus) {
|
if (!ignoreStatus) {
|
||||||
peer.playbackState = data.playbackState !== undefined ? data.playbackState : peer.playbackState;
|
peer.playbackState = data.playbackState !== undefined ? data.playbackState : peer.playbackState;
|
||||||
peer.currentTime = data.currentTime !== undefined ? data.currentTime : peer.currentTime;
|
peer.currentTime = data.currentTime !== undefined ? data.currentTime : peer.currentTime;
|
||||||
peer.lastHeartbeat = Date.now();
|
if (data.playbackState !== undefined || data.currentTime !== undefined) {
|
||||||
|
peer.lastHeartbeat = Date.now();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Migration: replace string peer with normalized object
|
// Migration: replace string peer with normalized object
|
||||||
@@ -1169,7 +1171,8 @@ async function handleAsyncMessage(message, sender, sendResponse) {
|
|||||||
addToHistory(message.action, 'You');
|
addToHistory(message.action, 'You');
|
||||||
|
|
||||||
const isNonEssentialEvent = message.action === EVENTS.PLAY || message.action === EVENTS.PAUSE || message.action === EVENTS.SEEK;
|
const isNonEssentialEvent = message.action === EVENTS.PLAY || message.action === EVENTS.PAUSE || message.action === EVENTS.SEEK;
|
||||||
const hasOtherPeers = currentRoom && Array.isArray(currentRoom.peers) && currentRoom.peers.length > 0;
|
const otherCount = currentRoom && Array.isArray(currentRoom.peers) ? currentRoom.peers.filter(p => (typeof p === 'object' ? p.peerId : p) !== peerId).length : 0;
|
||||||
|
const hasOtherPeers = otherCount > 0;
|
||||||
|
|
||||||
if (isNonEssentialEvent && !hasOtherPeers) {
|
if (isNonEssentialEvent && !hasOtherPeers) {
|
||||||
sendResponse({ status: 'ok_solo' });
|
sendResponse({ status: 'ok_solo' });
|
||||||
@@ -1384,11 +1387,41 @@ async function handleAsyncMessage(message, sender, sendResponse) {
|
|||||||
// Tab removal listener
|
// Tab removal listener
|
||||||
chrome.tabs.onRemoved.addListener((tabId) => {
|
chrome.tabs.onRemoved.addListener((tabId) => {
|
||||||
if (tabId === currentTabId) {
|
if (tabId === currentTabId) {
|
||||||
|
const wasInRoom = !!currentRoom;
|
||||||
currentTabId = null;
|
currentTabId = null;
|
||||||
currentTabTitle = null;
|
currentTabTitle = null;
|
||||||
chrome.storage.session.set({ currentTabId: null, currentTabTitle: null });
|
chrome.storage.session.set({ currentTabId: null, currentTabTitle: null });
|
||||||
updateBadgeStatus();
|
updateBadgeStatus();
|
||||||
addLog('Target tab closed.', 'warn');
|
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(() => {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "KoalaSync",
|
"name": "KoalaSync",
|
||||||
"version": "1.8.9",
|
"version": "1.8.10",
|
||||||
"description": "Watch party extension to synchronize video playback on YouTube, Twitch, Netflix, Emby, Jellyfin, and any HTML5 site in real-time with friends.",
|
"description": "Synchronize video playback on YouTube, Netflix, Emby, Jellyfin, and any HTML5 site in real-time with friends.",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"storage",
|
"storage",
|
||||||
"tabs",
|
"tabs",
|
||||||
|
|||||||
+16
-2
@@ -334,7 +334,9 @@ function startInterpolation() {
|
|||||||
const peer = activePeers.find(p => p.peerId === peerId);
|
const peer = activePeers.find(p => p.peerId === peerId);
|
||||||
if (peer && peer.playbackState === 'playing' && peer.currentTime != null && peer.lastHeartbeat) {
|
if (peer && peer.playbackState === 'playing' && peer.currentTime != null && peer.lastHeartbeat) {
|
||||||
const elapsed = (Date.now() - peer.lastHeartbeat) / 1000;
|
const elapsed = (Date.now() - peer.lastHeartbeat) / 1000;
|
||||||
el.textContent = formatTime(peer.currentTime + elapsed);
|
if (elapsed < 45) {
|
||||||
|
el.textContent = formatTime(peer.currentTime + elapsed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, 1000);
|
}, 1000);
|
||||||
@@ -477,7 +479,9 @@ function updatePeerList(peers) {
|
|||||||
let displayTime = p.currentTime;
|
let displayTime = p.currentTime;
|
||||||
if (p.playbackState === 'playing' && p.lastHeartbeat && p.currentTime != null) {
|
if (p.playbackState === 'playing' && p.lastHeartbeat && p.currentTime != null) {
|
||||||
const elapsed = (Date.now() - p.lastHeartbeat) / 1000;
|
const elapsed = (Date.now() - p.lastHeartbeat) / 1000;
|
||||||
displayTime += elapsed;
|
if (elapsed < 45) {
|
||||||
|
displayTime += elapsed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
timeSpan.textContent = formatTime(displayTime);
|
timeSpan.textContent = formatTime(displayTime);
|
||||||
statusLine.appendChild(timeSpan);
|
statusLine.appendChild(timeSpan);
|
||||||
@@ -1129,6 +1133,11 @@ elements.playBtn.addEventListener('click', () => {
|
|||||||
type: 'CONTENT_EVENT',
|
type: 'CONTENT_EVENT',
|
||||||
action: EVENTS.PLAY,
|
action: EVENTS.PLAY,
|
||||||
payload: {}
|
payload: {}
|
||||||
|
}, (response) => {
|
||||||
|
if (response && response.status === 'ok_solo') {
|
||||||
|
elements.playBtn.textContent = '▶ Play';
|
||||||
|
elements.playBtn.disabled = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
// Safety reset: restore button after 2.5s in case no peers respond
|
// Safety reset: restore button after 2.5s in case no peers respond
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -1150,6 +1159,11 @@ elements.pauseBtn.addEventListener('click', () => {
|
|||||||
type: 'CONTENT_EVENT',
|
type: 'CONTENT_EVENT',
|
||||||
action: EVENTS.PAUSE,
|
action: EVENTS.PAUSE,
|
||||||
payload: {}
|
payload: {}
|
||||||
|
}, (response) => {
|
||||||
|
if (response && response.status === 'ok_solo') {
|
||||||
|
elements.pauseBtn.textContent = '⏸ Pause';
|
||||||
|
elements.pauseBtn.disabled = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
// Safety reset: restore button after 2.5s in case no peers respond
|
// Safety reset: restore button after 2.5s in case no peers respond
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user