Initial commit: SyncWatch Chrome extension + WebSocket server
This commit is contained in:
66
extension/content.js
Normal file
66
extension/content.js
Normal file
@@ -0,0 +1,66 @@
|
||||
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);
|
||||
});
|
||||
Reference in New Issue
Block a user