[plugin - themeSwitch] rm hardcoded css (#259)

* install themes istead of hardcoded css

* dynamically import css files
This commit is contained in:
Raghavan
2024-02-22 13:11:42 +05:30
committed by GitHub
parent 02894d1317
commit 5f4e7d0379
36 changed files with 14222 additions and 21337 deletions

View File

@@ -7,5 +7,6 @@ yarn.lock
# production
dist
# workflows
.github
# 3rd party
# https://github.com/killhellokitty/stash-material-ize-theme/blob/main/stash-theme.css
plugins/themeSwitch/assets/themes/materialize

View File

@@ -119,8 +119,8 @@ if "https://metadataapi.net/graphql" in [
_id = json_input["args"]["hookContext"]["id"]
_type = json_input["args"]["hookContext"]["type"]
if _type == "Scene.Update.Post" and not settings["disableSceneMarkerHook"]:
scene = stash.find_scene(_id)
processScene(scene)
scene = stash.find_scene(_id)
processScene(scene)
else:
log.warning("The Porn DB endpoint not configured")

View File

@@ -0,0 +1,13 @@
/* [Galleries tab] Grid view for galleries */
.col.col-sm-6.mx-auto.table .d-none.d-sm-block {
display: none !important;
}
.col.col-sm-6.mx-auto.table .w-100.w-sm-auto {
width: 175px !important;
background-color: rgba(0, 0, 0, 0.45);
box-shadow: 0 0 2px rgba(0, 0, 0, 0.35);
}
.col.col-sm-6.mx-auto.table tr {
display: inline-table;
}

View File

@@ -0,0 +1,42 @@
/* [Global changes] Blur NSFW images */
.scene-card-preview-video,
.scene-card-preview-image,
.image-card-preview-image,
.image-thumbnail,
.gallery-card-image,
.performer-card-image,
.tag-card-image,
img.performer,
.movie-card-image,
.gallery .flexbin img,
.wall-item-media,
.scene-studio-overlay .image-thumbnail,
.image-card-preview-image,
#scene-details-container .text-input,
#scene-details-container .scene-header,
#scene-details-container .react-select__single-value,
.scene-details .pre,
#scene-tabs-tabpane-scene-file-info-panel span.col-8.text-truncate > a,
.gallery .flexbin img,
.movie-details .logo {
filter: blur(12px);
}
.scene-card-video {
filter: blur(13px);
}
.jw-video,
.jw-preview,
.jw-flag-floating,
.image-container,
.studio-logo,
.scene-cover {
filter: blur(20px);
}
.movie-card .text-truncate,
.scene-card .card-section {
filter: blur(4px);
}

View File

@@ -0,0 +1,5 @@
/* [Global changes] Hide the Donate button */
.btn-primary.btn.donate.minimal {
display: none;
}

View File

@@ -0,0 +1,4 @@
/* [Global changes] Hide 0 count badges */
span.badge[data-value="0"] {
display: none;
}

View File

@@ -0,0 +1,9 @@
/* [Global changes] Make the Toolbar Sticky v 0.1*/
.justify-content-center.btn-toolbar {
position: sticky;
top: 40px;
z-index: 100;
padding: 12px;
padding-bottom: 1px;
}

View File

@@ -0,0 +1,106 @@
/* [Global changes] Blur NSFW images and unblur on mouse over */
/* === MORE BLUR === */
/* scene */
.scene-card-preview,
.vjs-poster,
video,
.scene-cover,
.scrubber-item,
/* image */
.image-card-preview,
.image-image,
.gallery-image,
/* movie */
.movie-card-image,
.movie-images,
/* gallery */
.gallery-card-image,
table > tbody > tr > td > a > img.w-100,
/* performer */
.performer-card-image,
img.performer,
/* studio */
.studio-card-image,
/* tag */
.tag-card-image {
filter: blur(30px);
}
/* === LESS BLUR === */
/* common */
.card-section-title,
/* scene */
.scene-studio-overlay,
.scene-header > h3,
h3.scene-header,
.studio-logo,
.image-thumbnail,
/* image */
h3.image-header,
/* movie */
.movie-details > div > h2,
/* gallery */
h3.gallery-header,
/* studio */
.studio-details .logo,
.studio-details > div > h2,
/* tag */
.logo-container > .logo,
.logo-container > h2 {
filter: blur(2px);
}
/* === UNBLUR ON HOVER === */
/* common */
.thumbnail-section:hover *,
.card:hover .card-section-title,
/* scene */
.card:hover .scene-studio-overlay,
.video-js:hover .vjs-poster,
video:hover,
.scene-header:hover > h3,
div:hover > .scene-header,
.studio-logo:hover,
.scene-cover:hover,
.image-thumbnail:hover,
.scene-card-preview:hover,
.scrubber-item:hover,
/* image */
.image-image:hover,
div:hover > .image-header,
.gallery-image:hover,
/* movie */
.movie-images:hover,
.movie-details > div > h2:hover,
/* gallery */
div:hover > .gallery-header,
table > tbody > tr > td:hover > a > img.w-100,
/* performer */
img.performer:hover,
/* studio */
.studio-details .logo:hover,
.studio-details:hover > div > h2,
/* tag */
.logo-container > .logo:hover,
.logo-container:hover > h2 {
filter: blur(0px);
}

View File

@@ -0,0 +1,5 @@
/* [Images tab] Disable lightbox animation */
.Lightbox-carousel {
transition: none;
}

View File

@@ -0,0 +1,7 @@
/* [Images tab] Don't crop preview thumbnails */
.flexbin > * > img {
object-fit: inherit;
max-width: none;
min-width: initial;
}

View File

@@ -0,0 +1,15 @@
/* [Movies tab] Better Movie layout for desktops: Larger size poster */
.movie-details.mb-3.col.col-xl-4.col-lg-6 {
flex-basis: 70%;
}
.col-xl-8.col-lg-6 {
flex-basis: 30%;
}
.movie-images {
flex-direction: column;
flex-wrap: wrap;
}
.movie-image-container {
flex: 1 1 700px;
}

View File

@@ -0,0 +1,14 @@
/* [Movies tab] Better Movie layout for desktops: Regular size poster */
.movie-details.mb-3.col.col-xl-4.col-lg-6 {
flex-basis: 70%;
}
.col-xl-8.col-lg-6 {
flex-basis: 30%;
}
.movie-images {
flex-wrap: wrap;
}
.movie-image-container {
flex: 0 0 500px;
}

View File

@@ -0,0 +1,12 @@
/* [Performers tab] Move the tags row in the Performer's edit panel to the second position (just after name). */
form#performer-edit {
display: flex;
flex-direction: column;
}
#performer-edit > .row:nth-child(24) {
order: -1;
}
#performer-edit > .row:first-child {
order: -2;
}

