mirror of
https://github.com/SoPat712/videospeed.git
synced 2025-10-28 18:10:56 -04:00
gitignore update
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,5 +2,6 @@
|
|||||||
local
|
local
|
||||||
|
|
||||||
# IntelliJ IDEA
|
# IntelliJ IDEA
|
||||||
|
*.xpi
|
||||||
.idea/
|
.idea/
|
||||||
node_modules
|
node_modules
|
||||||
|
|||||||
337
inject.js
337
inject.js
@@ -186,6 +186,8 @@ function defineVideoController() {
|
|||||||
this.parent = target.parentElement || parent;
|
this.parent = target.parentElement || parent;
|
||||||
this.nudgeIntervalId = null;
|
this.nudgeIntervalId = null;
|
||||||
|
|
||||||
|
log(`Creating video controller for ${target.tagName} with src: ${target.src || target.currentSrc || 'none'}`, 4);
|
||||||
|
|
||||||
// Determine what speed to use
|
// Determine what speed to use
|
||||||
let storedSpeed = tc.settings.speeds[target.currentSrc];
|
let storedSpeed = tc.settings.speeds[target.currentSrc];
|
||||||
if (!tc.settings.rememberSpeed) {
|
if (!tc.settings.rememberSpeed) {
|
||||||
@@ -209,6 +211,13 @@ function defineVideoController() {
|
|||||||
|
|
||||||
this.div = this.initializeControls();
|
this.div = this.initializeControls();
|
||||||
|
|
||||||
|
if (!this.div) {
|
||||||
|
log("ERROR: Failed to create controller div!", 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log(`Controller created and attached to DOM. Hidden: ${this.div.classList.contains('vsc-hidden')}`, 4);
|
||||||
|
|
||||||
// Make the controller visible for 5 seconds on startup
|
// Make the controller visible for 5 seconds on startup
|
||||||
runAction("blink", 5000, null, this.video);
|
runAction("blink", 5000, null, this.video);
|
||||||
|
|
||||||
@@ -319,7 +328,7 @@ function defineVideoController() {
|
|||||||
const expectedSpeed = tc.settings.forceLastSavedSpeed
|
const expectedSpeed = tc.settings.forceLastSavedSpeed
|
||||||
? tc.settings.lastSpeed
|
? tc.settings.lastSpeed
|
||||||
: tc.settings.speeds[mutation.target.currentSrc] ||
|
: tc.settings.speeds[mutation.target.currentSrc] ||
|
||||||
tc.settings.lastSpeed;
|
tc.settings.lastSpeed;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (mutation.target.vsc) {
|
if (mutation.target.vsc) {
|
||||||
@@ -399,7 +408,7 @@ function defineVideoController() {
|
|||||||
if (
|
if (
|
||||||
this.video &&
|
this.video &&
|
||||||
Math.abs(this.video.playbackRate - (currentRate + nudgeAmount)) <
|
Math.abs(this.video.playbackRate - (currentRate + nudgeAmount)) <
|
||||||
nudgeAmount * 1.5
|
nudgeAmount * 1.5
|
||||||
) {
|
) {
|
||||||
this.video.playbackRate = currentRate;
|
this.video.playbackRate = currentRate;
|
||||||
}
|
}
|
||||||
@@ -471,32 +480,49 @@ function defineVideoController() {
|
|||||||
var fragment = doc.createDocumentFragment();
|
var fragment = doc.createDocumentFragment();
|
||||||
fragment.appendChild(wrapper);
|
fragment.appendChild(wrapper);
|
||||||
const parentEl = this.parent || this.video.parentElement;
|
const parentEl = this.parent || this.video.parentElement;
|
||||||
|
|
||||||
|
log(`Inserting controller: parentEl=${!!parentEl}, parentNode=${!!parentEl?.parentNode}, hostname=${location.hostname}`, 4);
|
||||||
|
|
||||||
if (!parentEl || !parentEl.parentNode) {
|
if (!parentEl || !parentEl.parentNode) {
|
||||||
|
log("No suitable parent found, appending to body", 4);
|
||||||
doc.body.appendChild(fragment);
|
doc.body.appendChild(fragment);
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
switch (true) {
|
|
||||||
case location.hostname == "www.amazon.com":
|
try {
|
||||||
case location.hostname == "www.reddit.com":
|
switch (true) {
|
||||||
case /hbogo\./.test(location.hostname):
|
case location.hostname == "www.amazon.com":
|
||||||
parentEl.parentElement.insertBefore(fragment, parentEl);
|
case location.hostname == "www.reddit.com":
|
||||||
break;
|
case /hbogo\./.test(location.hostname):
|
||||||
case location.hostname == "www.facebook.com":
|
log("Using parentElement.parentElement insertion", 5);
|
||||||
let p =
|
parentEl.parentElement.insertBefore(fragment, parentEl);
|
||||||
parentEl.parentElement.parentElement.parentElement.parentElement
|
break;
|
||||||
.parentElement.parentElement.parentElement;
|
case location.hostname == "www.facebook.com":
|
||||||
if (p && p.firstChild) p.insertBefore(fragment, p.firstChild);
|
log("Using Facebook-specific insertion", 5);
|
||||||
else parentEl.insertBefore(fragment, parentEl.firstChild);
|
let p =
|
||||||
break;
|
parentEl.parentElement.parentElement.parentElement.parentElement
|
||||||
case location.hostname == "tv.apple.com":
|
.parentElement.parentElement.parentElement;
|
||||||
const r = parentEl.getRootNode();
|
if (p && p.firstChild) p.insertBefore(fragment, p.firstChild);
|
||||||
const s = r && r.querySelector ? r.querySelector(".scrim") : null;
|
else parentEl.insertBefore(fragment, parentEl.firstChild);
|
||||||
if (s) s.prepend(fragment);
|
break;
|
||||||
else parentEl.insertBefore(fragment, parentEl.firstChild);
|
case location.hostname == "tv.apple.com":
|
||||||
break;
|
log("Using Apple TV-specific insertion", 5);
|
||||||
default:
|
const r = parentEl.getRootNode();
|
||||||
parentEl.insertBefore(fragment, parentEl.firstChild);
|
const s = r && r.querySelector ? r.querySelector(".scrim") : null;
|
||||||
|
if (s) s.prepend(fragment);
|
||||||
|
else parentEl.insertBefore(fragment, parentEl.firstChild);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log("Using default insertion method", 5);
|
||||||
|
parentEl.insertBefore(fragment, parentEl.firstChild);
|
||||||
|
}
|
||||||
|
log("Controller successfully inserted into DOM", 4);
|
||||||
|
} catch (error) {
|
||||||
|
log(`Error inserting controller: ${error.message}`, 2);
|
||||||
|
// Fallback to body insertion
|
||||||
|
doc.body.appendChild(fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrapper;
|
return wrapper;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -543,7 +569,7 @@ function setupListener() {
|
|||||||
video.vsc.speedIndicator.textContent = speed.toFixed(2);
|
video.vsc.speedIndicator.textContent = speed.toFixed(2);
|
||||||
tc.settings.speeds[video.currentSrc || "unknown_src"] = speed;
|
tc.settings.speeds[video.currentSrc || "unknown_src"] = speed;
|
||||||
tc.settings.lastSpeed = speed;
|
tc.settings.lastSpeed = speed;
|
||||||
chrome.storage.sync.set({ lastSpeed: speed }, () => {});
|
chrome.storage.sync.set({ lastSpeed: speed }, () => { });
|
||||||
if (fromUserInput) {
|
if (fromUserInput) {
|
||||||
runAction("blink", 1000, null, video);
|
runAction("blink", 1000, null, video);
|
||||||
}
|
}
|
||||||
@@ -583,12 +609,18 @@ function setupListener() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var vscInitializedDocuments = new Set();
|
var vscInitializedDocuments = new Set();
|
||||||
function initializeWhenReady(doc) {
|
function initializeWhenReady(doc, forceReinit = false) {
|
||||||
if (vscInitializedDocuments.has(doc) || !doc.body) return;
|
if (!forceReinit && vscInitializedDocuments.has(doc) || !doc.body) return;
|
||||||
|
|
||||||
|
// For navigation changes, we want to re-scan even if already initialized
|
||||||
|
if (forceReinit) {
|
||||||
|
log("Force re-initialization requested", 4);
|
||||||
|
}
|
||||||
|
|
||||||
if (doc.readyState === "complete") {
|
if (doc.readyState === "complete") {
|
||||||
initializeNow(doc);
|
initializeNow(doc, forceReinit);
|
||||||
} else {
|
} else {
|
||||||
doc.addEventListener("DOMContentLoaded", () => initializeNow(doc), {
|
doc.addEventListener("DOMContentLoaded", () => initializeNow(doc, forceReinit), {
|
||||||
once: true
|
once: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -608,7 +640,17 @@ function getShadow(parent) {
|
|||||||
do {
|
do {
|
||||||
r.push(c);
|
r.push(c);
|
||||||
gC(c);
|
gC(c);
|
||||||
if (c.shadowRoot) r.push(...getShadow(c.shadowRoot));
|
if (c.shadowRoot) {
|
||||||
|
r.push(...getShadow(c.shadowRoot));
|
||||||
|
// Also check for videos in shadow DOM
|
||||||
|
const shadowVideos = c.shadowRoot.querySelectorAll(tc.settings.audioBoolean ? "video,audio" : "video");
|
||||||
|
shadowVideos.forEach(video => {
|
||||||
|
if (!video.vsc) {
|
||||||
|
log(`Found video in shadow DOM`, 5);
|
||||||
|
checkForVideo(video, video.parentElement, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
c = c.nextElementSibling;
|
c = c.nextElementSibling;
|
||||||
} while (c);
|
} while (c);
|
||||||
}
|
}
|
||||||
@@ -617,9 +659,10 @@ function getShadow(parent) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
function initializeNow(doc) {
|
function initializeNow(doc, forceReinit = false) {
|
||||||
if (vscInitializedDocuments.has(doc) || !doc.body) return;
|
if (!forceReinit && (vscInitializedDocuments.has(doc) || !doc.body)) return;
|
||||||
if (!tc.settings.enabled) return;
|
if (!tc.settings.enabled) return;
|
||||||
|
|
||||||
if (!doc.body.classList.contains("vsc-initialized"))
|
if (!doc.body.classList.contains("vsc-initialized"))
|
||||||
doc.body.classList.add("vsc-initialized");
|
doc.body.classList.add("vsc-initialized");
|
||||||
if (typeof tc.videoController === "undefined") defineVideoController();
|
if (typeof tc.videoController === "undefined") defineVideoController();
|
||||||
@@ -628,7 +671,7 @@ function initializeNow(doc) {
|
|||||||
var docs = Array(doc);
|
var docs = Array(doc);
|
||||||
try {
|
try {
|
||||||
if (inIframe()) docs.push(window.top.document);
|
if (inIframe()) docs.push(window.top.document);
|
||||||
} catch (e) {}
|
} catch (e) { }
|
||||||
docs.forEach(function (d) {
|
docs.forEach(function (d) {
|
||||||
if (d.vscKeydownListenerAttached) return; // Prevent duplicate listeners
|
if (d.vscKeydownListenerAttached) return; // Prevent duplicate listeners
|
||||||
d.addEventListener(
|
d.addEventListener(
|
||||||
@@ -688,9 +731,16 @@ function initializeNow(doc) {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "attributes":
|
case "attributes":
|
||||||
if (
|
// Enhanced attribute monitoring for video detection
|
||||||
mutation.target.attributes["aria-hidden"] &&
|
const target = mutation.target;
|
||||||
mutation.target.attributes["aria-hidden"].value == "false"
|
if (target.tagName === "VIDEO" || target.tagName === "AUDIO") {
|
||||||
|
// Video/audio element had attributes changed - check if it needs controller
|
||||||
|
if (!target.vsc && (target.src || target.currentSrc)) {
|
||||||
|
checkForVideo(target, target.parentNode, true);
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
target.attributes["aria-hidden"] &&
|
||||||
|
target.attributes["aria-hidden"].value == "false"
|
||||||
) {
|
) {
|
||||||
var flattenedNodes = getShadow(document.body);
|
var flattenedNodes = getShadow(document.body);
|
||||||
var node = flattenedNodes.filter(
|
var node = flattenedNodes.filter(
|
||||||
@@ -719,9 +769,30 @@ function initializeNow(doc) {
|
|||||||
(node.nodeName === "AUDIO" && tc.settings.audioBoolean)
|
(node.nodeName === "AUDIO" && tc.settings.audioBoolean)
|
||||||
) {
|
) {
|
||||||
if (added) {
|
if (added) {
|
||||||
if (!node.vsc) node.vsc = new tc.videoController(node, parent);
|
if (!node.vsc) {
|
||||||
|
log(`Creating controller for ${node.tagName}: ${node.src || node.currentSrc || 'no src'}`, 4);
|
||||||
|
node.vsc = new tc.videoController(node, parent);
|
||||||
|
|
||||||
|
// Verify controller was created successfully
|
||||||
|
if (!node.vsc || !node.vsc.div) {
|
||||||
|
log(`ERROR: Controller creation failed for ${node.tagName}`, 2);
|
||||||
|
} else {
|
||||||
|
log(`Controller created successfully, div in DOM: ${document.contains(node.vsc.div)}`, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to intersection observer if available
|
||||||
|
if (doc.vscVideoIntersectionObserver) {
|
||||||
|
doc.vscVideoIntersectionObserver.observe(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (node.vsc) node.vsc.remove();
|
if (node.vsc) {
|
||||||
|
node.vsc.remove();
|
||||||
|
// Remove from intersection observer if available
|
||||||
|
if (doc.vscVideoIntersectionObserver) {
|
||||||
|
doc.vscVideoIntersectionObserver.unobserve(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (node.children != undefined) {
|
} else if (node.children != undefined) {
|
||||||
for (var i = 0; i < node.children.length; i++) {
|
for (var i = 0; i < node.children.length; i++) {
|
||||||
@@ -731,9 +802,10 @@ function initializeNow(doc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
observer.observe(doc, {
|
observer.observe(doc, {
|
||||||
attributeFilter: ["aria-hidden"],
|
attributeFilter: ["aria-hidden", "src", "currentSrc", "style", "class"],
|
||||||
childList: true,
|
childList: true,
|
||||||
subtree: true
|
subtree: true,
|
||||||
|
attributes: true
|
||||||
});
|
});
|
||||||
doc.vscMutationObserverAttached = true;
|
doc.vscMutationObserverAttached = true;
|
||||||
}
|
}
|
||||||
@@ -744,6 +816,45 @@ function initializeNow(doc) {
|
|||||||
if (!v.vsc) new tc.videoController(v, v.parentElement);
|
if (!v.vsc) new tc.videoController(v, v.parentElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Enhanced video detection via media events
|
||||||
|
if (!doc.vscMediaEventListenersAttached) {
|
||||||
|
const mediaEvents = ['loadstart', 'loadedmetadata', 'canplay', 'play'];
|
||||||
|
mediaEvents.forEach(eventType => {
|
||||||
|
doc.addEventListener(eventType, function (event) {
|
||||||
|
const target = event.target;
|
||||||
|
if ((target.tagName === 'VIDEO' || (target.tagName === 'AUDIO' && tc.settings.audioBoolean)) && !target.vsc) {
|
||||||
|
log(`Media event ${eventType} detected new ${target.tagName.toLowerCase()}`, 5);
|
||||||
|
checkForVideo(target, target.parentElement, true);
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
});
|
||||||
|
doc.vscMediaEventListenersAttached = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intersection Observer for lazy-loaded videos
|
||||||
|
if (!doc.vscIntersectionObserverAttached && 'IntersectionObserver' in window) {
|
||||||
|
const videoIntersectionObserver = new IntersectionObserver((entries) => {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
const target = entry.target;
|
||||||
|
if ((target.tagName === 'VIDEO' || (target.tagName === 'AUDIO' && tc.settings.audioBoolean)) && !target.vsc) {
|
||||||
|
log(`Intersection observer detected visible ${target.tagName.toLowerCase()}`, 5);
|
||||||
|
checkForVideo(target, target.parentElement, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, { threshold: 0.1 });
|
||||||
|
|
||||||
|
// Observe existing videos that might not have been processed
|
||||||
|
doc.querySelectorAll(q).forEach(video => {
|
||||||
|
videoIntersectionObserver.observe(video);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Store observer to add new videos to it
|
||||||
|
doc.vscVideoIntersectionObserver = videoIntersectionObserver;
|
||||||
|
doc.vscIntersectionObserverAttached = true;
|
||||||
|
}
|
||||||
|
|
||||||
Array.from(doc.getElementsByTagName("iframe")).forEach((f) => {
|
Array.from(doc.getElementsByTagName("iframe")).forEach((f) => {
|
||||||
if (f.vscLoadListenerAttached) return;
|
if (f.vscLoadListenerAttached) return;
|
||||||
f.addEventListener("load", () => {
|
f.addEventListener("load", () => {
|
||||||
@@ -764,6 +875,115 @@ function initializeNow(doc) {
|
|||||||
// Silently ignore CORS errors
|
// Silently ignore CORS errors
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// Navigation change detection for SPAs
|
||||||
|
if (!doc.vscNavigationListenersAttached) {
|
||||||
|
let currentUrl = location.href;
|
||||||
|
|
||||||
|
const handleNavigation = (source) => {
|
||||||
|
if (location.href !== currentUrl) {
|
||||||
|
const oldUrl = currentUrl;
|
||||||
|
currentUrl = location.href;
|
||||||
|
log(`Navigation detected via ${source}: ${oldUrl} -> ${currentUrl}`, 4);
|
||||||
|
|
||||||
|
// Wait a bit for the new content to load, then force re-scan
|
||||||
|
setTimeout(() => {
|
||||||
|
const q = tc.settings.audioBoolean ? "video,audio" : "video";
|
||||||
|
const videos = document.querySelectorAll(q);
|
||||||
|
log(`Post-navigation scan found ${videos.length} videos`, 4);
|
||||||
|
|
||||||
|
videos.forEach(video => {
|
||||||
|
if (!video.vsc) {
|
||||||
|
log(`Adding controller to post-navigation video`, 4);
|
||||||
|
checkForVideo(video, video.parentElement, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 500); // Increased delay for content to load
|
||||||
|
|
||||||
|
// Also do a quicker scan
|
||||||
|
setTimeout(() => {
|
||||||
|
const q = tc.settings.audioBoolean ? "video,audio" : "video";
|
||||||
|
const videos = document.querySelectorAll(q);
|
||||||
|
videos.forEach(video => {
|
||||||
|
if (!video.vsc && (video.src || video.currentSrc)) {
|
||||||
|
checkForVideo(video, video.parentElement, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Listen for popstate (back/forward navigation)
|
||||||
|
window.addEventListener('popstate', () => handleNavigation('popstate'));
|
||||||
|
|
||||||
|
// Override pushState and replaceState to catch programmatic navigation
|
||||||
|
const originalPushState = history.pushState;
|
||||||
|
const originalReplaceState = history.replaceState;
|
||||||
|
|
||||||
|
history.pushState = function (...args) {
|
||||||
|
originalPushState.apply(this, args);
|
||||||
|
handleNavigation('pushState');
|
||||||
|
};
|
||||||
|
|
||||||
|
history.replaceState = function (...args) {
|
||||||
|
originalReplaceState.apply(this, args);
|
||||||
|
handleNavigation('replaceState');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Listen for hashchange as well
|
||||||
|
window.addEventListener('hashchange', () => handleNavigation('hashchange'));
|
||||||
|
|
||||||
|
// Also intercept fetch and XMLHttpRequest for AJAX-heavy sites
|
||||||
|
const originalFetch = window.fetch;
|
||||||
|
window.fetch = function (...args) {
|
||||||
|
return originalFetch.apply(this, args).then(response => {
|
||||||
|
// After any fetch completes, check for new videos
|
||||||
|
setTimeout(() => {
|
||||||
|
const q = tc.settings.audioBoolean ? "video,audio" : "video";
|
||||||
|
const videos = document.querySelectorAll(q);
|
||||||
|
videos.forEach(video => {
|
||||||
|
if (!video.vsc && (video.src || video.currentSrc || video.readyState > 0)) {
|
||||||
|
log(`Post-fetch scan found video`, 5);
|
||||||
|
checkForVideo(video, video.parentElement, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 200);
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
doc.vscNavigationListenersAttached = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Periodic fallback scan for missed videos
|
||||||
|
if (!doc.vscPeriodicScanAttached) {
|
||||||
|
const periodicScan = () => {
|
||||||
|
const q = tc.settings.audioBoolean ? "video,audio" : "video";
|
||||||
|
const allVideos = doc.querySelectorAll(q);
|
||||||
|
let foundNew = false;
|
||||||
|
|
||||||
|
allVideos.forEach(video => {
|
||||||
|
if (!video.vsc && (video.src || video.currentSrc || video.readyState > 0)) {
|
||||||
|
log(`Periodic scan found missed ${video.tagName.toLowerCase()}`, 4);
|
||||||
|
checkForVideo(video, video.parentElement, true);
|
||||||
|
foundNew = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (foundNew) {
|
||||||
|
log(`Periodic scan found ${foundNew} new videos`, 4);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run periodic scan every 3 seconds, but only if we have videos on the page
|
||||||
|
setInterval(() => {
|
||||||
|
if (tc.mediaElements.length > 0 || doc.querySelector(tc.settings.audioBoolean ? "video,audio" : "video")) {
|
||||||
|
periodicScan();
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
doc.vscPeriodicScanAttached = true;
|
||||||
|
}
|
||||||
|
|
||||||
vscInitializedDocuments.add(doc);
|
vscInitializedDocuments.add(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -889,24 +1109,31 @@ function runAction(action, value, e) {
|
|||||||
controller.classList.toggle("vsc-hidden");
|
controller.classList.toggle("vsc-hidden");
|
||||||
break;
|
break;
|
||||||
case "blink":
|
case "blink":
|
||||||
if (
|
log(`Blink action: controller hidden=${controller.classList.contains("vsc-hidden")}, timeout=${controller.blinkTimeOut !== undefined}, duration=${numValue}`, 5);
|
||||||
controller.classList.contains("vsc-hidden") ||
|
|
||||||
controller.blinkTimeOut !== undefined
|
// Always clear existing timeout and show controller
|
||||||
) {
|
if (controller.blinkTimeOut !== undefined) {
|
||||||
clearTimeout(controller.blinkTimeOut);
|
clearTimeout(controller.blinkTimeOut);
|
||||||
controller.classList.remove("vsc-hidden");
|
|
||||||
controller.blinkTimeOut = setTimeout(() => {
|
|
||||||
if (
|
|
||||||
!(
|
|
||||||
controller.classList.contains("vsc-manual") &&
|
|
||||||
!controller.classList.contains("vsc-hidden")
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
controller.classList.add("vsc-hidden");
|
|
||||||
}
|
|
||||||
controller.blinkTimeOut = undefined;
|
|
||||||
}, numValue || 1000); // FIXED: Use numValue for consistency
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always show the controller
|
||||||
|
controller.classList.remove("vsc-hidden");
|
||||||
|
log(`Controller shown, setting timeout for ${numValue || 1000}ms`, 5);
|
||||||
|
|
||||||
|
controller.blinkTimeOut = setTimeout(() => {
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
controller.classList.contains("vsc-manual") &&
|
||||||
|
!controller.classList.contains("vsc-hidden")
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
controller.classList.add("vsc-hidden");
|
||||||
|
log("Controller auto-hidden after blink timeout", 5);
|
||||||
|
} else {
|
||||||
|
log("Controller kept visible (manual mode)", 5);
|
||||||
|
}
|
||||||
|
controller.blinkTimeOut = undefined;
|
||||||
|
}, numValue || 1000);
|
||||||
break;
|
break;
|
||||||
case "drag":
|
case "drag":
|
||||||
if (e) handleDrag(v, e);
|
if (e) handleDrag(v, e);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Video Speed Controller",
|
"name": "Video Speed Controller",
|
||||||
"short_name": "videospeed",
|
"short_name": "videospeed",
|
||||||
"version": "1.6.1",
|
"version": "2.0.0",
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"description": "Speed up, slow down, advance and rewind HTML5 audio/video with shortcuts",
|
"description": "Speed up, slow down, advance and rewind HTML5 audio/video with shortcuts",
|
||||||
"homepage_url": "https://github.com/SoPat712/videospeed",
|
"homepage_url": "https://github.com/SoPat712/videospeed",
|
||||||
|
|||||||
Reference in New Issue
Block a user