From a0566d89e5d9ecf1190d2bd2587acd133411cfd6 Mon Sep 17 00:00:00 2001 From: Youwen Wu Date: Mon, 23 Jun 2025 14:20:39 -0700 Subject: [PATCH] feat: add tidal hifi module and stylix theming --- hm/modules/linux/default.nix | 1 + hm/modules/linux/programs/bulk-programs.nix | 1 - hm/modules/linux/tidal-hifi/default.nix | 719 ++++++++++++++++++++ hm/modules/linux/tidal-hifi/themify.py | 162 +++++ hm/modules/linux/tidal-hifi/tidal-light.css | 684 +++++++++++++++++++ 5 files changed, 1566 insertions(+), 1 deletion(-) create mode 100644 hm/modules/linux/tidal-hifi/default.nix create mode 100644 hm/modules/linux/tidal-hifi/themify.py create mode 100644 hm/modules/linux/tidal-hifi/tidal-light.css diff --git a/hm/modules/linux/default.nix b/hm/modules/linux/default.nix index b3e842f..19ffe6f 100755 --- a/hm/modules/linux/default.nix +++ b/hm/modules/linux/default.nix @@ -13,6 +13,7 @@ ./desktop-environment ./theming ./platform-tweaks + ./tidal-hifi ]; programs.fish.functions = lib.mkIf config.liminalOS.programs.enable { diff --git a/hm/modules/linux/programs/bulk-programs.nix b/hm/modules/linux/programs/bulk-programs.nix index e15a278..e795798 100644 --- a/hm/modules/linux/programs/bulk-programs.nix +++ b/hm/modules/linux/programs/bulk-programs.nix @@ -107,7 +107,6 @@ in sbctl ] ++ lib.optionals pkgs.stdenv.targetPlatform.isAarch64 [ ] - ++ lib.optionals osConfig.liminalOS.config.allowUnfree [ tidal-hifi ] ) ); }; diff --git a/hm/modules/linux/tidal-hifi/default.nix b/hm/modules/linux/tidal-hifi/default.nix new file mode 100644 index 0000000..94b1b63 --- /dev/null +++ b/hm/modules/linux/tidal-hifi/default.nix @@ -0,0 +1,719 @@ +{ + config, + osConfig, + lib, + pkgs, + ... +}: +let + cfg = config.programs.tidal-hifi; +in +# TODO: add check for unfree: ++ lib.optionals osConfig.liminalOS.config.allowUnfree [ tidal-hifi ] +{ + options.programs.tidal-hifi = { + enable = lib.mkEnableOption "tidal Hi-Fi client"; + theme = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = '' + Custom CSS to use as theme for Tidal HiFi. + ''; + }; + }; + config = { + home.packages = lib.mkIf cfg.enable [ pkgs.tidal-hifi ]; + xdg.configFile."tidal-hifi/themes/stylix.css".text = lib.mkIf (cfg.theme != null) cfg.theme; + + programs.tidal-hifi = + lib.mkIf (config.liminalOS.programs.enable && osConfig.liminalOS.config.allowUnfree) + { + enable = true; + theme = with config.lib.stylix.colors.withHashtag; '' + /* + { + "name": "Tidal Light", + "author": "Interstellar_1", + "description": "A light theme for Tidal. v0.3.5b" + "license": "MIT License" + } + */ + :root { + /*background color*/ + --wave-color-solid-base-fill: ${base00} !important; + --wave-color-solid-accent-darkest: ${base01} !important; + --wave-color-solid-base-brighter: ${base01} !important; + --wave-color-solid-base-bright: ${base01} !important; + --wave-color-opacity-base-bright-thick: ${base05} !important; + + /*hover*/ + --wave-color-solid-base-brightest: ${base03} !important; + --wave-color-opacity-base-brightest-regular: ${base01} !important; + --wave-color-opacity-contrast-fill-regular: ${base04} !important; + --wave-color-solid-contrast-dark: ${base03} !important; + --transparent-play-hover: #e1e1e166 !important; + + /*border*/ + --wave-color-opacity-contrast-fill-ultra-thin: ${base02} !important; + + /*button color*/ + --wave-color-opacity-contrast-fill-thin: ${base03} !important; + --wave-color-solid-accent-darker: ${base0C} !important; + --wave-color-solid-rainbow-red-darkest: ${base08} !important; + --wave-color-solid-rainbow-red-darker: ${base08} !important; + --button-light: ${base03} !important; + --button-medium: ${base04} !important; + + /*accents*/ + --wave-color-solid-accent-fill: ${base0E} !important; + --text-accent: ${base0E} !important; + [data-w="textUrl"] { + color: var(--text-accent) !important; + } + --switch-accent: ${base0E} !important; + --wave-color-solid-rainbow-yellow-fill: ${base0A} !important; + + /*primary text*/ + [data-wave-color="textDefault"] { + color: ${base05} !important; + } + [data-wave-color="textWhite"] { + color: ${base05} !important; + } + /*secondary text*/ + --wave-color-text-secondary: ${base06} !important; + [data-wave-color="textSecondary"] { + color: ${base05}000b3 !important; + } + --wave-color-solid-contrast-darker: ${base06} !important; + --wave-color-opacity-contrast-fill-ultra-thick: ${base06} !important; + /*icons*/ + --wave-color-solid-contrast-fill: ${base05} !important; + --wave-color-opacity-contrast-fill-thick: ${base05}0009a !important; + + /*search*/ + --wave-color-opacity-base-brighter-ultra-thick: ${base04} !important; + --search-background: ${base01}e0 !important; + + /*user profile image*/ + --user-profile-linear-gradient: linear-gradient( + 160deg, + ${base0B} 1.22%, + ${base0D} 40.51%, + ${base04} 79.07% + ) !important; + } + + body { + background-color: ${base00} !important; + } + /*GENERAL*/ + /*hide right shadow*/ + #playQueueSidebar { + box-shadow: none !important; + } + + /*buttons*/ + ._activeTab_f47dafa { + background: ${base03}; + } + + /*HOMEPAGE*/ + /*artists*/ + .isLoggedIn--CEJH_::after { + background: none; + } + + /*hide album + playlist + mix bg*/ + ._dataContainer_66f4f40::before, + ._dataContainer_5bb6028::before, + ._dataContainer_7feb4a2::before { + background-image: none; + } + + /*artist name*/ + .css-5pl3ge { + color: ${base05}000ab; + } + + /*icons*/ + .icon--rmikT, + .icon--VV33E { + color: ${base05}; + } + ._icon_77f3f89 { + fill: ${base05} !important; + } + + /*SIDEBAR*/ + ._active_3451dba:is(a._sidebarItem_730d27e, button._sidebarItem_730d27e) span { + color: var(--wave-color-solid-accent-fill) !important; + } + + /*player shadow*/ + .player--gAOQG.notFullscreen--xbpBL { + box-shadow: 0 -6px 24px ${base04}26; + } + + /*ACCENT TEXT*/ + /*yellow*/ + ._wave-badge-color-max_1oxl7_22 { + color: ${base0A}; + background-color: ${base0A}38; + } + + /*blue*/ + ._wave-badge-color-high_1oxl7_17 { + color: var(--text-accent); + } + + .wave-text-title-bold { + color: ${base00} !important; + } + + /*none*/ + ._wave-badge-color-default_1oxl7_7 { + background-color: ${base03}; + color: ${base05}; + } + + svg._accentedIcon_d6d54e4 { + color: var(--wave-color-solid-accent-fill); + fill: var(--wave-color-solid-accent-fill) !important; + } + + .smallHeader--rfQsR { + --img: url(https://blocks.astratic.com/img/general-img-landscape.png) !important; + } + + /*shortcuts*/ + ._shortcutItem_6c8e7b4 { + box-shadow: none !important; + background-color: var(--wave-color-solid-base-brighter) !important; + } + + ._shortcutItem_6c8e7b4::after { + background: linear-gradient(${base05}0, ${base00}9); + } + + /*search*/ + .container--cl4MJ, + div.searchField--fgDKc, + div.searchField--fgDKc:focus, + ._container_f1be359 { + background-color: var(--search-background) !important; + border-color: var(--wave-color-opacity-contrast-fill-ultra-thin) !important; + } + + .container--sRPa5 { + border-color: var(--wave-color-opacity-contrast-fill-ultra-thin) !important; + } + + .icon--nNXej, + ._icon_49dd0aa { + background: linear-gradient(180deg, ${base00}, ${base03}) !important; + } + + a.searchPill--ED7eQ.active--e_BIx { + background: var(--wave-color-opacity-contrast-fill-thin) !important; + } + + .css-10jmp6g { + color: var(--wave-color-text-secondary) !important; + } + + ._imageContainer_dfdf7bd::after, + ._imageContainer_23303c1::after { + background: var(--transparent-play-hover) !important; + } + + /*updates*/ + .css-5pl3ge { + color: ${base05}000ab !important; + } + + /*explict badge*/ + ._explicitBadge_b93510b { + filter: invert(40%) brightness(110%) contrast(140%); + } + + #explicit-badge { + color: ${base05} !important; + } + + /*video badge*/ + .videoBadge--Tpdav { + fill: var(--wave-color-text-secondary); + filter: brightness(0.3) invert(0); + } + + /*canvas nav buttons*/ + .viewAllButton--Nb87U, + .css-7l8ggf { + background: ${base03}; + } + + .viewAllButton--Nb87U:hover, + .css-7l8ggf:hover { + background: ${base04}; + } + + /*album hover*/ + .overlay--ces1Z, + .overlay--Dn4ax, + .overlay--Cb6su, + .css-17bbmu3, + .css-ohr3gy, + ._overlay_3c15650, + ._overlay_aa1ee83, + ._overlay_62e2cfd, + ._overlay_e0e48ef, + ._overlay_7fd73e6, + ._overlay_f627136, + .css-1ug9uri, + .css-u7yq00 { + background: linear-gradient(${base05}0, ${base00}9e) !important; + } + + :is(._dataContainer_66f4f40 ._coverArtContainer_2eafdf9) + ._creditsOverlay_b234d8c { + background: ${base00}80; + } + + /*artist hover*/ + .css-179fhoi, + .css-fvlky0 { + background: linear-gradient(${base05}0, ${base00}9e) !important; + } + + /*play button hover*/ + .css-75d7zy { + background-color: ${base00}a6; + transition: 100ms; + } + + .css-75d7zy:hover { + background-color: var(--wave-color-solid-base-brighter); + } + + button.button--W_J5g.gray--tvcIF.contextMenuButton--Bcnyd:hover { + background-size: 200%; + } + + /*playlist hover*/ + .css-1voubjj:hover { + background-color: var(--wave-color-solid-base-brighter); + border: 5px var(--wave-color-opacity-contrast-fill-ultra-thin); + } + + /*queue popup*/ + .bottomGradient--BngZe, + ._bottomGradient_104d99b { + background-image: none; + } + + #playQueueSidebar { + box-shadow: 0 20px 25px 5px ${base00}57; + } + + /*audio quality popup*/ + ._containerMax_611862e { + background-color: transparent; + } + + /*PLAYER PANE*/ + .range--JNSfg { + background-color: ${base04}; + } + + :is(._player_1d16b04 button).withBackground[aria-checked="true"] { + background-color: ${base02}; + } + + ._range_ce0e571 { + background-color: var(--wave-color-opacity-contrast-fill-regular); + } + + /*album hover*/ + ._notFullscreenOverlay_1442d60 { + background: linear-gradient(0deg, ${base00}a6, ${base00}a6); + } + + /*FULL VIEW*/ + .activeTab--bqTiv { + background: ${base02}; + } + + .container--cl4MJ { + background: ${base00}63 !important; + } + + .css-u7yq00 { + background: ${base00}75; + } + + ._bottomGradient_5c344de { + background: none; + } + + ._button_84b8ffe { + background-color: var(--wave-color-solid-base-brighter); + } + + ._button_84b8ffe:hover { + background-color: var(--wave-color-solid-base-brightest); + } + + ._baseButton_15fc215:focus { + background: ${base03}; + } + + #nowPlaying { + background-image: none !important; + } + + /*thumbnail*/ + ._albumImageOverlay_2eabc2b { + background: ${base00}4f; + } + + /*ALBUM*/ + .albumImage--i2CqD { + box-shadow: + 0 20px 50px 5px ${base04}38, + 0 20px 40px 0 ${base05}00024; + } + + ._button_f1c7fcb { + background: var(--wave-color-solid-base-brighter); + } + + .artist-link { + color: ${base05}; + } + + /*remove bg image*/ + [class^="_dataContainer_"]:before { + --img: none !important; + background-image: none !important; + } + + /*playlist*/ + .refreshButton--bRrPi { + color: ${base05}; + } + + /*tracks page*/ + .variantPrimary--pjymy, + ._button_3357ce6 { + background-color: var(--button-light); + } + + .wave-text-body-demi { + color: ${base05}; + } + + /*track hover*/ + ._rowContainer_ebb4cfc:hover { + background: var(--wave-color-solid-base-brightest) !important; + } + + /*DIALOUGES*/ + .ReactModal__Content { + background: ${base01} !important; + } + + .label--fycqD.unchecked--goEjz { + background-color: ${base04}; + } + + .label--fycqD.checked--RVmZV { + background-color: var(--switch-accent); + } + + .primary--NLSX4 { + background-color: ${base03}; + } + + .primary--NLSX4:hover { + background-color: var(--wave-color-opacity-contrast-fill-regular) !important; + } + + .primary--NLSX4:disabled { + background-color: ${base02}; + } + + .primary--NLSX4:disabled:hover { + background-color: ${base02}; + } + + /*popups*/ + .notification--hckxF, + .native-range { + box-shadow: 0 20px 50px 5px ${base00}2e; + } + + ._notification_99c9c6e { + box-shadow: 0 16px 32px ${base05}0; + } + + ._notification_99c9c6e._error_0b778e5 { + background: var(--wave-color-solid-rainbow-red-darker); + } + + .errorIcon--VvndK { + fill: ${base05} !important; + } + + /*PROFILE*/ + .followingTag--CKRME, + .wave-text-footnote-medium { + color: var(--text-accent) !important; + } + + ._wave-btn-rank-primary_1lao2_58:hover { + background-color: ${base0E}; + } + + ._button_94c5125 { + background-color: transparent !important; + } + + .profilePicture--yrdRB { + box-shadow: none; + } + + ._input_15c0d78:focus { + color: var(--wave-color-solid-contrast-darker); + } + + /*my picks*/ + #My\ favorite\ track\ on\ repeat, + ._selectedPrompt_dac4cfc[style*="--prompt-base-color: ${base0D}1A"] { + --prompt-base-color: ${base0D} !important; + --prompt-color: ${base0E} !important; + } + + #My\ major\ mood\ booster, + ._selectedPrompt_dac4cfc[style*="--prompt-base-color: #FF91531A"] { + --prompt-base-color: ${base09} !important; + --prompt-color: ${base0A} !important; + } + + #My\ go-to\ artist\ right\ now, + ._selectedPrompt_dac4cfc[style*="--prompt-base-color: #FF53531A"] { + --prompt-base-color: ${base08} !important; + --prompt-color: ${base0F} !important; + } + + #My\ top\ album\ recently, + ._selectedPrompt_dac4cfc[style*="--prompt-base-color: #53FF981A"] { + --prompt-base-color: ${base0B} !important; + --prompt-color: ${base0B} !important; + } + + ._wave-btn-rank-clean_1lao2_127:hover { + color: ${base00}; + background-color: ${base05}38 !important; + } + + #pick-promt-item-search-field { + color: ${base05}; + } + + /*ARTIST PAGE*/ + ._background_4a10ea2:after { + content: "" !important; + position: absolute !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + bottom: 0 !important; + background-color: ${base00}4a !important; + } + + :is(._background_a548b6d ._image_7ba9b97):before { + background-color: ${base00}21 !important; + background-image: none !important; + background-blend-mode: normal !important; + } + + ._background_a548b6d { + background-image: linear-gradient(180deg, ${base00}66 0, ${base00}) !important; + } + + :is(._background_a548b6d ._image_7ba9b97):after { + background-image: var(--img) !important; + background-position: center !important; + background-repeat: no-repeat !important; + background-size: cover !important; + content: "" !important; + filter: blur(5px) brightness(30%) !important; + inset: -20px 0 !important; + mask-image: linear-gradient(0deg, ${base00}0 43%, ${base00}) !important; + position: absolute !important; + } + + ._mainImage_433f1ff:is(._background_a548b6d ._image_7ba9b97):after { + mask-image: linear-gradient(0deg, ${base00}0, ${base00}) !important; + filter: brightness(100%) !important; + height: 87% !important; + } + + .buttonText--LMsAT { + color: ${base00} !important; + } + + .css-10jmp6g { + color: ${base05}; + } + + .button--_0I_t { + background-color: var(--button-light); + } + + .button--_0I_t:hover { + background-color: var(--wave-color-opacity-contrast-fill-regular); + } + + #player__play { + color: ${base05}; + } + + .primary--NLSX4:hover { + background-color: ${base04}; + } + + :is(._buttons_ff12873 ._following_657edad) ._icon_29252d0 { + fill: var(--wave-color-solid-accent-fill) !important; + } + + /*bio*/ + ._dialog_148b5df { + color: ${base05}; + } + + /*producer discography*/ + .css-1thhtwd { + background: var(--wave-color-solid-base-brighter); + } + + .css-1thhtwd:hover { + background: var(--wave-color-opacity-contrast-fill-regular); + } + + ._buttonActive_5125b72 { + background: var(--button-light); + } + + ._buttonActive_5125b72:hover { + background: var(--wave-color-opacity-contrast-fill-regular); + } + + ._buttonActive_5125b72 > .wave-text-body-medium { + color: ${base05}; + } + /*SETTINGS*/ + ._container_b4f1e20._fillDark_a1e5896 > div, + ._container_9a0abb9 { + background: ${base01} !important; + } + + ._select_ef84104 { + background: var(--wave-color-solid-accent-darker) !important; + } + + .licenseFrame--C_hup { + background: ${base06}; + } + + svg#lastfm path { + fill: ${base05}; + } + + ._button_94c5125 { + background: var(--wave-color-solid-base-brighter); + } + + /*scrollbars*/ + ::-webkit-scrollbar { + background-color: transparent !important; + border: none !important; + width: 8px !important; + } + + ::-webkit-scrollbar-track { + background-color: var(--wave-color-solid-base-brighter) !important; + box-shadow: none; + } + + ::-webkit-scrollbar-thumb { + background-color: ${base04} !important; + border: none !important; + } + + /*luna*/ + body + > div.ReactModalPortal + > div + > div + > div.modalBody--TFBWU.selectableText--UDUkZ.modalText--gCapb.subtitle--dYfEG + > neptune-reactive-root + > div + > button, + #main + > div.__NEPTUNE_PAGE + > neptune-reactive-root + > div + > div + > div:nth-child(2) + > div + > div.neptune-card + > div + > div:nth-child(2) + > div:nth-child(1) + > button:nth-child(1), + #main + > div.__NEPTUNE_PAGE + > neptune-reactive-root + > div + > div + > div:nth-child(2) + > div + > div.neptune-card + > div + > div:nth-child(2) + > div:nth-child(1) + > button:nth-child(2) { + color: ${base05} !important; + } + + .neptune-switch::after { + background-color: ${base00} !important; + } + + .css-16hze37, + #main + > div:nth-child(3) + > div + > div.MuiContainer-root.MuiContainer-maxWidthLg.css-sot3eg + > div + > div:nth-child(2) + > div.MuiStack-root.css-16a8gxx + > div { + color: ${base07} !important; + } + + .css-yc8597, + .css-pfqxe1, + .css-axw7ok { + color: ${base00} !important; + } + + to { + opacity: 1; + transform: scale(1); + } + ''; + }; + }; +} diff --git a/hm/modules/linux/tidal-hifi/themify.py b/hm/modules/linux/tidal-hifi/themify.py new file mode 100644 index 0000000..932524f --- /dev/null +++ b/hm/modules/linux/tidal-hifi/themify.py @@ -0,0 +1,162 @@ +import re +import argparse +import sys + + +def create_themed_css(css_content): + """ + Replaces hardcoded color values in a CSS string with stylix variables. + + This function uses a predefined mapping to find and replace color codes (hex and named) + with their corresponding Nix stylix variables (e.g., ${base00}). + + Args: + css_content (str): A string containing the source CSS. + + Returns: + str: The themed CSS content with stylix variables. + """ + # This dictionary maps stylix variables to a list of colors they should replace. + # It includes various formats (e.g., hex, named colors) for comprehensive matching. + # This structure makes it easy to see which colors are grouped and to extend the theme. + COLOR_MAPPING = { + # Base Backgrounds (Lightest) + "${base00}": [ + "#ffffff", + "#fff", + "#fdfdfd", + "#fbfbfb", + "#fcfcfc", + ], + # Secondary & Modal Backgrounds + "${base01}": ["#f1f1f1", "#efefef", "#eaebeb", "#e5e5e5"], + # Hover, Active, Disabled States + "${base02}": ["#e7e7e8", "#00000013", "#00000017"], + # Brighter Hover & Light Buttons + "${base03}": [ + "#e0e2e2", + "#d9d9d9", + "#e0e0e0", + "#d5d5d5", + "#dbdbdb", + "#0000001c", + "#0000001a", + "#0003", + ], + # UI Elements, Medium Grays, Scrollbars + "${base04}": [ + "#bbbebe", + "#cbcbcb", + "#d4d4d4", + "#c3c3c3", + "#b6b6b6", + "#dddde0", + "#ababab", + "#0000003d", + "#a6a6a6", + ], + # Primary Text & Icons (Darkest) + "${base05}": ["#000", "#000000", "#252525", "#2a2a2a", "#6e6e6e"], + # Secondary Text + "${base06}": [ + "#434343", + "#383838", + "#29292a", + "#000000b3", + "#000000ab", + "#0000009a", + ], + # "White" Text on Colored Backgrounds + "${base07}": ["#e6e6ed"], + # --- Accent Colors --- + # Red (Errors, Notifications) + "${base08}": ["#fa5656", "#d85959", "#ff5656"], + # Orange + "${base09}": ["#f98f54"], + # Yellow + "${base0A}": ["#d1a70d", "#bc991e", "#e6d165", "#ffd332"], + # Green + "${base0B}": ["#356e56", "#49c47a", "#5deaa6"], + # Cyan (Light) + "${base0C}": ["#d5edeb"], + # Blue / Slate + "${base0D}": ["#96a6af", "#97a1ff"], + # Teal / Primary Accent + "${base0E}": ["#39afa5", "#3cb4aa", "#3bafa5", "#5ecce3", "#8bd4cf"], + # Magenta / Pink + "${base0F}": ["#e860d2"], + } + + # Replace the named color 'white' and 'black' first. + css_content = re.sub(r"\bwhite\b", "${base00}", css_content, flags=re.IGNORECASE) + css_content = re.sub(r"\bblack\b", "${base05}", css_content, flags=re.IGNORECASE) + + # To handle box-shadows, we replace the hex color part directly. + # We target black shadows specifically, as requested by the stylix spec (`shadow = ${base00}`). + css_content = re.sub( + r"(box-shadow:.*?)#000000([0-9a-fA-F]*)", r"\1${base00}\2", css_content + ) + + # Iterate through the mapping and replace each color. + for stylix_var, color_list in COLOR_MAPPING.items(): + for color in color_list: + try: + # Create a regex pattern for the specific color, ignoring case. + pattern = re.compile(re.escape(color), re.IGNORECASE) + css_content = pattern.sub(stylix_var, css_content) + except re.error as e: + # This error handling is for cases where a color string might form an invalid regex. + print(f"Regex error for color '{color}': {e}", file=sys.stderr) + + return css_content + + +def main(): + """ + Main function to parse arguments and run the CSS theming process. + """ + # Set up command-line argument parsing. + parser = argparse.ArgumentParser( + description="Replaces hardcoded colors in a Tidal CSS file with stylix variables.", + formatter_class=argparse.RawTextHelpFormatter, + ) + parser.add_argument("input_file", help="The path to the source CSS file.") + parser.add_argument( + "-o", + "--output", + dest="output_file", + help="The path to write the themed CSS file to.\nIf omitted, prints to standard output.", + ) + args = parser.parse_args() + + # Read the source CSS from the specified input file. + try: + with open(args.input_file, "r", encoding="utf-8") as f: + source_css = f.read() + except FileNotFoundError: + print(f"Error: Input file not found at '{args.input_file}'", file=sys.stderr) + sys.exit(1) + except Exception as e: + print(f"Error reading input file: {e}", file=sys.stderr) + sys.exit(1) + + # Process the CSS content to replace colors. + themed_css = create_themed_css(source_css) + + # Write the result to the output file or print to the console. + if args.output_file: + try: + with open(args.output_file, "w", encoding="utf-8") as f: + f.write(themed_css) + print(f"Successfully wrote themed CSS to '{args.output_file}'") + except Exception as e: + print(f"Error writing to output file: {e}", file=sys.stderr) + sys.exit(1) + else: + # If no output file is specified, print to standard output. + print(themed_css) + + +# Execute the main function when the script is run. +if __name__ == "__main__": + main() diff --git a/hm/modules/linux/tidal-hifi/tidal-light.css b/hm/modules/linux/tidal-hifi/tidal-light.css new file mode 100644 index 0000000..e58c593 --- /dev/null +++ b/hm/modules/linux/tidal-hifi/tidal-light.css @@ -0,0 +1,684 @@ +/* +{ + "name": "Tidal Light", + "author": "Interstellar_1", + "description": "A light theme for Tidal. v0.3.5b" + "license": "MIT License" +} +*/ +:root { + /*background color*/ + --wave-color-solid-base-fill: white !important; + --wave-color-solid-accent-darkest: #f1f1f1 !important; + --wave-color-solid-base-brighter: #eaebeb !important; + --wave-color-solid-base-bright: #f1f1f1 !important; + --wave-color-opacity-base-bright-thick: #000 !important; + + /*hover*/ + --wave-color-solid-base-brightest: #e0e2e2 !important; + --wave-color-opacity-base-brightest-regular: #e5e5e5 !important; + --wave-color-opacity-contrast-fill-regular: #bbbebe !important; + --wave-color-solid-contrast-dark: #e0e2e2 !important; + --transparent-play-hover: #e1e1e166 !important; + + /*border*/ + --wave-color-opacity-contrast-fill-ultra-thin: #00000017 !important; + + /*button color*/ + --wave-color-opacity-contrast-fill-thin: #0000001c !important; + --wave-color-solid-accent-darker: #d5edeb !important; + --wave-color-solid-rainbow-red-darkest: #fa5656 !important; + --wave-color-solid-rainbow-red-darker: #d85959 !important; + --button-light: #d9d9d9 !important; + --button-medium: #cbcbcb !important; + + /*accents*/ + --wave-color-solid-accent-fill: #39afa5 !important; + --text-accent: #3cb4aa !important; + [data-w="textUrl"] { + color: var(--text-accent) !important; + } + --switch-accent: #3bafa5 !important; + --wave-color-solid-rainbow-yellow-fill: #d1a70d !important; + + /*primary text*/ + [data-wave-color="textDefault"] { + color: #000 !important; + } + [data-wave-color="textWhite"] { + color: #000 !important; + } + /*secondary text*/ + --wave-color-text-secondary: #434343 !important; + [data-wave-color="textSecondary"] { + color: #000000b3 !important; + } + --wave-color-solid-contrast-darker: #383838 !important; + --wave-color-opacity-contrast-fill-ultra-thick: #383838 !important; + /*icons*/ + --wave-color-solid-contrast-fill: #000 !important; + --wave-color-opacity-contrast-fill-thick: #0000009a !important; + + /*search*/ + --wave-color-opacity-base-brighter-ultra-thick: #c3c3c3 !important; + --search-background: #efefefe0 !important; + + /*user profile image*/ + --user-profile-linear-gradient: linear-gradient( + 160deg, + #356e56 1.22%, + #96a6af 40.51%, + #cbcbcb 79.07% + ) !important; +} + +body { + background-color: #fff !important; +} +/*GENERAL*/ +/*hide right shadow*/ +#playQueueSidebar { + box-shadow: none !important; +} + +/*buttons*/ +._activeTab_f47dafa { + background: #0000001c; +} + +/*HOMEPAGE*/ +/*artists*/ +.isLoggedIn--CEJH_::after { + background: none; +} + +/*hide album + playlist + mix bg*/ +._dataContainer_66f4f40::before, +._dataContainer_5bb6028::before, +._dataContainer_7feb4a2::before { + background-image: none; +} + +/*artist name*/ +.css-5pl3ge { + color: #000000ab; +} + +/*icons*/ +.icon--rmikT, +.icon--VV33E { + color: #000; +} +._icon_77f3f89 { + fill: #000 !important; +} + +/*SIDEBAR*/ +._active_3451dba:is(a._sidebarItem_730d27e, button._sidebarItem_730d27e) span { + color: var(--wave-color-solid-accent-fill) !important; +} + +/*player shadow*/ +.player--gAOQG.notFullscreen--xbpBL { + box-shadow: 0 -6px 24px #a6a6a626; +} + +/*ACCENT TEXT*/ +/*yellow*/ +._wave-badge-color-max_1oxl7_22 { + color: #bc991e; + background-color: #ffd33238; +} + +/*blue*/ +._wave-badge-color-high_1oxl7_17 { + color: var(--text-accent); +} + +.wave-text-title-bold { + color: #fff !important; +} + +/*none*/ +._wave-badge-color-default_1oxl7_7 { + background-color: #0000001a; + color: #000; +} + +svg._accentedIcon_d6d54e4 { + color: var(--wave-color-solid-accent-fill); + fill: var(--wave-color-solid-accent-fill) !important; +} + +.smallHeader--rfQsR { + --img: url(https://blocks.astratic.com/img/general-img-landscape.png) !important; +} + +/*shortcuts*/ +._shortcutItem_6c8e7b4 { + box-shadow: none !important; + background-color: var(--wave-color-solid-base-brighter) !important; +} + +._shortcutItem_6c8e7b4::after { + background: linear-gradient(#0000, #fff9); +} + +/*search*/ +.container--cl4MJ, +div.searchField--fgDKc, +div.searchField--fgDKc:focus, +._container_f1be359 { + background-color: var(--search-background) !important; + border-color: var(--wave-color-opacity-contrast-fill-ultra-thin) !important; +} + +.container--sRPa5 { + border-color: var(--wave-color-opacity-contrast-fill-ultra-thin) !important; +} + +.icon--nNXej, +._icon_49dd0aa { + background: linear-gradient(180deg, #fdfdfd, #dbdbdb) !important; +} + +a.searchPill--ED7eQ.active--e_BIx { + background: var(--wave-color-opacity-contrast-fill-thin) !important; +} + +.css-10jmp6g { + color: var(--wave-color-text-secondary) !important; +} + +._imageContainer_dfdf7bd::after, +._imageContainer_23303c1::after { + background: var(--transparent-play-hover) !important; +} + +/*updates*/ +.css-5pl3ge { + color: #000000ab !important; +} + +/*explict badge*/ +._explicitBadge_b93510b { + filter: invert(40%) brightness(110%) contrast(140%); +} + +#explicit-badge { + color: #000 !important; +} + +/*video badge*/ +.videoBadge--Tpdav { + fill: var(--wave-color-text-secondary); + filter: brightness(0.3) invert(0); +} + +/*canvas nav buttons*/ +.viewAllButton--Nb87U, +.css-7l8ggf { + background: #e0e0e0; +} + +.viewAllButton--Nb87U:hover, +.css-7l8ggf:hover { + background: #cbcbcb; +} + +/*album hover*/ +.overlay--ces1Z, +.overlay--Dn4ax, +.overlay--Cb6su, +.css-17bbmu3, +.css-ohr3gy, +._overlay_3c15650, +._overlay_aa1ee83, +._overlay_62e2cfd, +._overlay_e0e48ef, +._overlay_7fd73e6, +._overlay_f627136, +.css-1ug9uri, +.css-u7yq00 { + background: linear-gradient(#0000, #ffffff9e) !important; +} + +:is(._dataContainer_66f4f40 ._coverArtContainer_2eafdf9) + ._creditsOverlay_b234d8c { + background: #fdfdfd80; +} + +/*artist hover*/ +.css-179fhoi, +.css-fvlky0 { + background: linear-gradient(#0000, #ffffff9e) !important; +} + +/*play button hover*/ +.css-75d7zy { + background-color: #ffffffa6; + transition: 100ms; +} + +.css-75d7zy:hover { + background-color: var(--wave-color-solid-base-brighter); +} + +button.button--W_J5g.gray--tvcIF.contextMenuButton--Bcnyd:hover { + background-size: 200%; +} + +/*playlist hover*/ +.css-1voubjj:hover { + background-color: var(--wave-color-solid-base-brighter); + border: 5px var(--wave-color-opacity-contrast-fill-ultra-thin); +} + +/*queue popup*/ +.bottomGradient--BngZe, +._bottomGradient_104d99b { + background-image: none; +} + +#playQueueSidebar { + box-shadow: 0 20px 25px 5px #00000057; +} + +/*audio quality popup*/ +._containerMax_611862e { + background-color: transparent; +} + +/*PLAYER PANE*/ +.range--JNSfg { + background-color: #0000003d; +} + +:is(._player_1d16b04 button).withBackground[aria-checked="true"] { + background-color: #00000013; +} + +._range_ce0e571 { + background-color: var(--wave-color-opacity-contrast-fill-regular); +} + +/*album hover*/ +._notFullscreenOverlay_1442d60 { + background: linear-gradient(0deg, #ffffffa6, #ffffffa6); +} + +/*FULL VIEW*/ +.activeTab--bqTiv { + background: #00000017; +} + +.container--cl4MJ { + background: #fcfcfc63 !important; +} + +.css-u7yq00 { + background: #ffffff75; +} + +._bottomGradient_5c344de { + background: none; +} + +._button_84b8ffe { + background-color: var(--wave-color-solid-base-brighter); +} + +._button_84b8ffe:hover { + background-color: var(--wave-color-solid-base-brightest); +} + +._baseButton_15fc215:focus { + background: #0003; +} + +#nowPlaying { + background-image: none !important; +} + +/*thumbnail*/ +._albumImageOverlay_2eabc2b { + background: #ffffff4f; +} + +/*ALBUM*/ +.albumImage--i2CqD { + box-shadow: + 0 20px 50px 5px #b6b6b638, + 0 20px 40px 0 #00000024; +} + +._button_f1c7fcb { + background: var(--wave-color-solid-base-brighter); +} + +.artist-link { + color: #252525; +} + +/*remove bg image*/ +[class^="_dataContainer_"]:before { + --img: none !important; + background-image: none !important; +} + +/*playlist*/ +.refreshButton--bRrPi { + color: #000; +} + +/*tracks page*/ +.variantPrimary--pjymy, +._button_3357ce6 { + background-color: var(--button-light); +} + +.wave-text-body-demi { + color: #000; +} + +/*track hover*/ +._rowContainer_ebb4cfc:hover { + background: var(--wave-color-solid-base-brightest) !important; +} + +/*DIALOUGES*/ +.ReactModal__Content { + background: #f1f1f1 !important; +} + +.label--fycqD.unchecked--goEjz { + background-color: #ababab; +} + +.label--fycqD.checked--RVmZV { + background-color: var(--switch-accent); +} + +.primary--NLSX4 { + background-color: #d5d5d5; +} + +.primary--NLSX4:hover { + background-color: var(--wave-color-opacity-contrast-fill-regular) !important; +} + +.primary--NLSX4:disabled { + background-color: #e7e7e8; +} + +.primary--NLSX4:disabled:hover { + background-color: #e7e7e8; +} + +/*popups*/ +.notification--hckxF, +.native-range { + box-shadow: 0 20px 50px 5px #0000002e; +} + +._notification_99c9c6e { + box-shadow: 0 16px 32px #0000; +} + +._notification_99c9c6e._error_0b778e5 { + background: var(--wave-color-solid-rainbow-red-darker); +} + +.errorIcon--VvndK { + fill: #000 !important; +} + +/*PROFILE*/ +.followingTag--CKRME, +.wave-text-footnote-medium { + color: var(--text-accent) !important; +} + +._wave-btn-rank-primary_1lao2_58:hover { + background-color: #8bd4cf; +} + +._button_94c5125 { + background-color: transparent !important; +} + +.profilePicture--yrdRB { + box-shadow: none; +} + +._input_15c0d78:focus { + color: var(--wave-color-solid-contrast-darker); +} + +/*my picks*/ +#My\ favorite\ track\ on\ repeat, +._selectedPrompt_dac4cfc[style*="--prompt-base-color: #97A1FF1A"] { + --prompt-base-color: #97a1ff !important; + --prompt-color: #5ecce3 !important; +} + +#My\ major\ mood\ booster, +._selectedPrompt_dac4cfc[style*="--prompt-base-color: #FF91531A"] { + --prompt-base-color: #f98f54 !important; + --prompt-color: #e6d165 !important; +} + +#My\ go-to\ artist\ right\ now, +._selectedPrompt_dac4cfc[style*="--prompt-base-color: #FF53531A"] { + --prompt-base-color: #ff5656 !important; + --prompt-color: #e860d2 !important; +} + +#My\ top\ album\ recently, +._selectedPrompt_dac4cfc[style*="--prompt-base-color: #53FF981A"] { + --prompt-base-color: #49c47a !important; + --prompt-color: #5deaa6 !important; +} + +._wave-btn-rank-clean_1lao2_127:hover { + color: #fff; + background-color: #6e6e6e38 !important; +} + +#pick-promt-item-search-field { + color: #000; +} + +/*ARTIST PAGE*/ +._background_4a10ea2:after { + content: "" !important; + position: absolute !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + bottom: 0 !important; + background-color: #ffffff4a !important; +} + +:is(._background_a548b6d ._image_7ba9b97):before { + background-color: #ffffff21 !important; + background-image: none !important; + background-blend-mode: normal !important; +} + +._background_a548b6d { + background-image: linear-gradient(180deg, #fbfbfb66 0, #fff) !important; +} + +:is(._background_a548b6d ._image_7ba9b97):after { + background-image: var(--img) !important; + background-position: center !important; + background-repeat: no-repeat !important; + background-size: cover !important; + content: "" !important; + filter: blur(5px) brightness(30%) !important; + inset: -20px 0 !important; + mask-image: linear-gradient(0deg, #fff0 43%, #fff) !important; + position: absolute !important; +} + +._mainImage_433f1ff:is(._background_a548b6d ._image_7ba9b97):after { + mask-image: linear-gradient(0deg, #fff0, #fff) !important; + filter: brightness(100%) !important; + height: 87% !important; +} + +.buttonText--LMsAT { + color: #fff !important; +} + +.css-10jmp6g { + color: #2a2a2a; +} + +.button--_0I_t { + background-color: var(--button-light); +} + +.button--_0I_t:hover { + background-color: var(--wave-color-opacity-contrast-fill-regular); +} + +#player__play { + color: #000; +} + +.primary--NLSX4:hover { + background-color: #dddde0; +} + +:is(._buttons_ff12873 ._following_657edad) ._icon_29252d0 { + fill: var(--wave-color-solid-accent-fill) !important; +} + +/*bio*/ +._dialog_148b5df { + color: black; +} + +/*producer discography*/ +.css-1thhtwd { + background: var(--wave-color-solid-base-brighter); +} + +.css-1thhtwd:hover { + background: var(--wave-color-opacity-contrast-fill-regular); +} + +._buttonActive_5125b72 { + background: var(--button-light); +} + +._buttonActive_5125b72:hover { + background: var(--wave-color-opacity-contrast-fill-regular); +} + +._buttonActive_5125b72 > .wave-text-body-medium { + color: #000; +} +/*SETTINGS*/ +._container_b4f1e20._fillDark_a1e5896 > div, +._container_9a0abb9 { + background: #f1f1f1 !important; +} + +._select_ef84104 { + background: var(--wave-color-solid-accent-darker) !important; +} + +.licenseFrame--C_hup { + background: #29292a; +} + +svg#lastfm path { + fill: #000; +} + +._button_94c5125 { + background: var(--wave-color-solid-base-brighter); +} + +/*scrollbars*/ +::-webkit-scrollbar { + background-color: transparent !important; + border: none !important; + width: 8px !important; +} + +::-webkit-scrollbar-track { + background-color: var(--wave-color-solid-base-brighter) !important; + box-shadow: none; +} + +::-webkit-scrollbar-thumb { + background-color: #d4d4d4 !important; + border: none !important; +} + +/*luna*/ +body + > div.ReactModalPortal + > div + > div + > div.modalBody--TFBWU.selectableText--UDUkZ.modalText--gCapb.subtitle--dYfEG + > neptune-reactive-root + > div + > button, +#main + > div.__NEPTUNE_PAGE + > neptune-reactive-root + > div + > div + > div:nth-child(2) + > div + > div.neptune-card + > div + > div:nth-child(2) + > div:nth-child(1) + > button:nth-child(1), +#main + > div.__NEPTUNE_PAGE + > neptune-reactive-root + > div + > div + > div:nth-child(2) + > div + > div.neptune-card + > div + > div:nth-child(2) + > div:nth-child(1) + > button:nth-child(2) { + color: #000 !important; +} + +.neptune-switch::after { + background-color: #fff !important; +} + +.css-16hze37, +#main + > div:nth-child(3) + > div + > div.MuiContainer-root.MuiContainer-maxWidthLg.css-sot3eg + > div + > div:nth-child(2) + > div.MuiStack-root.css-16a8gxx + > div { + color: #e6e6ed !important; +} + +.css-yc8597, +.css-pfqxe1, +.css-axw7ok { + color: #fff !important; +} + +to { + opacity: 1; + transform: scale(1); +}