mirror of
https://github.com/SoPat712/videospeed.git
synced 2026-04-21 04:42:35 -04:00
378 lines
12 KiB
JavaScript
378 lines
12 KiB
JavaScript
document.addEventListener("DOMContentLoaded", function () {
|
|
var speederShared =
|
|
typeof SpeederShared === "object" && SpeederShared ? SpeederShared : {};
|
|
var siteRuleUtils = speederShared.siteRules || {};
|
|
var popupControlUtils = speederShared.popupControls || {};
|
|
|
|
/* `label` is only used if ui-icons.js has no path for this action (fallback). */
|
|
var controllerButtonDefs = {
|
|
rewind: { label: "", className: "rw" },
|
|
slower: { label: "", className: "" },
|
|
faster: { label: "", className: "" },
|
|
advance: { label: "", className: "rw" },
|
|
display: { label: "", className: "hideButton" },
|
|
reset: { label: "\u21BB", className: "" },
|
|
fast: { label: "", className: "" },
|
|
nudge: { label: "", className: "" },
|
|
pause: { label: "", className: "" },
|
|
muted: { label: "", className: "" },
|
|
louder: { label: "", className: "" },
|
|
softer: { label: "", className: "" },
|
|
mark: { label: "", className: "" },
|
|
jump: { label: "", className: "" },
|
|
settings: { label: "", className: "" }
|
|
};
|
|
|
|
var defaultButtons = ["rewind", "slower", "faster", "advance", "display"];
|
|
var popupExcludedButtonIds = new Set(["settings"]);
|
|
var storageDefaults = {
|
|
enabled: true,
|
|
showPopupControlBar: true,
|
|
controllerButtons: defaultButtons,
|
|
popupMatchHoverControls: true,
|
|
popupControllerButtons: defaultButtons,
|
|
siteRules: []
|
|
};
|
|
var renderToken = 0;
|
|
|
|
function matchSiteRule(url, siteRules) {
|
|
return siteRuleUtils.matchSiteRule(url, siteRules);
|
|
}
|
|
|
|
function isSiteRuleDisabled(rule) {
|
|
return siteRuleUtils.isSiteRuleDisabled(rule);
|
|
}
|
|
|
|
function resolvePopupButtons(storage, siteRule) {
|
|
return popupControlUtils.resolvePopupButtons(storage, siteRule, {
|
|
controllerButtonDefs: controllerButtonDefs,
|
|
defaultButtons: defaultButtons,
|
|
excludedIds: popupExcludedButtonIds
|
|
});
|
|
}
|
|
|
|
function setControlBarVisible(visible) {
|
|
var bar = document.getElementById("popupControlBar");
|
|
var dividers = document.querySelectorAll(".popup-divider");
|
|
if (bar) bar.style.display = visible ? "" : "none";
|
|
dividers.forEach(function (d) { d.style.display = visible ? "" : "none"; });
|
|
}
|
|
|
|
function sendToActiveTab(message, callback) {
|
|
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
|
|
if (tabs[0] && tabs[0].id) {
|
|
chrome.tabs.sendMessage(tabs[0].id, message, function (response) {
|
|
if (chrome.runtime.lastError) {
|
|
if (callback) callback(null);
|
|
} else {
|
|
if (callback) callback(response);
|
|
}
|
|
});
|
|
} else {
|
|
if (callback) callback(null);
|
|
}
|
|
});
|
|
}
|
|
|
|
function getActiveTabContext(callback) {
|
|
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
|
|
var activeTab = tabs && tabs[0] ? tabs[0] : null;
|
|
if (!activeTab || !activeTab.id) {
|
|
if (callback) callback({ tab: null, url: "" });
|
|
return;
|
|
}
|
|
|
|
var tabUrl = typeof activeTab.url === "string" ? activeTab.url : "";
|
|
if (tabUrl.length > 0) {
|
|
if (callback) callback({ tab: activeTab, url: tabUrl });
|
|
return;
|
|
}
|
|
|
|
chrome.tabs.sendMessage(
|
|
activeTab.id,
|
|
{ action: "get_page_context" },
|
|
function (response) {
|
|
if (chrome.runtime.lastError) {
|
|
if (callback) callback({ tab: activeTab, url: "" });
|
|
return;
|
|
}
|
|
|
|
var pageUrl =
|
|
response && typeof response.url === "string" ? response.url : "";
|
|
if (callback) callback({ tab: activeTab, url: pageUrl });
|
|
}
|
|
);
|
|
});
|
|
}
|
|
|
|
function updateSpeedDisplay(speed) {
|
|
var el = document.getElementById("popupSpeed");
|
|
if (el) el.textContent = (speed != null ? Number(speed) : 1).toFixed(2);
|
|
}
|
|
|
|
function applySpeedAndResetFromResponse(response) {
|
|
if (response && response.speed != null) {
|
|
updateSpeedDisplay(response.speed);
|
|
}
|
|
}
|
|
|
|
function pickBestFrameSpeedResult(results) {
|
|
return popupControlUtils.pickBestFrameSpeedResult(results);
|
|
}
|
|
|
|
function querySpeed() {
|
|
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
|
|
if (!tabs[0] || tabs[0].id == null) {
|
|
return;
|
|
}
|
|
var tabId = tabs[0].id;
|
|
chrome.tabs.executeScript(
|
|
tabId,
|
|
{ allFrames: true, file: "frameSpeedSnapshot.js" },
|
|
function (results) {
|
|
if (chrome.runtime.lastError) {
|
|
sendToActiveTab({ action: "get_speed" }, function (response) {
|
|
applySpeedAndResetFromResponse(response || { speed: 1 });
|
|
});
|
|
return;
|
|
}
|
|
var best = pickBestFrameSpeedResult(results);
|
|
if (best) {
|
|
applySpeedAndResetFromResponse(best);
|
|
} else {
|
|
sendToActiveTab({ action: "get_speed" }, function (response) {
|
|
applySpeedAndResetFromResponse(response || { speed: 1 });
|
|
});
|
|
}
|
|
}
|
|
);
|
|
});
|
|
}
|
|
|
|
function buildControlBar(buttons, customIconsMap) {
|
|
var bar = document.getElementById("popupControlBar");
|
|
if (!bar) return;
|
|
|
|
var existing = bar.querySelectorAll("button");
|
|
existing.forEach(function (btn) { btn.remove(); });
|
|
|
|
var customMap = customIconsMap || {};
|
|
|
|
buttons.forEach(function (btnId) {
|
|
var def = controllerButtonDefs[btnId];
|
|
if (!def) return;
|
|
|
|
var btn = document.createElement("button");
|
|
btn.dataset.action = btnId;
|
|
var customEntry = customMap[btnId];
|
|
if (customEntry && customEntry.svg) {
|
|
var customSpan = vscCreateSvgWrap(document, customEntry.svg, "vsc-btn-icon");
|
|
if (customSpan) {
|
|
btn.appendChild(customSpan);
|
|
} else {
|
|
btn.textContent = def.label || "?";
|
|
}
|
|
} else if (typeof vscIconSvgString === "function") {
|
|
var svgStr = vscIconSvgString(btnId, 16);
|
|
if (svgStr) {
|
|
var iconSpan = vscCreateSvgWrap(document, svgStr, "vsc-btn-icon");
|
|
if (iconSpan) {
|
|
btn.appendChild(iconSpan);
|
|
} else {
|
|
btn.textContent = def.label || "?";
|
|
}
|
|
} else {
|
|
btn.textContent = def.label || "?";
|
|
}
|
|
} else {
|
|
btn.textContent = def.label || "?";
|
|
}
|
|
if (def.className) btn.className = def.className;
|
|
btn.title = btnId.charAt(0).toUpperCase() + btnId.slice(1);
|
|
|
|
btn.addEventListener("click", function () {
|
|
if (btnId === "settings") {
|
|
window.open(chrome.runtime.getURL("options.html"));
|
|
return;
|
|
}
|
|
sendToActiveTab(
|
|
{ action: "run_action", actionName: btnId },
|
|
function () {
|
|
querySpeed();
|
|
}
|
|
);
|
|
});
|
|
|
|
bar.appendChild(btn);
|
|
});
|
|
}
|
|
|
|
var manifest = chrome.runtime.getManifest();
|
|
var versionElement = document.querySelector("#app-version");
|
|
if (versionElement) {
|
|
versionElement.innerText = manifest.version;
|
|
}
|
|
|
|
document.querySelector("#config").addEventListener("click", function () {
|
|
window.open(chrome.runtime.getURL("options.html"));
|
|
});
|
|
|
|
document.querySelector("#about").addEventListener("click", function () {
|
|
window.open("https://github.com/SoPat712/Speeder");
|
|
});
|
|
|
|
document.querySelector("#feedback").addEventListener("click", function () {
|
|
window.open("https://github.com/SoPat712/Speeder/issues");
|
|
});
|
|
|
|
document.querySelector("#donate").addEventListener("click", function () {
|
|
this.classList.add("hide");
|
|
document.querySelector("#donateOptions").classList.remove("hide");
|
|
});
|
|
|
|
document.querySelector("#enable").addEventListener("click", function () {
|
|
toggleEnabled(true, settingsSavedReloadMessage);
|
|
});
|
|
|
|
document.querySelector("#disable").addEventListener("click", function () {
|
|
toggleEnabled(false, settingsSavedReloadMessage);
|
|
});
|
|
|
|
document.querySelector("#refresh").addEventListener("click", function () {
|
|
setStatusMessage("Rescanning page...");
|
|
sendToActiveTab({ action: "rescan_page" }, function (response) {
|
|
if (!response) {
|
|
setStatusMessage("Cannot run on this page.");
|
|
} else if (response.status === "complete") {
|
|
setStatusMessage("Scan complete. Closing...");
|
|
setTimeout(function () { window.close(); }, 500);
|
|
} else {
|
|
setStatusMessage("Scan failed. Please reload the page.");
|
|
}
|
|
});
|
|
});
|
|
|
|
function renderForActiveTab() {
|
|
var currentRenderToken = ++renderToken;
|
|
|
|
chrome.storage.local.get(["customButtonIcons"], function (loc) {
|
|
if (currentRenderToken !== renderToken) return;
|
|
var customIconsMap =
|
|
loc && loc.customButtonIcons && typeof loc.customButtonIcons === "object"
|
|
? loc.customButtonIcons
|
|
: {};
|
|
|
|
chrome.storage.sync.get(storageDefaults, function (storage) {
|
|
if (currentRenderToken !== renderToken) return;
|
|
|
|
getActiveTabContext(function (context) {
|
|
if (currentRenderToken !== renderToken) return;
|
|
|
|
var url = context && context.url ? context.url : "";
|
|
var siteRule = matchSiteRule(url, storage.siteRules);
|
|
var siteDisabled = isSiteRuleDisabled(siteRule);
|
|
var siteAvailable = siteRuleUtils.isSpeederActiveForSite(
|
|
storage.enabled,
|
|
siteRule
|
|
);
|
|
var showBar = storage.showPopupControlBar !== false;
|
|
|
|
if (siteRule && siteRule.showPopupControlBar !== undefined) {
|
|
showBar = siteRule.showPopupControlBar;
|
|
}
|
|
|
|
toggleEnabledUI(storage.enabled !== false);
|
|
buildControlBar(
|
|
resolvePopupButtons(storage, siteRule),
|
|
customIconsMap
|
|
);
|
|
setControlBarVisible(siteAvailable && showBar);
|
|
|
|
if (siteDisabled) {
|
|
setStatusMessage("Speeder is disabled for this site.");
|
|
updateSpeedDisplay(1);
|
|
return;
|
|
}
|
|
|
|
clearStatusMessage();
|
|
if (siteAvailable) {
|
|
querySpeed();
|
|
} else {
|
|
updateSpeedDisplay(1);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
chrome.tabs.onActivated.addListener(function () {
|
|
renderForActiveTab();
|
|
});
|
|
|
|
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
|
|
if (!tab || tab.active !== true) return;
|
|
if (changeInfo.url !== undefined || changeInfo.status === "complete") {
|
|
renderForActiveTab();
|
|
}
|
|
});
|
|
|
|
chrome.storage.onChanged.addListener(function (changes, areaName) {
|
|
if (areaName === "local" && changes.customButtonIcons) {
|
|
renderForActiveTab();
|
|
return;
|
|
}
|
|
if (areaName !== "sync") return;
|
|
if (
|
|
changes.enabled ||
|
|
changes.showPopupControlBar ||
|
|
changes.controllerButtons ||
|
|
changes.popupMatchHoverControls ||
|
|
changes.popupControllerButtons ||
|
|
changes.siteRules
|
|
) {
|
|
renderForActiveTab();
|
|
}
|
|
});
|
|
|
|
renderForActiveTab();
|
|
|
|
function toggleEnabled(enabled, callback) {
|
|
chrome.storage.sync.set({ enabled: enabled }, function () {
|
|
toggleEnabledUI(enabled);
|
|
if (callback) callback(enabled);
|
|
});
|
|
}
|
|
|
|
function toggleEnabledUI(enabled) {
|
|
document.querySelector("#enable").classList.toggle("hide", enabled);
|
|
document.querySelector("#disable").classList.toggle("hide", !enabled);
|
|
|
|
const suffix = `${enabled ? "" : "_disabled"}.png`;
|
|
chrome.browserAction.setIcon({
|
|
path: {
|
|
19: "icons/icon19" + suffix,
|
|
38: "icons/icon38" + suffix,
|
|
48: "icons/icon48" + suffix
|
|
}
|
|
});
|
|
}
|
|
|
|
function settingsSavedReloadMessage(enabled) {
|
|
setStatusMessage(
|
|
`${enabled ? "Enabled" : "Disabled"}. Reload page to see changes`
|
|
);
|
|
}
|
|
|
|
function setStatusMessage(str) {
|
|
const status_element = document.querySelector("#status");
|
|
status_element.classList.toggle("hide", false);
|
|
status_element.innerText = str;
|
|
}
|
|
|
|
function clearStatusMessage() {
|
|
const status_element = document.querySelector("#status");
|
|
status_element.classList.toggle("hide", true);
|
|
status_element.innerText = "";
|
|
}
|
|
});
|