View File

@@ -0,0 +1,35 @@
/* [Performers tab] Place performer image in the background on performer page */
.performer-image-container.col-md-4.text-center {
flex: 0 0 0%;
max-width: 0%;
}
#performer-page .performer-image-container .btn.btn-link {
position: fixed;
width: 100%;
top: 0;
left: 0;
padding: 0;
}
#performer-page .performer-image-container .btn.btn-link:before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(
to left,
rgba(0, 0, 0, 0) 0%,
rgb(0 0 0 / 75%) 100%
);
z-index: 1;
}
#performer-page .performer-image-container .performer {
max-height: none;
max-width: none;
width: 100%;
}

View File

@@ -0,0 +1,5 @@
/* [Performers tab] Show entire performer image in performer card */
.performer.image {
background-size: contain !important;
}

View File

@@ -0,0 +1,11 @@
/* [Scenes tab] Adjust the mouse over behaviour in wall mode */
@media (min-width: 576px) {
.wall-item:hover::before {
opacity: 0;
}
.wall-item:hover .wall-item-container {
transform: scale(1.5);
}
}

View File

@@ -0,0 +1,8 @@
/* [Scenes tab] Disable zoom on hover in wall mode */
.wall-item:hover .wall-item-container {
transform: none;
}
.wall-item:before {
opacity: 0 !important;
}

View File

@@ -0,0 +1,5 @@
/* [Scenes tab] Hide the scene scrubber and max out the player's height */
.scrubber-wrapper {
display: none;
}

View File

