let applyingRemote = false; function getMediaElement() { const els = Array.from(document.querySelectorAll('video, audio')); if (!els.length) return null; const playing = els.find((el) => !el.paused && !el.ended); if (playing) return playing; const videos = els.filter((el) => el.tagName === 'VIDEO'); return videos.length ? videos[0] : els[0]; } function onPlay(e) { if (applyingRemote) return; chrome.runtime.sendMessage({ type: 'media_event', action: 'play', time: e.target.currentTime }); } function onPause(e) { if (applyingRemote) return; chrome.runtime.sendMessage({ type: 'media_event', action: 'pause', time: e.target.currentTime }); } function onSeeked(e) { if (applyingRemote) return; chrome.runtime.sendMessage({ type: 'media_event', action: 'seek', time: e.target.currentTime }); } function attachToMedia(el) { if (el._syncwatchAttached) return; el._syncwatchAttached = true; el.addEventListener('play', onPlay); el.addEventListener('pause', onPause); el.addEventListener('seeked', onSeeked); } function attachAll() { document.querySelectorAll('video, audio').forEach(attachToMedia); } attachAll(); const observer = new MutationObserver(attachAll); observer.observe(document.documentElement, { childList: true, subtree: true }); chrome.runtime.onMessage.addListener((msg) => { if (msg.type !== 'apply_sync') return; const el = getMediaElement(); if (!el) return; applyingRemote = true; // Re-sync time on any action; only seek if drift is significant const drift = Math.abs(el.currentTime - msg.time); if (msg.action === 'play') { if (drift > 1) el.currentTime = msg.time; el.play().catch(() => {}); } else if (msg.action === 'pause') { el.pause(); if (drift > 1) el.currentTime = msg.time; } else if (msg.action === 'seek') { el.currentTime = msg.time; } setTimeout(() => { applyingRemote = false; }, 500); });