diff --git a/build.ts b/build.ts index a7bb49c..544c748 100644 --- a/build.ts +++ b/build.ts @@ -3,6 +3,7 @@ import fs from "fs"; import path from "path"; import crypto from "crypto"; import { minify as minifyHtml } from "html-minifier-terser"; +import CleanCSS from "clean-css"; const nativeExternals = ["@neptune", "@plugin", "electron"]; const minify = true; @@ -36,8 +37,8 @@ const fileUrl: esbuild.Plugin = { if (!minify) { content = fs.readFileSync(path, encoding).trimEnd(); } else { + const file = fs.readFileSync(path, "utf-8"); if (path.endsWith(".html")) { - const file = fs.readFileSync(path, "utf-8"); content = await minifyHtml(file, { collapseWhitespace: true, removeComments: true, @@ -49,6 +50,8 @@ const fileUrl: esbuild.Plugin = { removeStyleLinkTypeAttributes: true, useShortDoctype: true, }); + } else if (path.endsWith(".css")) { + content = new CleanCSS().minify(file).styles; } else { throw new Error(`Don't know how to minify file type: ${path}`); } diff --git a/package.json b/package.json index 168ef2b..90182ca 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,10 @@ "serve": "serve -C ./plugins" }, "devDependencies": { + "@types/clean-css": "^4.2.11", "@types/html-minifier-terser": "^7.0.2", "@types/node": "^20.14.12", + "clean-css": "^5.3.3", "concurrently": "^8.2.2", "electron": "^31.3.0", "esbuild": "^0.23.0", diff --git a/plugins/CoverTheme/src/index.ts b/plugins/CoverTheme/src/index.ts index 7dabbca..48874c2 100644 --- a/plugins/CoverTheme/src/index.ts +++ b/plugins/CoverTheme/src/index.ts @@ -3,6 +3,7 @@ import getPlaybackControl from "@inrixia/lib/getPlaybackControl"; import { MediaItemCache } from "@inrixia/lib/Caches/MediaItemCache"; import { setStyle } from "@inrixia/lib/css/setStyle"; import { getPalette } from "@inrixia/lib/nativeBridge"; +import transparent from "file://transparent.css?minify"; import { Tracer } from "@inrixia/lib/trace"; const trace = Tracer("[CoverTheme]"); @@ -11,22 +12,27 @@ let prevSong: string | undefined; let prevCover: string | undefined; let vars = new Set(); -const getCoverUrl = (id: string) => "https://resources.tidal.com/images/" + id.split("-").join("/") + "/640x640.jpg"; +const getCoverUrl = (id: string) => + "https://resources.tidal.com/images/" + + id.split("-").join("/") + + "/640x640.jpg"; type ColorInfo = [colorName: string, rgb: string | null]; const paletteCache: Record> = {}; const getCachedPalette = (coverId: string) => { const palette = paletteCache[coverId]; if (palette !== undefined) return palette; - return (paletteCache[coverId] = getPalette(getCoverUrl(coverId)).then((palette) => { - const colors: ColorInfo[] = []; - for (const colorName in palette) { - // @ts-expect-error Native return types dont serialize class methods like .rgb(), - // but thankfully the class pre-fills the value in a private _rgb property we can use. - colors.push([colorName, palette[colorName]?._rgb?.join(", ")]); + return (paletteCache[coverId] = getPalette(getCoverUrl(coverId)).then( + (palette) => { + const colors: ColorInfo[] = []; + for (const colorName in palette) { + // @ts-expect-error Native return types dont serialize class methods like .rgb(), + // but thankfully the class pre-fills the value in a private _rgb property we can use. + colors.push([colorName, palette[colorName]?._rgb?.join(", ")]); + } + return colors; } - return colors; - })).catch(trace.msg.err.withContext(`Failed to get cover palette!`)); + )).catch(trace.msg.err.withContext(`Failed to get cover palette!`)); }; async function updateBackground(productId: string) { @@ -54,9 +60,15 @@ function onTransition([track]: any[]) { if (id) updateBackground(id); } -const unloadPrefill = intercept("playbackControls/PREFILL_MEDIA_PRODUCT_TRANSITION", onTransition); +const unloadPrefill = intercept( + "playbackControls/PREFILL_MEDIA_PRODUCT_TRANSITION", + onTransition +); -const unloadTransition = intercept("playbackControls/MEDIA_PRODUCT_TRANSITION", onTransition); +const unloadTransition = intercept( + "playbackControls/MEDIA_PRODUCT_TRANSITION", + onTransition +); const style = setStyle(); export function updateCSS() { @@ -69,31 +81,13 @@ export function updateCSS() { "bottom right": "DarkMuted", }; const gradients = Object.entries(positions) - .map(([position, variable]) => `radial-gradient(ellipse at ${position}, rgb(var(--cover-${variable}), 0.5), transparent 70%)`) + .map( + ([position, variable]) => + `radial-gradient(ellipse at ${position}, rgb(var(--cover-${variable}), 0.5), transparent 70%)` + ) .join(", "); - - const css = ` - body { - background-image:${gradients}; - } - #wimp, main, [class^="sidebarWrapper"], [class^="mainContainer"], [class^="tabListWrapper"] { - background: unset !important; - } - - #footerPlayer, nav, [class^="bar"] { - background-color: color-mix(in srgb, var(--wave-color-solid-base-brighter), transparent 70%) !important; - } - - #nowPlaying > [class^="innerContainer"] { - height: calc(100vh - 126px); - overflow: hidden; - } - - .tidal-ui__z-stack > :not(:has(div)) { - background-image: linear-gradient(90deg, rgb(var(--cover-DarkVibrant), 0.5), rgb(var(--cover-LightVibrant), 0.5)) !important; - }`; - - style.css = css; + document.body.style.backgroundImage = gradients; + style.css = transparent; } updateCSS(); @@ -104,7 +98,9 @@ export const onUnload = () => { unloadPrefill(); unloadTransition(); style.remove(); - vars.forEach((variable) => document.documentElement.style.removeProperty(variable)); + vars.forEach((variable) => + document.documentElement.style.removeProperty(variable) + ); prevSong = undefined; prevCover = undefined; }; diff --git a/plugins/CoverTheme/src/transparent.css b/plugins/CoverTheme/src/transparent.css new file mode 100644 index 0000000..5b6f57b --- /dev/null +++ b/plugins/CoverTheme/src/transparent.css @@ -0,0 +1,30 @@ +#wimp, +main, +[class^="sidebarWrapper"], +[class^="mainContainer"], +[class^="tabListWrapper"] { + background: unset !important; +} + +#footerPlayer, +nav, +[class^="bar"] { + background-color: color-mix( + in srgb, + var(--wave-color-solid-base-brighter), + transparent 70% + ) !important; +} + +#nowPlaying > [class^="innerContainer"] { + height: calc(100vh - 126px); + overflow: hidden; +} + +.tidal-ui__z-stack > :not(:has(div)) { + background-image: linear-gradient( + 90deg, + rgb(var(--cover-DarkVibrant), 0.5), + rgb(var(--cover-LightVibrant), 0.5) + ) !important; +} diff --git a/plugins/SongDownloader/src/index.ts b/plugins/SongDownloader/src/index.ts index 72bc475..1030fe2 100644 --- a/plugins/SongDownloader/src/index.ts +++ b/plugins/SongDownloader/src/index.ts @@ -1,7 +1,7 @@ import "@inrixia/lib/contentButton.styles"; import { TrackItem } from "neptune-types/tidal"; -import { parseExtension, parseFileName } from "./parseFileName"; +import { parseFileName } from "./parseFileName"; import { Tracer } from "@inrixia/lib/trace"; const trace = Tracer("[SongDownloader]"); diff --git a/plugins/TidalTags/src/index.ts b/plugins/TidalTags/src/index.ts index be3bd94..779b370 100644 --- a/plugins/TidalTags/src/index.ts +++ b/plugins/TidalTags/src/index.ts @@ -2,7 +2,7 @@ import { intercept, store } from "@neptune"; import { setFLACInfo } from "./setFLACInfo"; -import { style } from "./style"; +import styles from "file://styles.css?minify"; import { setQualityTags } from "./setQualityTags"; export { Settings } from "./Settings"; @@ -13,13 +13,23 @@ import { setInfoColumnHeaders, setInfoColumns } from "./setInfoColumns"; import { MediaItemCache } from "@inrixia/lib/Caches/MediaItemCache"; import { PlaybackContext } from "@inrixia/lib/AudioQualityTypes"; import safeUnload from "@inrixia/lib/safeUnload"; +import { setStyle } from "@inrixia/lib/css/setStyle"; /** * Flac Info */ // @ts-expect-error Intercept callback does not have types filled -const unloadIntercept = intercept("playbackControls/MEDIA_PRODUCT_TRANSITION", setFLACInfo); -setFLACInfo([{ playbackContext: store.getState().playbackControls.playbackContext }]); +const unloadIntercept = intercept( + "playbackControls/MEDIA_PRODUCT_TRANSITION", + setFLACInfo +); +setFLACInfo([ + { + playbackContext: ( + store.getState().playbackControls.playbackContext + ), + }, +]); /** * Tags & Info Columns @@ -29,7 +39,9 @@ const observer = new MutationObserver((mutationsList) => { if (mutation.type === "childList") { for (const node of mutation.addedNodes) { if (isElement(node)) { - const trackRows = node.querySelectorAll('div[data-test="tracklist-row"]'); + const trackRows = node.querySelectorAll( + 'div[data-test="tracklist-row"]' + ); if (trackRows.length !== 0) updateTrackRows(trackRows); } } @@ -46,7 +58,8 @@ const updateTrackRows = async (trackRows: NodeListOf) => { if (trackItem === undefined) continue; if (settings.showTags) setQualityTags(trackRow, trackId, trackItem); - if (settings.displayInfoColumns) setInfoColumns(trackRow, trackId, trackItem); + if (settings.displayInfoColumns) + setInfoColumns(trackRow, trackId, trackItem); } }; export const updateObserver = () => { @@ -57,6 +70,7 @@ export const updateObserver = () => { } }; updateObserver(); +const style = setStyle(styles); export const onUnload = () => { observer.disconnect(); diff --git a/plugins/TidalTags/src/style.ts b/plugins/TidalTags/src/styles.css similarity index 71% rename from plugins/TidalTags/src/style.ts rename to plugins/TidalTags/src/styles.css index a46a62c..56589a2 100644 --- a/plugins/TidalTags/src/style.ts +++ b/plugins/TidalTags/src/styles.css @@ -1,8 +1,5 @@ -import { setStyle } from "@inrixia/lib/css/setStyle"; - -const styles = ` div[class*="titleCell--"] { - width: auto; !important + width: auto !important; } .quality-tag-container { @@ -12,6 +9,7 @@ div[class*="titleCell--"] { font-size: 12px; line-height: 24px; } + .quality-tag { justify-content: center; align-items: center; @@ -22,6 +20,3 @@ div[class*="titleCell--"] { transition: background-color 0.2s; margin-left: 5px; } -`; - -export const style = setStyle(styles); diff --git a/plugins/_lib/contentButton.css b/plugins/_lib/contentButton.css new file mode 100644 index 0000000..55e0cd5 --- /dev/null +++ b/plugins/_lib/contentButton.css @@ -0,0 +1,34 @@ +.context-button { + align-items: center; + display: flex; + font-weight: 500; + padding: 20px 16px; + width: 100%; + height: 45px; + flex-grow: 1; + color: #b878ff; + position: relative; +} +.context-button:hover { + background-color: #9e46ff; + color: #fff; +} +.context-button::before { + content: ""; + position: absolute; + top: 0; + left: 0; + height: 100%; + width: var(--progress, 0); /* Initially set to 0 */ + background: rgba(255, 255, 255, 0.25); /* Loading bar color */ + z-index: 1; +} +.context-button.loading { + background-color: #9e46ff; + cursor: not-allowed; + color: #fff; +} +.context-button span { + z-index: 2; + position: relative; +} diff --git a/plugins/_lib/contentButton.styles.ts b/plugins/_lib/contentButton.styles.ts index 3499242..ae442a7 100644 --- a/plugins/_lib/contentButton.styles.ts +++ b/plugins/_lib/contentButton.styles.ts @@ -1,40 +1,4 @@ import { setStyle } from "./css/setStyle"; - -const styles = ` -.context-button { - align-items: center; - display: flex; - font-weight: 500; - padding: 20px 16px; - width: 100%; - height: 45px; - flex-grow: 1; - color: #b878ff; - position: relative; -} -.context-button:hover { - background-color: #9e46ff; - color: #fff; -} -.context-button::before { - content: ""; - position: absolute; - top: 0; - left: 0; - height: 100%; - width: var(--progress, 0); /* Initially set to 0 */ - background: rgba(255, 255, 255, 0.25); /* Loading bar color */ - z-index: 1; -} -.context-button.loading { - background-color: #9e46ff; - cursor: not-allowed; - color: #fff; -} -.context-button span { - z-index: 2; - position: relative; -} -`; +import styles from "file://contentButton.css?minify"; setStyle(styles, "content-button"); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3475ec3..668e5b8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,12 +21,18 @@ importers: specifier: ^10.0.0 version: 10.2.0 devDependencies: + '@types/clean-css': + specifier: ^4.2.11 + version: 4.2.11 '@types/html-minifier-terser': specifier: ^7.0.2 version: 7.0.2 '@types/node': specifier: ^20.14.12 version: 20.16.1 + clean-css: + specifier: ^5.3.3 + version: 5.3.3 concurrently: specifier: ^8.2.2 version: 8.2.2 @@ -421,6 +427,9 @@ packages: '@types/cacheable-request@6.0.3': resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} + '@types/clean-css@4.2.11': + resolution: {integrity: sha512-Y8n81lQVTAfP2TOdtJJEsCoYl1AnOkqDqMvXb9/7pfgZZ7r8YrEyurrAvAoAjHOGXKRybay+5CsExqIH6liccw==} + '@types/html-minifier-terser@7.0.2': resolution: {integrity: sha512-mm2HqV22l8lFQh4r2oSsOEVea+m0qqxEmwpc9kC1p/XzmjLWrReR9D/GRs8Pex2NX/imyEH9c5IU/7tMBQCHOA==} @@ -1869,6 +1878,11 @@ snapshots: '@types/node': 20.16.1 '@types/responselike': 1.0.3 + '@types/clean-css@4.2.11': + dependencies: + '@types/node': 20.16.1 + source-map: 0.6.1 + '@types/html-minifier-terser@7.0.2': {} '@types/http-cache-semantics@4.0.4': {}