@@ -0,0 +1,5 @@
/* [Scenes tab] Hide scene specs (resolution, duration) from scene card */
.scene-specs-overlay {
display: none;
}

View File

@@ -0,0 +1,5 @@
/* [Scenes tab] Hide studio logo/text from scene card */
.scene-studio-overlay {
display: none;
}

View File

@@ -0,0 +1,6 @@
/*This will hide the truncated text that appears under the tile and date. */
/* [Scenes Tab] - Hide the truncated text on scene card */
.TruncatedText.scene-card__description {
display: none;
}

View File

@@ -0,0 +1,8 @@
/* [Scenes tab] Allow for longer string when displaying "Studio as Text" on scene thumbnails */
.scene-studio-overlay {
font-weight: 600 !important;
opacity: 1 !important;
width: 60% !important;
text-overflow: ellipsis !important;
}

View File

@@ -0,0 +1,6 @@
.extra-scene-info {
display: inline;
}
.file-path {
display: block;
}

View File

@@ -0,0 +1,14 @@
/* [Scenes tab] Swap studio and resolution/duration positions */
.scene-studio-overlay {
bottom: 1rem;
right: 0.7rem;
height: inherit;
top: inherit;
}
.scene-specs-overlay {
right: 0.7rem;
top: 0.7rem;
bottom: inherit;
}

View File

@@ -0,0 +1,5 @@
/* [Scenes tab] Make the list of tags take up less width */
.bs-popover-bottom {
max-width: 500px;
}

View File

@@ -0,0 +1,35 @@
/* Author: Qx#1573 */
/* [Studios tab] Changes the layout of studio cards */
.studio-card.grid-card.card div.card-section div.rating-banner {
display: none;
}
.slick-slide .studio-card-image {
height: 300px;
}
.studio-card,
.recommendation-row .studio-card {
padding: 0;
width: 500px;
height: 300px;
}
.studio-card-image,
.recommendation-row .studio-card .studio-card-image {
max-height: 300px;
width: 500px;
}
.studio-card.grid-card.card div.card-section {
position: absolute;
bottom: 0em;
width: inherit;
background-color: rgba(0, 0, 0, 0.7);
overflow: hidden;
height: 2.5em;
transition: 0.5s ease-in-out;
}
.studio-card.grid-card.card div.card-section:hover {
height: 7em;
}

View File

@@ -0,0 +1,11 @@
/* [Studios tab] Show more item per row - Author hijack_hornet */
:not(.recommendation-row .studio-card).studio-card {
width: 15%;
}
:not(.recommendation-row .studio-card-image).studio-card-image {
width: 100%;
}
.studio-card h5 {
text-align: center !important;
display: block;
}

View File

@@ -0,0 +1,108 @@
/*Tag layout changes - Author hijack_hornet */
.tag-card {
width: 16rem;
padding: 0;
}
.tag-card .card-section {
height: 2.5rem;
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: #0000007a;
line-height: none;
}
.tag-card .card-section .TruncatedText {
-webkit-line-clamp: 1 !important;
}
.tag-card h1,
h2,
h3,
h4,
h5,
h6,
.h1,
.h2,
.h3,
.h4,
.h5,
.h6 {
line-height: normal;
}
.tag-card hr,
.tag-description {
display: none;
}
.tag-card .btn-group {
position: absolute;
width: 100%;
bottom: 2.5rem;
margin-bottom: 0;
opacity: 0;
transition: ease 0.2s;
}
.tag-card .btn-group:hover {
opacity: 1;
transition: ease 0.2s;
background: #0000007a;
}
.tag-card-image {
object-fit: cover;
object-position: center;
}
.zoom-0 .tag-card-image {
max-height: none;
height: 16rem;
width: 12rem;
}
.zoom-1 .tag-card-image {
max-height: none;
height: 20rem;
width: 15rem;
}
.zoom-2 .tag-card-image {
max-height: none;
height: 24rem;
width: 18rem;
}
.zoom-3 .tag-card-image {
max-height: none;
height: 28rem;
width: 21rem;
}
.zoom-0.tag-card,
.zoom-1.tag-card,
.zoom-2.tag-card,
.zoom-3.tag-card {
width: initial;
}
.tag-card .card-section > a {
position: absolute;
width: 100%;
height: 100%;
display: block;
left: 0;
right: 0;
top: 0;
bottom: 0;
padding: 7px 14px 0px 14px;
}
.tag-card .card-section .tag-sub-tags {
position: relative;
margin-top: 2rem;
z-index: 1;
}
.tag-sub-tags {
font-size: 0;
}
.tag-parent-tags {
display: none;
}

