Skip to content

Commit

Permalink
[Hot Cards] Add utility files and update CDNs (#373)
Browse files Browse the repository at this point in the history
  • Loading branch information
HandyRandyx authored Jul 26, 2024
1 parent 11042b3 commit fc8e718
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 14 deletions.
10 changes: 1 addition & 9 deletions plugins/hotCards/hotCards.js
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@
gradientAnimation = "",
filter = ""
) {
const opacity = getBackgroundOpacity(cardOptions.opacity);
const opacity = getFixedBackgroundOpacity(cardOptions.opacity);
const fill = /true/i.test(cardOptions.fill);
const gradientAnimationStr = gradientAnimation
? `animation: move ${gradientAnimation};`
Expand Down Expand Up @@ -675,14 +675,6 @@
animate();
}

function getRandomInt(max) {
return Math.floor(Math.random() * max);
}

function getBackgroundOpacity(opacity) {
return parseFloat((1 - opacity / 100).toFixed(1));
}

function createCardStyle(
hoverColor,
hoverAnimation,
Expand Down
10 changes: 5 additions & 5 deletions plugins/hotCards/hotCards.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
name: Hot Cards
description: Adds custom styling to card elements that match a Tag ID or a Rating Threshold.
version: 1.1.6
version: 1.1.7
url: https://github.com/stashapp/CommunityScripts/tree/main/plugins/hotCards
# requires: CommunityScriptsUILibrary
ui:
requires:
- CommunityScriptsUILibrary
javascript:
- https://cdn.jsdelivr.net/gh/HandyRandyx/stash-plugins@main/utils/fetchInterceptor.js
- https://cdn.jsdelivr.net/gh/HandyRandyx/stash-plugins@main/utils/stashHandler.js
- https://cdn.jsdelivr.net/gh/HandyRandyx/stash-plugins@main/utils/registerPathChangeListener.js
- https://cdn.jsdelivr.net/gh/HandyRandyx/stash-plugins@main/utils/waitForClass.js
- https://cdn.jsdelivr.net/gh/stashapp/CommunityScripts@main/plugins/hotCards/utils/fetchInterceptor.js
- https://cdn.jsdelivr.net/gh/stashapp/CommunityScripts@main/plugins/hotCards/utils/stashHandler.js
- https://cdn.jsdelivr.net/gh/stashapp/CommunityScripts@main/plugins/hotCards/utils/registerPathChangeListener.js
- https://cdn.jsdelivr.net/gh/stashapp/CommunityScripts@main/plugins/hotCards/utils/helpers.js
- hotCards.js
css:
- hotCards.css
Expand Down
31 changes: 31 additions & 0 deletions plugins/hotCards/utils/fetchInterceptor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
(() => {
if (window.stashListener) return;

const { fetch: originalFetch } = window;
const stashListener = new EventTarget();

window.fetch = async (...args) => {
let [resource, config] = args;
const response = await originalFetch(resource, config);
const contentType = response.headers.get("content-type");

if (
typeof resource === "string" &&
contentType &&
contentType.indexOf("application/json") !== -1 &&
resource.endsWith("/graphql")
) {
try {
const data = await response.clone().json();
stashListener.dispatchEvent(
new CustomEvent("response", { detail: data })
);
} catch (e) {
console.error("Error parsing JSON:", e);
}
}
return response;
};

window.stashListener = stashListener;
})();
37 changes: 37 additions & 0 deletions plugins/hotCards/utils/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/** General */

function getRandomInt(max) {
return Math.floor(Math.random() * max);
}

function getFixedBackgroundOpacity(opacity) {
return parseFloat((1 - opacity / 100).toFixed(1));
}

/** Elements */

function waitForClass(className, callback) {
const checkInterval = 100; // ms
const maxRetries = 30; // Timeout after 3 seconds
let retryCount = 0;

const intervalId = setInterval(() => {
const elements = document.getElementsByClassName(className);
if (elements.length > 0) {
clearInterval(intervalId);
callback();
} else if (retryCount >= maxRetries) {
clearInterval(intervalId);
console.info(
`Element with class ${className} not found within timeout period`
);
}
retryCount++;
}, checkInterval);
}

function waitForImageLoad(selector, callback) {
var imgEl = document.querySelector(selector);
if (imgEl?.complete) return callback(imgEl);
setTimeout(waitForImageLoad, 100, selector, callback);
}
24 changes: 24 additions & 0 deletions plugins/hotCards/utils/registerPathChangeListener.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
function registerPathChangeListener(pattern, callback) {
const regex = new RegExp(pattern);

function checkURL() {
const currentPathName = window.location.pathname;
if (regex.test(currentPathName)) callback();
}

// Listen to popstate event for back/forward navigation
window.addEventListener("popstate", checkURL);

// Hijack pushState and replaceState methods
["pushState", "replaceState"].forEach((method) => {
const original = history[method];
history[method] = function () {
const result = original.apply(this, arguments);
checkURL();
return result;
};
});

// Initial check
checkURL();
}
55 changes: 55 additions & 0 deletions plugins/hotCards/utils/stashHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const stash = {
galleries: {},
images: {},
movies: {},
performers: {},
scenes: {},
studios: {},
};

stashListener.addEventListener("response", (event) => {
const dataProcessors = {
galleries: processData("findGalleries", "galleries"),
images: processData("findImages", "images"),
movies: processData("findMovies", "movies"),
performers: processData("findPerformers", "performers"),
scenes: processData("findScenes", "scenes"),
studios: processData("findStudios", "studios"),
};

for (const key in dataProcessors) {
dataProcessors[key](event.detail);
}

processOtherData(event.detail);
});

function processData(findKey, dataKey) {
return function (data) {
if (data.data[findKey]?.[dataKey]) {
for (const item of data.data[findKey][dataKey]) {
stash[dataKey][item.id] = item;
}
}
};
}

function processOtherData(data) {
const otherDataMappings = [
{ findKey: "findScene", key: "movies", nested: true },
{ findKey: "findScene", key: "galleries", nested: false },
{ findKey: "findScene", key: "performers", nested: false },
{ findKey: "findImage", key: "performers", nested: false },
{ findKey: "findGallery", key: "performers", nested: false },
{ findKey: "findGallery", key: "scenes", nested: false },
];

for (const mapping of otherDataMappings) {
if (data.data[mapping.findKey]?.[mapping.key]) {
for (const item of data.data[mapping.findKey][mapping.key]) {
const value = mapping.nested ? item[mapping.key.slice(0, -1)] : item;
stash[mapping.key][value.id] = value;
}
}
}
}

0 comments on commit fc8e718

Please sign in to comment.