Files
return-youtube-dislike/Extensions/combined/src/state.js
T

402 lines
12 KiB
JavaScript
Raw Normal View History

import { getLikeButton, getDislikeButton, getButtons, getLikeTextContainer, getDislikeTextContainer } from "./buttons";
import { createRateBar } from "./bar";
import {
2022-01-19 00:40:06 -05:00
getBrowser,
getVideoId,
cLog,
numberFormat,
getColorFromTheme,
querySelector,
localize,
createObserver,
} from "./utils";
2022-01-08 23:22:29 +03:00
//TODO: Do not duplicate here and in ryd.background.js
const apiUrl = "https://returnyoutubedislikeapi.com";
const LIKED_STATE = "LIKED_STATE";
const DISLIKED_STATE = "DISLIKED_STATE";
const NEUTRAL_STATE = "NEUTRAL_STATE";
2021-12-15 21:53:43 +05:30
let extConfig = {
disableVoteSubmission: false,
disableLogging: false,
coloredThumbs: false,
coloredBar: false,
colorTheme: "classic",
numberDisplayFormat: "compactShort",
2022-04-21 18:45:42 +02:00
showTooltipPercentage: false,
tooltipPercentageMode: "dash_like",
2022-04-19 00:57:28 -05:00
numberDisplayReformatLikes: false,
selectors: {
dislikeTextContainer: [],
likeTextContainer: [],
buttons: {
shorts: {
mobile: [],
desktop: [],
},
regular: {
mobile: [],
desktopMenu: [],
desktopNoMenu: [],
},
likeButton: {
segmented: [],
segmentedGetButtons: [],
notSegmented: [],
},
dislikeButton: {
segmented: [],
segmentedGetButtons: [],
notSegmented: [],
},
},
menuContainer: [],
roundedDesign: [],
},
2021-12-15 21:53:43 +05:30
};
let storedData = {
likes: 0,
dislikes: 0,
previousState: NEUTRAL_STATE,
};
function isMobile() {
return location.hostname == "m.youtube.com";
}
2022-03-18 10:27:58 -04:00
function isShorts() {
return location.pathname.startsWith("/shorts");
2022-03-18 10:27:58 -04:00
}
2022-07-24 18:48:10 +02:00
function isNewDesign() {
return document.getElementById("comment-teaser") !== null;
}
2022-10-09 01:12:22 +02:00
function isRoundedDesign() {
return querySelector(extConfig.selectors.roundedDesign) !== null;
2022-10-09 01:12:22 +02:00
}
let shortsObserver = null;
2022-04-24 15:57:19 -05:00
if (isShorts() && !shortsObserver) {
cLog("Initializing shorts mutation observer");
shortsObserver = createObserver(
{
attributes: true,
},
(mutationList) => {
mutationList.forEach((mutation) => {
if (
mutation.type === "attributes" &&
mutation.target.nodeName === "TP-YT-PAPER-BUTTON" &&
mutation.target.id === "button"
) {
// cLog('Short thumb button status changed');
if (mutation.target.getAttribute("aria-pressed") === "true") {
mutation.target.style.color =
mutation.target.parentElement.parentElement.id === "like-button"
? getColorFromTheme(true)
: getColorFromTheme(false);
} else {
mutation.target.style.color = "unset";
}
return;
2022-04-24 15:57:19 -05:00
}
cLog("Unexpected mutation observer event: " + mutation.target + mutation.type);
});
},
);
2022-04-26 23:05:26 +02:00
}
2022-04-12 13:43:50 +02:00
function isLikesDisabled() {
// return true if the like button's text doesn't contain any number
if (isMobile()) {
return /^\D*$/.test(getButtons().children[0].querySelector(".button-renderer-text").innerText);
2022-04-12 13:43:50 +02:00
}
2023-12-12 23:25:17 +01:00
return /^\D*$/.test(getLikeTextContainer().innerText);
2022-04-24 15:57:19 -05:00
}
function isVideoLiked() {
if (isMobile()) {
return getLikeButton().querySelector("button").getAttribute("aria-label") === "true";
}
return (
getLikeButton().classList.contains("style-default-active") ||
getLikeButton().querySelector("button")?.getAttribute("aria-pressed") === "true"
);
}
function isVideoDisliked() {
if (isMobile()) {
return getDislikeButton().querySelector("button").getAttribute("aria-label") === "true";
}
return (
getDislikeButton().classList.contains("style-default-active") ||
getDislikeButton().querySelector("button")?.getAttribute("aria-pressed") === "true"
);
}
function getState(storedData) {
if (isVideoLiked()) {
return { current: LIKED_STATE, previous: storedData.previousState };
}
if (isVideoDisliked()) {
return { current: DISLIKED_STATE, previous: storedData.previousState };
}
return { current: NEUTRAL_STATE, previous: storedData.previousState };
}
//--- Sets The Likes And Dislikes Values ---//
function setLikes(likesCount) {
cLog(`SET likes ${likesCount}`);
getLikeTextContainer().innerText = likesCount;
}
function setDislikes(dislikesCount) {
cLog(`SET dislikes ${dislikesCount}`);
2022-10-09 01:12:22 +02:00
getDislikeTextContainer()?.removeAttribute("is-empty");
2022-04-12 13:43:50 +02:00
if (!isLikesDisabled()) {
2022-01-01 08:37:16 +03:00
if (isMobile()) {
getButtons().children[1].querySelector(".button-renderer-text").innerText = dislikesCount;
2022-01-01 08:37:16 +03:00
return;
}
getDislikeTextContainer().innerText = dislikesCount;
2022-01-01 08:37:16 +03:00
} else {
2022-02-11 23:58:00 +05:30
cLog("likes count disabled by creator");
2022-01-01 08:37:16 +03:00
if (isMobile()) {
getButtons().children[1].querySelector(".button-renderer-text").innerText = localize("TextLikesDisabled");
2022-01-01 08:37:16 +03:00
return;
}
getDislikeTextContainer().innerText = localize("TextLikesDisabled");
}
}
function getLikeCountFromButton() {
2022-08-05 22:57:27 +02:00
try {
if (isShorts()) {
//Youtube Shorts don't work with this query. It's not necessary; we can skip it and still see the results.
2022-08-05 22:57:27 +02:00
//It should be possible to fix this function, but it's not critical to showing the dislike count.
return false;
}
let likeButton =
getLikeButton().querySelector("yt-formatted-string#text") ?? getLikeButton().querySelector("button");
let likesStr = likeButton.getAttribute("aria-label").replace(/\D/g, "");
2022-08-05 22:57:27 +02:00
return likesStr.length > 0 ? parseInt(likesStr) : false;
2022-10-09 01:12:22 +02:00
} catch {
2022-08-05 22:57:27 +02:00
return false;
}
}
function processResponse(response, storedData) {
const formattedDislike = numberFormat(response.dislikes);
setDislikes(formattedDislike);
2022-04-19 00:57:28 -05:00
if (extConfig.numberDisplayReformatLikes === true) {
const nativeLikes = getLikeCountFromButton();
if (nativeLikes !== false) {
setLikes(numberFormat(nativeLikes));
}
}
storedData.dislikes = parseInt(response.dislikes);
storedData.likes = getLikeCountFromButton() || parseInt(response.likes);
createRateBar(storedData.likes, storedData.dislikes);
if (extConfig.coloredThumbs === true) {
2022-04-26 23:05:26 +02:00
if (isShorts()) {
// for shorts, leave deactivated buttons in default color
let shortLikeButton = getLikeButton().querySelector("tp-yt-paper-button#button");
let shortDislikeButton = getDislikeButton().querySelector("tp-yt-paper-button#button");
2022-04-26 23:05:26 +02:00
if (shortLikeButton.getAttribute("aria-pressed") === "true") {
2022-04-24 15:57:19 -05:00
shortLikeButton.style.color = getColorFromTheme(true);
}
2022-04-26 23:05:26 +02:00
if (shortDislikeButton.getAttribute("aria-pressed") === "true") {
2022-04-24 15:57:19 -05:00
shortDislikeButton.style.color = getColorFromTheme(false);
}
shortsObserver.observe(shortLikeButton);
shortsObserver.observe(shortDislikeButton);
2022-04-24 15:57:19 -05:00
} else {
getLikeButton().style.color = getColorFromTheme(true);
getDislikeButton().style.color = getColorFromTheme(false);
}
}
//Temporary disabling this - it breaks all places where getButtons()[1] is used
// createStarRating(response.rating, isMobile());
}
// Tells the user if the API is down
function displayError(error) {
getDislikeTextContainer().innerText = localize("textTempUnavailable");
}
2022-01-08 23:22:29 +03:00
async function setState(storedData) {
storedData.previousState = isVideoDisliked() ? DISLIKED_STATE : isVideoLiked() ? LIKED_STATE : NEUTRAL_STATE;
let statsSet = false;
cLog("Video is loaded. Adding buttons...");
2022-01-08 23:22:29 +03:00
let videoId = getVideoId(window.location.href);
let likeCount = getLikeCountFromButton() || null;
let response = await fetch(`${apiUrl}/votes?videoId=${videoId}&likeCount=${likeCount || ""}`, {
method: "GET",
headers: {
Accept: "application/json",
},
})
.then((response) => {
if (!response.ok) displayError(response.error);
return response;
})
2022-01-08 23:22:29 +03:00
.then((response) => response.json())
.catch(displayError);
2022-01-08 23:22:29 +03:00
cLog("response from api:");
cLog(JSON.stringify(response));
if (response !== undefined && !("traceId" in response) && !statsSet) {
processResponse(response, storedData);
}
}
async function setInitialState() {
await setState(storedData);
2021-12-18 01:28:43 +01:00
}
async function initExtConfig() {
2021-12-15 21:53:43 +05:30
initializeDisableVoteSubmission();
initializeDisableLogging();
initializeColoredThumbs();
initializeColoredBar();
initializeColorTheme();
2022-01-11 17:48:24 -05:00
initializeNumberDisplayFormat();
2022-04-21 18:45:42 +02:00
initializeTooltipPercentage();
initializeTooltipPercentageMode();
2022-04-19 00:57:28 -05:00
initializeNumberDisplayReformatLikes();
await initializeSelectors();
}
async function initializeSelectors() {
console.log("initializing selectors");
let result = await fetch(`${apiUrl}/configs/selectors`, {
method: "GET",
headers: {
Accept: "application/json",
},
})
.then((response) => response.json())
.catch((error) => {});
extConfig.selectors = result ?? extConfig.selectors;
console.log(result);
2021-12-15 21:53:43 +05:30
}
function initializeDisableVoteSubmission() {
2022-01-08 18:36:54 +03:00
getBrowser().storage.sync.get(["disableVoteSubmission"], (res) => {
2021-12-15 21:53:43 +05:30
if (res.disableVoteSubmission === undefined) {
2022-01-08 18:36:54 +03:00
getBrowser().storage.sync.set({ disableVoteSubmission: false });
} else {
2021-12-15 21:53:43 +05:30
extConfig.disableVoteSubmission = res.disableVoteSubmission;
}
});
}
function initializeDisableLogging() {
getBrowser().storage.sync.get(["disableLogging"], (res) => {
if (res.disableLogging === undefined) {
getBrowser().storage.sync.set({ disableLogging: true });
} else {
extConfig.disableLogging = res.disableLogging;
}
});
}
2022-01-19 00:40:06 -05:00
function initializeColoredThumbs() {
getBrowser().storage.sync.get(["coloredThumbs"], (res) => {
2022-01-19 00:40:06 -05:00
if (res.coloredThumbs === undefined) {
getBrowser().storage.sync.set({ coloredThumbs: false });
} else {
2022-01-19 00:40:06 -05:00
extConfig.coloredThumbs = res.coloredThumbs;
}
});
}
function initializeColoredBar() {
getBrowser().storage.sync.get(["coloredBar"], (res) => {
2022-01-19 00:40:06 -05:00
if (res.coloredBar === undefined) {
getBrowser().storage.sync.set({ coloredBar: false });
} else {
2022-01-19 00:40:06 -05:00
extConfig.coloredBar = res.coloredBar;
}
});
}
2022-01-19 00:40:06 -05:00
function initializeColorTheme() {
getBrowser().storage.sync.get(["colorTheme"], (res) => {
2022-01-19 00:40:06 -05:00
if (res.colorTheme === undefined) {
getBrowser().storage.sync.set({ colorTheme: false });
} else {
2022-01-19 00:40:06 -05:00
extConfig.colorTheme = res.colorTheme;
}
});
}
2022-01-11 17:48:24 -05:00
function initializeNumberDisplayFormat() {
getBrowser().storage.sync.get(["numberDisplayFormat"], (res) => {
2022-01-11 17:48:24 -05:00
if (res.numberDisplayFormat === undefined) {
getBrowser().storage.sync.set({ numberDisplayFormat: "compactShort" });
} else {
2022-01-11 17:48:24 -05:00
extConfig.numberDisplayFormat = res.numberDisplayFormat;
}
2022-01-19 00:40:06 -05:00
});
}
2022-04-21 18:45:42 +02:00
function initializeTooltipPercentage() {
getBrowser().storage.sync.get(["showTooltipPercentage"], (res) => {
if (res.showTooltipPercentage === undefined) {
getBrowser().storage.sync.set({ showTooltipPercentage: false });
} else {
extConfig.showTooltipPercentage = res.showTooltipPercentage;
}
});
}
function initializeTooltipPercentageMode() {
getBrowser().storage.sync.get(["tooltipPercentageMode"], (res) => {
if (res.tooltipPercentageMode === undefined) {
getBrowser().storage.sync.set({ tooltipPercentageMode: "dash_like" });
} else {
extConfig.tooltipPercentageMode = res.tooltipPercentageMode;
}
});
}
2022-04-19 00:57:28 -05:00
function initializeNumberDisplayReformatLikes() {
getBrowser().storage.sync.get(["numberDisplayReformatLikes"], (res) => {
if (res.numberDisplayReformatLikes === undefined) {
getBrowser().storage.sync.set({ numberDisplayReformatLikes: false });
} else {
extConfig.numberDisplayReformatLikes = res.numberDisplayReformatLikes;
}
});
}
export {
isMobile,
2022-03-18 10:27:58 -04:00
isShorts,
isVideoDisliked,
isVideoLiked,
2022-07-24 18:48:10 +02:00
isNewDesign,
2022-10-09 01:12:22 +02:00
isRoundedDesign,
getState,
setState,
2021-12-18 01:28:43 +01:00
setInitialState,
setLikes,
setDislikes,
getLikeCountFromButton,
LIKED_STATE,
DISLIKED_STATE,
NEUTRAL_STATE,
2021-12-15 21:53:43 +05:30
extConfig,
initExtConfig,
storedData,
2022-04-26 23:05:26 +02:00
isLikesDisabled,
};