View File

@@ -0,0 +1,69 @@
/* Author: Qx#1573 */
/* [Tags changes] changes the layout of tag cards on tags page and hover */
.tag-parent-tags,
.tag-sub-tags {
display: none;
}
.tag-card.zoom-0.grid-card.card div.card-section div.card-popovers.btn-group {
margin-top: 1em;
}
.tag-card.zoom-0.grid-card.card
div.thumbnail-section
a.tag-card-header
img.tag-card-image {
object-fit: cover;
}
.tag-card.zoom-0.grid-card.card div.card-section hr {
display: none;
}
.tag-card.zoom-0.grid-card.card {
padding: 0;
width: 300px;
height: 180px;
}
.tag-card.zoom-0.grid-card.card div.card-section {
position: absolute;
text-shadow: 2px 2px 2px #000;
width: 100%;
background-color: rgba(0, 0, 0, 0.3);
height: 3em;
overflow: hidden;
transition: 0.8s ease-in-out;
}
.tag-card.zoom-0.grid-card.card div.card-section a {
text-decoration: none;
}
.tag-card.zoom-0.grid-card.card div.card-section:hover {
height: 22em;
}
.tag-card.zoom-0.grid-card.card
div.card-section
a
h5.card-section-title.flex-aligned
div.TruncatedText {
white-space: nowrap;
text-overflow: ellipsis;
width: 300px;
overflow: hidden;
display: block;
}
.tag-card.zoom-0.grid-card.card
div.card-section
div.TruncatedText.tag-description {
position: relative;
top: 0.5em;
-webkit-text-stroke-width: 1px;
font-size: 16px;
}
.tag-card .card-popovers .btn {
text-shadow: 1px 1px 1px #000;
stroke: black;
stroke-width: 15;
}

View File

@@ -0,0 +1,21 @@
/* Author: Echoman */
/* [Tags Images] Hides The tag images in Tags view and HR */
.tag-card-image {
display: none !important;
}
.tag-card > hr {
display: none !important;
}
.card {
padding: 10px !important;
}
.card-popovers {
margin-bottom: 0px !important;
}
.tag-card {
padding: 0px !important;
}

View File

@@ -0,0 +1,154 @@
/*Tag layout changes - Author hijack_hornet */
.tag-card {
width: 16rem;
padding: 0;
}
.tag-card .card-section {
height: 2.5rem;
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: #0000007a;
line-height: none;
}
.tag-card .card-section .TruncatedText {
-webkit-line-clamp: 1 !important;
}
.tag-card h1,
h2,
h3,
h4,
h5,
h6,
.h1,
.h2,
.h3,
.h4,
.h5,
.h6 {
line-height: normal;
}
.tag-card hr,
.tag-description {
display: none;
}
.tag-card .btn-group {
position: absolute;
width: 100%;
bottom: 2.5rem;
margin-bottom: 0;
opacity: 0;
transition: ease 0.2s;
}
.tag-card .btn-group:hover {
opacity: 1;
transition: ease 0.2s;
background: #0000007a;
}
.tag-card-image {
object-fit: cover;
object-position: center;
}
.zoom-0 .tag-card-image {
max-height: none;
height: 16rem;
width: 12rem;
}
.zoom-1 .tag-card-image {
max-height: none;
height: 20rem;
width: 15rem;
}
.zoom-2 .tag-card-image {
max-height: none;
height: 24rem;
width: 18rem;
}
.zoom-3 .tag-card-image {
max-height: none;
height: 28rem;
width: 21rem;
}
.zoom-0.tag-card,
.zoom-1.tag-card,
.zoom-2.tag-card,
.zoom-3.tag-card {
width: initial;
}
.tag-card .card-section > a {
position: absolute;
width: 100%;
height: 100%;
display: block;
left: 0;
right: 0;
top: 0;
bottom: 0;
padding: 7px 14px 0px 14px;
}
.tag-card .card-section .tag-sub-tags {
position: relative;
margin-top: 2rem;
z-index: 1;
}
.tag-sub-tags {
font-size: 0;
}
.tag-parent-tags {
display: none;
}
/*Tag subtag exploration snipset*/
.tag-card .card-section > a {
cursor: default;
pointer-events: none;
}
.tag-card .card-section > hr {
margin-top: 2rem;
}
.tag-card .card-section .tag-sub-tags {
position: absolute !important;
margin-top: 0 !important;
width: 100%;
height: 100%;
display: block;
left: 0;
right: 0;
top: 0;
bottom: 0;
padding: 0;
}
.tag-sub-tags::before {
content: "";
display: block;
background: url("https://img.icons8.com/material-outlined/24/137cbd/connection-status-off.png")
no-repeat;
background-size: 1.5rem 1.5rem;
width: 1.5rem;
height: 1.5rem;
float: right;
margin: 0.5rem 0.5rem 0 0;
}
.tag-sub-tags > a {
width: 100%;
height: 100%;
display: block;
}
.tag-card .btn-group a {
z-index: 10;
}
.tag-sub-tags {
font-size: 0;
}
.tag-parent-tags {
display: none;
}

