|
@@ -17,7 +17,7 @@
|
|
// @license AGPL-3.0-only
|
|
// @license AGPL-3.0-only
|
|
// @author Sv443
|
|
// @author Sv443
|
|
// @copyright Sv443 (https://github.com/Sv443)
|
|
// @copyright Sv443 (https://github.com/Sv443)
|
|
-// @icon https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/images/logo/logo_dev_48.png
|
|
|
|
|
|
+// @icon https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/images/logo/logo_dev_48.png
|
|
// @match https://music.youtube.com/*
|
|
// @match https://music.youtube.com/*
|
|
// @match https://www.youtube.com/*
|
|
// @match https://www.youtube.com/*
|
|
// @run-at document-start
|
|
// @run-at document-start
|
|
@@ -33,49 +33,49 @@
|
|
// @grant GM.openInTab
|
|
// @grant GM.openInTab
|
|
// @grant unsafeWindow
|
|
// @grant unsafeWindow
|
|
// @noframes
|
|
// @noframes
|
|
-// @resource css-bundle https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/dist/BetterYTM.css
|
|
|
|
-// @resource css-above_queue_btns https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/style/aboveQueueBtns.css
|
|
|
|
-// @resource css-anchor_improvements https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/style/anchorImprovements.css
|
|
|
|
-// @resource css-fix_hdr https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/style/fixHDR.css
|
|
|
|
-// @resource css-fix_spacing https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/style/fixSpacing.css
|
|
|
|
-// @resource css-show_votes https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/style/showVotes.css
|
|
|
|
-// @resource css-vol_slider_size https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/style/volSliderSize.css
|
|
|
|
-// @resource doc-changelog https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/changelog.md
|
|
|
|
-// @resource icon-advanced_mode https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/plus_circle_small.svg
|
|
|
|
-// @resource icon-arrow_down https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/arrow_down.svg
|
|
|
|
-// @resource icon-auto_like_enabled https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/auto_like_enabled.svg
|
|
|
|
-// @resource icon-auto_like https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/auto_like.svg
|
|
|
|
-// @resource icon-clear_list https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/clear_list.svg
|
|
|
|
-// @resource icon-delete https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/delete.svg
|
|
|
|
-// @resource icon-edit https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/edit.svg
|
|
|
|
-// @resource icon-error https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/error.svg
|
|
|
|
-// @resource icon-experimental https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/beaker_small.svg
|
|
|
|
-// @resource icon-globe_small https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/globe_small.svg
|
|
|
|
-// @resource icon-globe https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/globe.svg
|
|
|
|
-// @resource icon-help https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/help.svg
|
|
|
|
-// @resource icon-image_filled https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/image_filled.svg
|
|
|
|
-// @resource icon-image https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/image.svg
|
|
|
|
-// @resource icon-link https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/link.svg
|
|
|
|
-// @resource icon-lyrics https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/lyrics.svg
|
|
|
|
-// @resource icon-reload https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/refresh.svg
|
|
|
|
-// @resource icon-skip_to https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/skip_to.svg
|
|
|
|
-// @resource icon-spinner https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/icons/spinner.svg
|
|
|
|
-// @resource img-close https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/images/close.png
|
|
|
|
-// @resource img-discord https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/images/external/discord.png
|
|
|
|
-// @resource img-github https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/images/external/github.png
|
|
|
|
-// @resource img-greasyfork https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/images/external/greasyfork.png
|
|
|
|
-// @resource img-logo_dev https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/images/logo/logo_dev_48.png
|
|
|
|
-// @resource img-logo https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/images/logo/logo_48.png
|
|
|
|
-// @resource img-openuserjs https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/images/external/openuserjs.png
|
|
|
|
-// @resource trans-de_DE https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/translations/de_DE.json
|
|
|
|
-// @resource trans-en_US https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/translations/en_US.json
|
|
|
|
-// @resource trans-en_UK https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/translations/en_UK.json
|
|
|
|
-// @resource trans-es_ES https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/translations/es_ES.json
|
|
|
|
-// @resource trans-fr_FR https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/translations/fr_FR.json
|
|
|
|
-// @resource trans-hi_IN https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/translations/hi_IN.json
|
|
|
|
-// @resource trans-ja_JA https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/translations/ja_JA.json
|
|
|
|
-// @resource trans-pt_BR https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/translations/pt_BR.json
|
|
|
|
-// @resource trans-zh_CN https://raw.githubusercontent.com/Sv443/BetterYTM/5f7a1c2a/assets/translations/zh_CN.json
|
|
|
|
|
|
+// @resource css-bundle https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/dist/BetterYTM.css
|
|
|
|
+// @resource css-above_queue_btns https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/style/aboveQueueBtns.css
|
|
|
|
+// @resource css-anchor_improvements https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/style/anchorImprovements.css
|
|
|
|
+// @resource css-fix_hdr https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/style/fixHDR.css
|
|
|
|
+// @resource css-fix_spacing https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/style/fixSpacing.css
|
|
|
|
+// @resource css-show_votes https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/style/showVotes.css
|
|
|
|
+// @resource css-vol_slider_size https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/style/volSliderSize.css
|
|
|
|
+// @resource doc-changelog https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/changelog.md
|
|
|
|
+// @resource icon-advanced_mode https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/plus_circle_small.svg
|
|
|
|
+// @resource icon-arrow_down https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/arrow_down.svg
|
|
|
|
+// @resource icon-auto_like_enabled https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/auto_like_enabled.svg
|
|
|
|
+// @resource icon-auto_like https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/auto_like.svg
|
|
|
|
+// @resource icon-clear_list https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/clear_list.svg
|
|
|
|
+// @resource icon-delete https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/delete.svg
|
|
|
|
+// @resource icon-edit https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/edit.svg
|
|
|
|
+// @resource icon-error https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/error.svg
|
|
|
|
+// @resource icon-experimental https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/beaker_small.svg
|
|
|
|
+// @resource icon-globe_small https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/globe_small.svg
|
|
|
|
+// @resource icon-globe https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/globe.svg
|
|
|
|
+// @resource icon-help https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/help.svg
|
|
|
|
+// @resource icon-image_filled https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/image_filled.svg
|
|
|
|
+// @resource icon-image https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/image.svg
|
|
|
|
+// @resource icon-link https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/link.svg
|
|
|
|
+// @resource icon-lyrics https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/lyrics.svg
|
|
|
|
+// @resource icon-reload https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/refresh.svg
|
|
|
|
+// @resource icon-skip_to https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/skip_to.svg
|
|
|
|
+// @resource icon-spinner https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/icons/spinner.svg
|
|
|
|
+// @resource img-close https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/images/close.png
|
|
|
|
+// @resource img-discord https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/images/external/discord.png
|
|
|
|
+// @resource img-github https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/images/external/github.png
|
|
|
|
+// @resource img-greasyfork https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/images/external/greasyfork.png
|
|
|
|
+// @resource img-logo_dev https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/images/logo/logo_dev_48.png
|
|
|
|
+// @resource img-logo https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/images/logo/logo_48.png
|
|
|
|
+// @resource img-openuserjs https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/images/external/openuserjs.png
|
|
|
|
+// @resource trans-de_DE https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/translations/de_DE.json
|
|
|
|
+// @resource trans-en_US https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/translations/en_US.json
|
|
|
|
+// @resource trans-en_UK https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/translations/en_UK.json
|
|
|
|
+// @resource trans-es_ES https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/translations/es_ES.json
|
|
|
|
+// @resource trans-fr_FR https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/translations/fr_FR.json
|
|
|
|
+// @resource trans-hi_IN https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/translations/hi_IN.json
|
|
|
|
+// @resource trans-ja_JA https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/translations/ja_JA.json
|
|
|
|
+// @resource trans-pt_BR https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/translations/pt_BR.json
|
|
|
|
+// @resource trans-zh_CN https://raw.githubusercontent.com/Sv443/BetterYTM/339ef3d0/assets/translations/zh_CN.json
|
|
// @require https://cdn.jsdelivr.net/npm/@sv443-network/[email protected]/dist/index.global.js
|
|
// @require https://cdn.jsdelivr.net/npm/@sv443-network/[email protected]/dist/index.global.js
|
|
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/fuse.basic.js
|
|
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/fuse.basic.js
|
|
// @require https://cdn.jsdelivr.net/npm/[email protected]/lib/marked.umd.js
|
|
// @require https://cdn.jsdelivr.net/npm/[email protected]/lib/marked.umd.js
|
|
@@ -186,7 +186,7 @@ var PluginIntent;
|
|
})(PluginIntent || (PluginIntent = {}));const modeRaw = "development";
|
|
})(PluginIntent || (PluginIntent = {}));const modeRaw = "development";
|
|
const branchRaw = "develop";
|
|
const branchRaw = "develop";
|
|
const hostRaw = "github";
|
|
const hostRaw = "github";
|
|
-const buildNumberRaw = "5f7a1c2a";
|
|
|
|
|
|
+const buildNumberRaw = "339ef3d0";
|
|
/** The mode in which the script was built (production or development) */
|
|
/** The mode in which the script was built (production or development) */
|
|
const mode = (modeRaw.match(/^#{{.+}}$/) ? "production" : modeRaw);
|
|
const mode = (modeRaw.match(/^#{{.+}}$/) ? "production" : modeRaw);
|
|
/** The branch to use in various URLs that point to the GitHub repo */
|
|
/** The branch to use in various URLs that point to the GitHub repo */
|
|
@@ -3201,25 +3201,6 @@ function addConfigMenuOptionYT(container) {
|
|
return error("Couldn't add config menu option to YT titlebar - couldn't find container element");
|
|
return error("Couldn't add config menu option to YT titlebar - couldn't find container element");
|
|
});
|
|
});
|
|
}
|
|
}
|
|
-//#region upgrade tab
|
|
|
|
-/** Removes the "Upgrade" / YT Music Premium tab from the sidebar */
|
|
|
|
-function removeUpgradeTab() {
|
|
|
|
- return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
- addSelectorListener("sideBar", "#contentContainer #guide-content #items ytmusic-guide-entry-renderer:nth-of-type(4)", {
|
|
|
|
- listener: (tabElemLarge) => {
|
|
|
|
- tabElemLarge.remove();
|
|
|
|
- log("Removed large upgrade tab");
|
|
|
|
- },
|
|
|
|
- });
|
|
|
|
- // TODO:FIXME: see https://github.com/Sv443/BetterYTM/issues/91
|
|
|
|
- addSelectorListener("sideBarMini", "#sections ytmusic-guide-section-renderer[is-primary] #items ytmusic-guide-entry-renderer:nth-of-type(4)", {
|
|
|
|
- listener: (tabElemSmall) => {
|
|
|
|
- tabElemSmall.remove();
|
|
|
|
- log("Removed small upgrade tab");
|
|
|
|
- },
|
|
|
|
- });
|
|
|
|
- });
|
|
|
|
-}
|
|
|
|
//#region anchor impr.
|
|
//#region anchor impr.
|
|
/** Adds anchors around elements and tweaks existing ones so songs are easier to open in a new tab */
|
|
/** Adds anchors around elements and tweaks existing ones so songs are easier to open in a new tab */
|
|
function addAnchorImprovements() {
|
|
function addAnchorImprovements() {
|
|
@@ -3710,15 +3691,22 @@ function initShowVotes() {
|
|
},
|
|
},
|
|
});
|
|
});
|
|
siteEvents.on("watchIdChanged", (watchId) => __awaiter(this, void 0, void 0, function* () {
|
|
siteEvents.on("watchIdChanged", (watchId) => __awaiter(this, void 0, void 0, function* () {
|
|
- const voteObj = yield fetchVideoVotes(watchId);
|
|
|
|
- if (!voteObj || !("likes" in voteObj) || !("dislikes" in voteObj) || !("rating" in voteObj))
|
|
|
|
- return error("Couldn't fetch votes from ReturnYouTubeDislikes API");
|
|
|
|
|
|
+ var _a, _b;
|
|
const labelLikes = document.querySelector("ytmusic-like-button-renderer .bytm-vote-label.likes");
|
|
const labelLikes = document.querySelector("ytmusic-like-button-renderer .bytm-vote-label.likes");
|
|
const labelDislikes = document.querySelector("ytmusic-like-button-renderer .bytm-vote-label.dislikes");
|
|
const labelDislikes = document.querySelector("ytmusic-like-button-renderer .bytm-vote-label.dislikes");
|
|
if (!labelLikes || !labelDislikes)
|
|
if (!labelLikes || !labelDislikes)
|
|
return error("Couldn't find vote label elements while updating like and dislike counts");
|
|
return error("Couldn't find vote label elements while updating like and dislike counts");
|
|
- labelLikes.textContent = voteObj.likes.toLocaleString(undefined, getVoteNumberFormat());
|
|
|
|
- labelDislikes.textContent = voteObj.dislikes.toLocaleString(undefined, getVoteNumberFormat());
|
|
|
|
|
|
+ if (labelLikes.dataset.watchId === watchId && labelDislikes.dataset.watchId === watchId)
|
|
|
|
+ return log("Vote labels already updated for this video");
|
|
|
|
+ const voteObj = yield fetchVideoVotes(watchId);
|
|
|
|
+ if (!voteObj || !("likes" in voteObj) || !("dislikes" in voteObj) || !("rating" in voteObj))
|
|
|
|
+ return error("Couldn't fetch votes from ReturnYouTubeDislikes API");
|
|
|
|
+ labelLikes.dataset.watchId = (_a = getWatchId()) !== null && _a !== void 0 ? _a : "";
|
|
|
|
+ labelLikes.textContent = formatVoteNumber(voteObj.likes);
|
|
|
|
+ labelLikes.title = labelLikes.ariaLabel = t("vote_label_likes", voteObj.likes);
|
|
|
|
+ labelDislikes.textContent = formatVoteNumber(voteObj.dislikes);
|
|
|
|
+ labelDislikes.title = labelDislikes.ariaLabel = t("vote_label_dislikes", voteObj.dislikes);
|
|
|
|
+ labelDislikes.dataset.watchId = (_b = getWatchId()) !== null && _b !== void 0 ? _b : "";
|
|
}));
|
|
}));
|
|
});
|
|
});
|
|
}
|
|
}
|
|
@@ -3728,10 +3716,12 @@ function addVoteNumbers(voteCont, voteObj) {
|
|
if (!likeBtn || !dislikeBtn)
|
|
if (!likeBtn || !dislikeBtn)
|
|
return error("Couldn't find like or dislike button while adding vote numbers");
|
|
return error("Couldn't find like or dislike button while adding vote numbers");
|
|
const createLabel = (amount, type) => {
|
|
const createLabel = (amount, type) => {
|
|
|
|
+ var _a;
|
|
const label = document.createElement("span");
|
|
const label = document.createElement("span");
|
|
label.classList.add("bytm-vote-label", "bytm-no-select", type);
|
|
label.classList.add("bytm-vote-label", "bytm-no-select", type);
|
|
- label.textContent = amount.toLocaleString(undefined, getVoteNumberFormat());
|
|
|
|
|
|
+ label.textContent = String(formatVoteNumber(amount));
|
|
label.title = label.ariaLabel = t(`vote_label_${type}`, amount);
|
|
label.title = label.ariaLabel = t(`vote_label_${type}`, amount);
|
|
|
|
+ label.dataset.watchId = (_a = getWatchId()) !== null && _a !== void 0 ? _a : "";
|
|
label.addEventListener("click", (e) => {
|
|
label.addEventListener("click", (e) => {
|
|
var _a;
|
|
var _a;
|
|
e.preventDefault();
|
|
e.preventDefault();
|
|
@@ -3746,19 +3736,21 @@ function addVoteNumbers(voteCont, voteObj) {
|
|
const dislikeLblEl = createLabel(voteObj.dislikes, "dislikes");
|
|
const dislikeLblEl = createLabel(voteObj.dislikes, "dislikes");
|
|
dislikeBtn.insertAdjacentElement("afterend", dislikeLblEl);
|
|
dislikeBtn.insertAdjacentElement("afterend", dislikeLblEl);
|
|
}
|
|
}
|
|
-function getVoteNumberFormat() {
|
|
|
|
- return getFeature("showVotesFormat") === "short"
|
|
|
|
|
|
+/** Formats a number with the notation based on the config */
|
|
|
|
+function formatVoteNumber(num) {
|
|
|
|
+ return num.toLocaleString(undefined, getFeature("showVotesFormat") === "short"
|
|
? {
|
|
? {
|
|
notation: "compact",
|
|
notation: "compact",
|
|
compactDisplay: "short",
|
|
compactDisplay: "short",
|
|
|
|
+ maximumFractionDigits: 1,
|
|
}
|
|
}
|
|
: {
|
|
: {
|
|
style: "decimal",
|
|
style: "decimal",
|
|
maximumFractionDigits: 0,
|
|
maximumFractionDigits: 0,
|
|
- };
|
|
|
|
|
|
+ });
|
|
}
|
|
}
|
|
function addVoteRatio(voteCont, voteObj) {
|
|
function addVoteRatio(voteCont, voteObj) {
|
|
- console.log("># TODO: addVoteRatio", voteCont, voteObj);
|
|
|
|
|
|
+ dbg("># TODO: addVoteRatio", voteCont, voteObj);
|
|
}//#region beforeunload popup
|
|
}//#region beforeunload popup
|
|
let beforeUnloadEnabled = true;
|
|
let beforeUnloadEnabled = true;
|
|
/** Disables the popup before leaving the site */
|
|
/** Disables the popup before leaving the site */
|
|
@@ -5102,12 +5094,6 @@ const featInfo = {
|
|
advanced: true,
|
|
advanced: true,
|
|
textAdornment: () => combineAdornments([adornments.advanced, adornments.reloadRequired]),
|
|
textAdornment: () => combineAdornments([adornments.advanced, adornments.reloadRequired]),
|
|
},
|
|
},
|
|
- removeUpgradeTab: {
|
|
|
|
- type: "toggle",
|
|
|
|
- category: "layout",
|
|
|
|
- default: true,
|
|
|
|
- textAdornment: adornments.reloadRequired,
|
|
|
|
- },
|
|
|
|
thumbnailOverlayBehavior: {
|
|
thumbnailOverlayBehavior: {
|
|
type: "select",
|
|
type: "select",
|
|
category: "layout",
|
|
category: "layout",
|
|
@@ -5699,18 +5685,22 @@ const migrations = {
|
|
"closeToastsTimeout", "disableDarkReaderSites",
|
|
"closeToastsTimeout", "disableDarkReaderSites",
|
|
]),
|
|
]),
|
|
// 5 -> 6 (v2.1)
|
|
// 5 -> 6 (v2.1)
|
|
- 6: (oldData) => useNewDefaultIfUnchanged(useDefaultConfig(oldData, [
|
|
|
|
- "autoLikeChannels", "autoLikeChannelToggleBtn",
|
|
|
|
- "autoLikeTimeout", "autoLikeShowToast",
|
|
|
|
- "autoLikeOpenMgmtDialog", "showVotes",
|
|
|
|
- "showVotesFormat", "showVoteRatio",
|
|
|
|
- "toastDuration", "initTimeout",
|
|
|
|
- // forgot to add this to the migration when adding the feature so now will have to do:
|
|
|
|
- "volumeSliderLabel",
|
|
|
|
- ]), [
|
|
|
|
- { key: "rememberSongTimeSites", oldDefault: "ytm" },
|
|
|
|
- { key: "volumeSliderScrollStep", oldDefault: 10 },
|
|
|
|
- ]),
|
|
|
|
|
|
+ 6: (oldData) => {
|
|
|
|
+ const newData = useNewDefaultIfUnchanged(useDefaultConfig(oldData, [
|
|
|
|
+ "autoLikeChannels", "autoLikeChannelToggleBtn",
|
|
|
|
+ "autoLikeTimeout", "autoLikeShowToast",
|
|
|
|
+ "autoLikeOpenMgmtDialog", "showVotes",
|
|
|
|
+ "showVotesFormat", "showVoteRatio",
|
|
|
|
+ "toastDuration", "initTimeout",
|
|
|
|
+ // forgot to add this to the migration when adding the feature so now will have to do:
|
|
|
|
+ "volumeSliderLabel",
|
|
|
|
+ ]), [
|
|
|
|
+ { key: "rememberSongTimeSites", oldDefault: "ytm" },
|
|
|
|
+ { key: "volumeSliderScrollStep", oldDefault: 10 },
|
|
|
|
+ ]);
|
|
|
|
+ "removeUpgradeTab" in newData && delete newData.removeUpgradeTab;
|
|
|
|
+ return newData;
|
|
|
|
+ },
|
|
// TODO(v2.2): use default for "autoLikePlayerBarToggleBtn"
|
|
// TODO(v2.2): use default for "autoLikePlayerBarToggleBtn"
|
|
// TODO: once advanced filtering is fully implemented, clear cache on migration to fv6
|
|
// TODO: once advanced filtering is fully implemented, clear cache on migration to fv6
|
|
// 6 -> 7 (vX.X)
|
|
// 6 -> 7 (vX.X)
|
|
@@ -5757,7 +5747,7 @@ function initConfig() {
|
|
let data = yield cfgDataStore.loadData();
|
|
let data = yield cfgDataStore.loadData();
|
|
// since the config changes so much in development keys need to be fixed in this special way
|
|
// since the config changes so much in development keys need to be fixed in this special way
|
|
if (mode === "development") {
|
|
if (mode === "development") {
|
|
- yield cfgDataStore.setData(fixMissingCfgKeys(data));
|
|
|
|
|
|
+ yield cfgDataStore.setData(fixCfgKeys(data));
|
|
data = cfgDataStore.getData();
|
|
data = cfgDataStore.getData();
|
|
}
|
|
}
|
|
log(`Initialized feature config DataStore (formatVersion = ${cfgDataStore.formatVersion})`);
|
|
log(`Initialized feature config DataStore (formatVersion = ${cfgDataStore.formatVersion})`);
|
|
@@ -5765,7 +5755,7 @@ function initConfig() {
|
|
info(" !- Config data was initialized with default values");
|
|
info(" !- Config data was initialized with default values");
|
|
else if (oldFmtVer !== cfgDataStore.formatVersion) {
|
|
else if (oldFmtVer !== cfgDataStore.formatVersion) {
|
|
try {
|
|
try {
|
|
- yield cfgDataStore.setData(data = fixMissingCfgKeys(data));
|
|
|
|
|
|
+ yield cfgDataStore.setData(data = fixCfgKeys(data));
|
|
info(` !- Config data was migrated from version ${oldFmtVer} to ${cfgDataStore.formatVersion}`);
|
|
info(` !- Config data was migrated from version ${oldFmtVer} to ${cfgDataStore.formatVersion}`);
|
|
}
|
|
}
|
|
catch (err) {
|
|
catch (err) {
|
|
@@ -5778,10 +5768,10 @@ function initConfig() {
|
|
});
|
|
});
|
|
}
|
|
}
|
|
/**
|
|
/**
|
|
- * Fixes missing keys in the passed config object with their default values and returns a copy of the fixed object.
|
|
|
|
|
|
+ * Fixes missing keys in the passed config object with their default values or removes extraneous keys and returns a copy of the fixed object.
|
|
* Returns a copy of the originally passed object if nothing needs to be fixed.
|
|
* Returns a copy of the originally passed object if nothing needs to be fixed.
|
|
*/
|
|
*/
|
|
-function fixMissingCfgKeys(cfg) {
|
|
|
|
|
|
+function fixCfgKeys(cfg) {
|
|
const newCfg = Object.assign({}, cfg);
|
|
const newCfg = Object.assign({}, cfg);
|
|
const passedKeys = Object.keys(cfg);
|
|
const passedKeys = Object.keys(cfg);
|
|
const defaultKeys = Object.keys(defaultData);
|
|
const defaultKeys = Object.keys(defaultData);
|
|
@@ -5790,6 +5780,11 @@ function fixMissingCfgKeys(cfg) {
|
|
for (const key of missingKeys)
|
|
for (const key of missingKeys)
|
|
newCfg[key] = defaultData[key];
|
|
newCfg[key] = defaultData[key];
|
|
}
|
|
}
|
|
|
|
+ const extraKeys = passedKeys.filter(k => !defaultKeys.includes(k));
|
|
|
|
+ if (extraKeys.length > 0) {
|
|
|
|
+ for (const key of extraKeys)
|
|
|
|
+ delete newCfg[key];
|
|
|
|
+ }
|
|
return newCfg;
|
|
return newCfg;
|
|
}
|
|
}
|
|
/** Returns the current feature config from the in-memory cache as a copy */
|
|
/** Returns the current feature config from the in-memory cache as a copy */
|
|
@@ -6422,7 +6417,7 @@ function onInteraction(elem, listener, listenerOptions) {
|
|
}let curLogLevel = LogLevel.Info;
|
|
}let curLogLevel = LogLevel.Info;
|
|
/** Common prefix to be able to tell logged messages apart and filter them in devtools */
|
|
/** Common prefix to be able to tell logged messages apart and filter them in devtools */
|
|
const consPrefix = `[${scriptInfo.name}]`;
|
|
const consPrefix = `[${scriptInfo.name}]`;
|
|
-`[${scriptInfo.name}/#DEBUG]`;
|
|
|
|
|
|
+const consPrefixDbg = `[${scriptInfo.name}/#DEBUG]`;
|
|
/** Sets the current log level. 0 = Debug, 1 = Info */
|
|
/** Sets the current log level. 0 = Debug, 1 = Info */
|
|
function setLogLevel(level) {
|
|
function setLogLevel(level) {
|
|
curLogLevel = level;
|
|
curLogLevel = level;
|
|
@@ -6460,6 +6455,10 @@ function warn(...args) {
|
|
/** Logs all passed values to the console as an error, no matter the log level. */
|
|
/** Logs all passed values to the console as an error, no matter the log level. */
|
|
function error(...args) {
|
|
function error(...args) {
|
|
console.error(consPrefix, ...args);
|
|
console.error(consPrefix, ...args);
|
|
|
|
+}
|
|
|
|
+/** Logs all passed values to the console with a debug-specific prefix */
|
|
|
|
+function dbg(...args) {
|
|
|
|
+ console.log(consPrefixDbg, ...args);
|
|
}//#region misc
|
|
}//#region misc
|
|
let cachedDomain;
|
|
let cachedDomain;
|
|
/**
|
|
/**
|
|
@@ -6715,17 +6714,41 @@ function fetchCss(key) {
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
+/** Cache for the vote data of YouTube videos to prevent unnecessary requests */
|
|
|
|
+const voteCache = new Map();
|
|
|
|
+/** Time-to-live for the vote cache in milliseconds */
|
|
|
|
+const voteCacheTTL = 1000 * 60 * 5;
|
|
/**
|
|
/**
|
|
- * Fetches the votes object for a YouTube video from the [Return YouTube Dislikes API.](https://returnyoutubedislike.com/docs)
|
|
|
|
|
|
+ * Fetches the votes object for a YouTube video from the [Return YouTube Dislike API.](https://returnyoutubedislike.com/docs)
|
|
* @param watchId The watch ID of the video
|
|
* @param watchId The watch ID of the video
|
|
*/
|
|
*/
|
|
function fetchVideoVotes(watchId) {
|
|
function fetchVideoVotes(watchId) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
try {
|
|
try {
|
|
- return JSON.parse((yield sendRequest({
|
|
|
|
|
|
+ if (voteCache.has(watchId)) {
|
|
|
|
+ const cached = voteCache.get(watchId);
|
|
|
|
+ if (Date.now() - cached.timestamp < voteCacheTTL)
|
|
|
|
+ return cached;
|
|
|
|
+ else
|
|
|
|
+ voteCache.delete(watchId);
|
|
|
|
+ }
|
|
|
|
+ const votesRaw = JSON.parse((yield sendRequest({
|
|
method: "GET",
|
|
method: "GET",
|
|
url: `https://returnyoutubedislikeapi.com/votes?videoId=${watchId}`,
|
|
url: `https://returnyoutubedislikeapi.com/votes?videoId=${watchId}`,
|
|
})).response);
|
|
})).response);
|
|
|
|
+ if (!("id" in votesRaw) || !("likes" in votesRaw) || !("dislikes" in votesRaw) || !("rating" in votesRaw)) {
|
|
|
|
+ error("Couldn't parse video votes due to an error:", votesRaw);
|
|
|
|
+ return undefined;
|
|
|
|
+ }
|
|
|
|
+ const votesObj = {
|
|
|
|
+ id: votesRaw.id,
|
|
|
|
+ likes: votesRaw.likes,
|
|
|
|
+ dislikes: votesRaw.dislikes,
|
|
|
|
+ rating: votesRaw.rating,
|
|
|
|
+ timestamp: Date.now(),
|
|
|
|
+ };
|
|
|
|
+ voteCache.set(votesObj.id, votesObj);
|
|
|
|
+ return votesObj;
|
|
}
|
|
}
|
|
catch (err) {
|
|
catch (err) {
|
|
error("Couldn't fetch video votes due to an error:", err);
|
|
error("Couldn't fetch video votes due to an error:", err);
|
|
@@ -6737,7 +6760,6 @@ function fetchVideoVotes(watchId) {
|
|
// console watermark with sexy gradient
|
|
// console watermark with sexy gradient
|
|
const styleGradient = "background: rgba(165, 38, 38, 1); background: linear-gradient(90deg, rgb(154, 31, 103) 0%, rgb(135, 31, 31) 40%, rgb(184, 64, 41) 100%);";
|
|
const styleGradient = "background: rgba(165, 38, 38, 1); background: linear-gradient(90deg, rgb(154, 31, 103) 0%, rgb(135, 31, 31) 40%, rgb(184, 64, 41) 100%);";
|
|
const styleCommon = "color: #fff; font-size: 1.3rem;";
|
|
const styleCommon = "color: #fff; font-size: 1.3rem;";
|
|
- console.log();
|
|
|
|
console.log(`%c${scriptInfo.name}%c${scriptInfo.version}%c • ${scriptInfo.namespace}%c\n\nBuild #${buildNumber}`, `${styleCommon} ${styleGradient} font-weight: bold; padding-left: 6px; padding-right: 6px;`, `${styleCommon} background-color: #333; padding-left: 8px; padding-right: 8px;`, "color: #fff; font-size: 1.2rem;", "padding: initial;");
|
|
console.log(`%c${scriptInfo.name}%c${scriptInfo.version}%c • ${scriptInfo.namespace}%c\n\nBuild #${buildNumber}`, `${styleCommon} ${styleGradient} font-weight: bold; padding-left: 6px; padding-right: 6px;`, `${styleCommon} background-color: #333; padding-left: 8px; padding-right: 8px;`, "color: #fff; font-size: 1.2rem;", "padding: initial;");
|
|
console.log([
|
|
console.log([
|
|
"Powered by:",
|
|
"Powered by:",
|
|
@@ -6749,7 +6771,6 @@ function fetchVideoVotes(watchId) {
|
|
"─ This markdown parser library: https://github.com/markedjs/marked",
|
|
"─ This markdown parser library: https://github.com/markedjs/marked",
|
|
"─ This fuzzy search library: https://github.com/krisk/Fuse",
|
|
"─ This fuzzy search library: https://github.com/krisk/Fuse",
|
|
].join("\n"));
|
|
].join("\n"));
|
|
- console.log();
|
|
|
|
}
|
|
}
|
|
//#region preInit
|
|
//#region preInit
|
|
/** Stuff that needs to be called ASAP, before anything async happens */
|
|
/** Stuff that needs to be called ASAP, before anything async happens */
|
|
@@ -6828,8 +6849,6 @@ function onDomLoad() {
|
|
ftInit.push(["addWatermark", addWatermark()]);
|
|
ftInit.push(["addWatermark", addWatermark()]);
|
|
if (feats.fixSpacing)
|
|
if (feats.fixSpacing)
|
|
ftInit.push(["fixSpacing", fixSpacing()]);
|
|
ftInit.push(["fixSpacing", fixSpacing()]);
|
|
- if (feats.removeUpgradeTab)
|
|
|
|
- ftInit.push(["removeUpgradeTab", removeUpgradeTab()]);
|
|
|
|
ftInit.push(["thumbnailOverlay", initThumbnailOverlay()]);
|
|
ftInit.push(["thumbnailOverlay", initThumbnailOverlay()]);
|
|
if (feats.hideCursorOnIdle)
|
|
if (feats.hideCursorOnIdle)
|
|
ftInit.push(["hideCursorOnIdle", initHideCursorOnIdle()]);
|
|
ftInit.push(["hideCursorOnIdle", initHideCursorOnIdle()]);
|
|
@@ -6939,7 +6958,7 @@ function registerDevMenuCommands() {
|
|
}), "r");
|
|
}), "r");
|
|
GM.registerMenuCommand("Fix missing config values", () => __awaiter(this, void 0, void 0, function* () {
|
|
GM.registerMenuCommand("Fix missing config values", () => __awaiter(this, void 0, void 0, function* () {
|
|
const oldFeats = JSON.parse(JSON.stringify(getFeatures()));
|
|
const oldFeats = JSON.parse(JSON.stringify(getFeatures()));
|
|
- yield setFeatures(fixMissingCfgKeys(oldFeats));
|
|
|
|
|
|
+ yield setFeatures(fixCfgKeys(oldFeats));
|
|
console.log("Fixed missing config values.\nFrom:", oldFeats, "\n\nTo:", getFeatures());
|
|
console.log("Fixed missing config values.\nFrom:", oldFeats, "\n\nTo:", getFeatures());
|
|
if (confirm("All missing or invalid config values were set to their default values.\nReload the page now?"))
|
|
if (confirm("All missing or invalid config values were set to their default values.\nReload the page now?"))
|
|
location.reload();
|
|
location.reload();
|