View File

@@ -0,0 +1 @@
https://github.com/killhellokitty/stash-material-ize-theme/blob/main/stash-theme.css

File diff suppressed because one or more lines are too long

View File

@@ -10,3 +10,5 @@ ui:
- themeSwitchCSS.js
css:
- themeSwtichDefault.css
assets:
/: assets

File diff suppressed because one or more lines are too long

View File

@@ -244,16 +244,20 @@
}
}
function applyStyleToHead(key, css) {
const styleElement = document.createElement("style");
styleElement.setAttribute("type", "text/css");
const cssTextNode = document.createTextNode(css);
styleElement.id = key;
styleElement.appendChild(cssTextNode);
document.getElementsByTagName("head")[0].appendChild(styleElement);
function addStyleSheet(key, path) {
console.log(key, path);
const styleSheet = document.createElement("link");
styleSheet.setAttribute(
"href",
`${stash.serverUrl}plugin/themeSwitch/assets${path}`
);
styleSheet.setAttribute("rel", "stylesheet");
styleSheet.setAttribute("type", "text/css");
styleSheet.id = key;
document.getElementsByTagName("head")[0].appendChild(styleSheet);
}
function applyCSS(category, key, css, set) {
async function applyCSS(category, key, path, pluginId, pluginSrc) {
if (category === "Themes") {
// Turn Off old Theme
let regex = /(themeSwitchPlugin-theme-.*)/;
@@ -268,8 +272,16 @@
) {
setObject(storageKey, category, false);
let element = document.getElementById(storageKey);
if (element) {
if (element && !pluginId) {
element.remove();
} else {
const oldThemePluginId = getDataFromKey(storageKey, "pluginId");
if (oldThemePluginId) {
await enablePlugin(oldThemePluginId, false);
setTimeout(() => {
location.reload();
}, 1000);
}
}
}
}
@@ -278,15 +290,25 @@
if (!theme && key != "themeSwitchPlugin-theme-default") {
setObject(key, category, true).then(() => {
applyStyleToHead(key, css);
addStyleSheet(key, path);
});
} else if (!theme && key === "themeSwitchPlugin-theme-default") {
setObject(key, category, true);
} else if (theme && key === "themeSwitchPlugin-theme-default") {
setObject(key, category, true);
} else if (theme && key !== "themeSwitchPlugin-theme-default") {
setObject(key, category, true).then(() => {
applyStyleToHead(key, css);
setObject(key, category, true).then(async () => {
if (pluginId) {
if (!(await isPluginInstalled(pluginId))) {
await installPlugin(pluginId, pluginSrc);
}
await enablePlugin(pluginId, true);
setTimeout(() => {
location.reload();
}, 1000);
} else if (path) {
addStyleSheet(key, path);
}
});
}
} else {
@@ -294,10 +316,10 @@
const storageObject = JSON.parse(localStorage.getItem(key));
if (!storageObject || storageObject.active === false) {
setObject(key, category, true).then(() => {
applyStyleToHead(key, css);
addStyleSheet(key, path);
});
} else if (storageObject.active && !document.getElementById(key)) {
applyStyleToHead(key, css);
addStyleSheet(key, path);
} else {
setObject(key, category, false).then(() => {
document.getElementById(key).remove();
@@ -331,6 +353,63 @@
}
}
async function getInstalledPlugins() {
try {
const res = await stash.callGQL({
operationName: "Plugins",
variables: {},
query: "query Plugins{plugins{id}}",
});
return res.data.plugins.map((plugin) => plugin.id);
} catch (err) {
console.error(err);
}
}
async function isPluginInstalled(plugin) {
const installedPlugins = await getInstalledPlugins();
return installedPlugins.includes(plugin);
}
async function enablePlugin(plugin, state) {
try {
const query = {
operationName: "SetPluginsEnabled",
variables: {
enabledMap: {},
},
query:
"mutation SetPluginsEnabled($enabledMap: BoolMap!) {\n setPluginsEnabled(enabledMap: $enabledMap)\n}",
};
query.variables.enabledMap[plugin] = state;
await stash.callGQL(query);
} catch (err) {
console.error(err);
}
}
async function installPlugin(plugin, src) {
try {
await stash.callGQL({
operationName: "InstallPluginPackages",
variables: {
packages: [
{
id: plugin,
sourceURL: src,
},
],
},
query:
"mutation InstallPluginPackages($packages: [PackageSpecInput!]!) {installPackages(type: Plugin, packages: $packages)}",
});
} catch (err) {
console.error(err);
}
}
function createBTNMenu() {
return new Promise(function (resolve, reject) {
waitForElementClass("top-nav", function () {
@@ -381,7 +460,7 @@
header.className = "modal-header";
accordion.append(header);
Object.entries(themeSwitchCSS).forEach(
Object.entries(window.themeSwitchCSS).forEach(
([category, themesInCategory], i) => {
const categoryDiv = document.createElement("div");
categoryDiv.className = "card";
@@ -440,7 +519,7 @@
fieldset.className = "checkbox-switch";
// Loop over themes in each category
Object.entries(themesInCategory).forEach(([themeId, theme]) => {
themesInCategory.forEach((theme) => {
if (category === "Navigation") {
} else {
const forRow = document.createElement("div");
@@ -463,17 +542,30 @@
const themeData = {
category: category,
key: theme.key,
css: theme.styles,
...(theme.path
? { path: theme.path }
: theme.pluginId
? {
pluginId: theme.pluginId,
pluginSrc: theme.pluginSrc,
}
: {}),
};
input.setAttribute("id", category + "-" + theme.key);
input.addEventListener(
"click",
(function (category, key, css) {
return function () {
applyCSS(category, key, css);
(function (themeData) {
return async function () {
applyCSS(
themeData.category,
themeData.key,
themeData.path,
themeData.pluginId,
themeData.pluginSrc
);
};
})(themeData.category, themeData.key, themeData.css),
})(themeData),
false
);
@@ -593,11 +685,11 @@
});
}
function returnCSS(key) {
for (const [, categoryThemes] of Object.entries(themeSwitchCSS)) {
for (const [, theme] of Object.entries(categoryThemes)) {
function getDataFromKey(key, field) {
for (const [, categoryThemes] of Object.entries(window.themeSwitchCSS)) {
for (const theme of categoryThemes) {
if (key === theme.key) {
return theme.styles;
return theme[field];
}
}
}
@@ -624,8 +716,7 @@
selectedTheme = JSON.parse(localStorage.getItem(key));
if (selectedTheme.active === true) {
appliedThemeOtherThanDefault.push("True");
const css = returnCSS(key);
applyCSS(selectedTheme.category, key, css, true);
applyCSS(selectedTheme.category, key, getDataFromKey(key, "path"));
}
}
}
@@ -675,10 +766,7 @@
init();
}
for (var i = 0; i < StashPages.length; i++) {
const page = StashPages[i];
stash.addEventListener(page, createMenuAndInit);
}
stash.addEventListeners(StashPages, createMenuAndInit);
// Reset menuCreated flag on hard refresh
window.addEventListener("beforeunload", function () {