From 3ac43cb1e81397091b5da6c319bca7a17d726c62 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 7 Jul 2024 12:15:37 +0700 Subject: [PATCH] Mpris material colors --- modules/common/ags/covercolors.py | 3 +- modules/common/ags/default.nix | 24 +-- modules/common/ags/modules/materialcolors.js | 26 ---- modules/common/ags/modules/mpris.js | 155 +++++++++++-------- modules/common/ags/style.css | 6 +- 5 files changed, 104 insertions(+), 110 deletions(-) delete mode 100644 modules/common/ags/modules/materialcolors.js diff --git a/modules/common/ags/covercolors.py b/modules/common/ags/covercolors.py index 2c72db5..db3059d 100644 --- a/modules/common/ags/covercolors.py +++ b/modules/common/ags/covercolors.py @@ -13,8 +13,7 @@ def cache_and_get_colors(file_path): file_hash = hashlib.sha256(file_path.encode('utf-8')).hexdigest() cache_path = os.path.join(CACHE_DIR, file_hash[:2], file_hash[2:]) - if not os.path.exists(cache_path): - os.makedirs(cache_path) + os.makedirs(cache_path, exist_ok=True) colors_path = os.path.join(cache_path, "colors.json") if os.path.exists(colors_path): diff --git a/modules/common/ags/default.nix b/modules/common/ags/default.nix index 2a714e8..6e0f0dd 100644 --- a/modules/common/ags/default.nix +++ b/modules/common/ags/default.nix @@ -15,24 +15,14 @@ ]; installPhase = "install -Dm755 ${./covercolors.py} $out/bin/covercolors"; }; - # ags = pkgs.stdenv.mkDerivation rec { - # name = "ags"; - # nativeBuildInputs = with pkgs; [makeWrapper]; - # propagatedBuildInputs = [ - # covercolors - # ]; - # dontUnpack = true; - # installPhase = " - # wrapProgram ${pkgs.ags}/bin/ags --prefix PATH : '${lib.makeBinPath propagatedBuildInputs}' - # "; - # }; - ags = pkgs.ags.overrideAttrs (oldAttrs: { - runtimeDependencies = [covercolors]; - }); systemdTarget = "graphical-session.target"; in { - # TODO: Remove this after testing - home.packages = [ags]; + home.packages = [ + # TODO: Remove this after testing + pkgs.ags + # TODO: Find a way to add this for ags only + covercolors + ]; systemd.user.services.ags = { Unit = { Description = " A customizable and extensible shell "; @@ -43,7 +33,7 @@ in { Service = { Type = "simple"; - ExecStart = "${ags}/bin/ags"; + ExecStart = "${pkgs.ags}/bin/ags"; Restart = "always"; }; diff --git a/modules/common/ags/modules/materialcolors.js b/modules/common/ags/modules/materialcolors.js deleted file mode 100644 index 4ab31d0..0000000 --- a/modules/common/ags/modules/materialcolors.js +++ /dev/null @@ -1,26 +0,0 @@ -/** @param {import("types/service/mpris").MprisPlayer} player */ -export const getMaterialColors = (player) => { - const ret = Variable({ - primary: "#222222", - onPrimary: "#ffffff", - background: "#222222", - onBackground: "#ffffff", - coverPath: "", - }); - - player.bind("cover_path").as((cover) => { - Utils.timeout(100, () => { - Utils.execAsync(["covercolors", cover]) - .then((colors) => { - const col = JSON.parse(colors); - if (!col) return; - col.coverPath = cover; - ret.setValue(col); - }) - .catch(print); - }); - }); - - return ret; -}; - diff --git a/modules/common/ags/modules/mpris.js b/modules/common/ags/modules/mpris.js index 307127b..afa4c62 100644 --- a/modules/common/ags/modules/mpris.js +++ b/modules/common/ags/modules/mpris.js @@ -1,5 +1,3 @@ -import { getMaterialColors } from "./materialcolors.js"; - const mpris = await Service.import("mpris"); /** @param {{player: import("types/service/mpris").MprisPlayer} & import("types/widgets/icon").IconProps} props */ @@ -115,77 +113,110 @@ export const MprisPlayer = ({ player, ...props }) => { return Widget.Box({ visible: player.bind("play_back_status").as((x) => x !== "Stopped"), className: `mpris-cover-art ${props.className}`, - css: colors.bind().as( - (x) => ` - background-image: radial-gradient(circle, rgba(0, 0, 0, 0.4) 30%, ${x.primary}), url("${x.coverPath}"); \ - color: ${x.onBackground}; + css: Utils.merge( + [colors.bind(), player.bind("cover_path")], + (colors, cover) => ` + background-image: radial-gradient(circle, rgba(0, 0, 0, 0.4) 30%, ${colors.primary}), url("${cover}"); \ + color: ${colors.onBackground}; `, ), vexpand: false, children: [ - Widget.Box({ + Widget.CenterBox({ vertical: true, hexpand: true, - children: [ - Widget.Box({ - vertical: true, - vexpand: true, - css: colors.bind().as((x) => `color: ${x.onBackground}`), - child: PlayerIcon({ player }), - }), - Widget.Box({ - hexpand: true, - children: [ - Widget.Box({ - css: colors.bind().as((x) => `color: ${x.onBackground}`), - vertical: true, - vpack: "center", - hexpand: true, - children: [ - TitleLabel({ - player, - css: "font-weight: 600; font-size: 19px;", - }), - ArtistLabel({ - player, - css: "font-weight: 400; font-size: 17px;", - }), - ], - }), - Widget.Box({ - children: [ - PlayPause({ - player, - hpack: "end", - className: "mpris-play", - css: colors.bind().as( - (x) => ` + startWidget: Widget.Box({ + vertical: true, + vexpand: true, + css: colors.bind().as((x) => `color: ${x.onBackground}`), + child: PlayerIcon({ player }), + }), + centerWidget: Widget.Box({ + hexpand: true, + children: [ + Widget.Box({ + css: colors.bind().as( + (x) => ` + color: ${x.onBackground}; + margin-right: 12px; + `, + ), + vertical: true, + vpack: "center", + hexpand: true, + children: [ + TitleLabel({ + player, + css: "font-weight: 600; font-size: 19px;", + maxWidthChars: 33, + }), + ArtistLabel({ + player, + css: "font-weight: 400; font-size: 17px;", + maxWidthChars: 40, + }), + ], + }), + Widget.Box({ + children: [ + PlayPause({ + player, + hpack: "end", + className: "mpris-play", + css: colors.bind().as( + (x) => ` background-color: ${x.primary}; color: ${x.onPrimary}; `, - ), - }), - ], - }), - ], - }), - Widget.Box({ - css: colors.bind().as((x) => `color: ${x.onBackground}`), - vpack: "end", - children: [ - Widget.Box({ - hexpand: true, - children: [ - PreviousButton({ player, css: "margin-left: 16px;" }), - PositionSlider({ player, hexpand: true }), - NextButton({ player, css: "margin-right: 16px;" }), - ], - }), - ], - }), - ], + ), + }), + ], + }), + ], + }), + endWidget: Widget.Box({ + css: colors.bind().as((x) => `color: ${x.onBackground}`), + vpack: "end", + children: [ + Widget.Box({ + hexpand: true, + children: [ + PreviousButton({ player, css: "margin-left: 16px;" }), + PositionSlider({ player, hexpand: true }), + NextButton({ player, css: "margin-right: 16px;" }), + ], + }), + ], + }), }), ], ...props, }); }; + +// TODO: Move ret inside getMaterialColors to support multiple players. +const ret = Variable({ + primary: "#222222", + onPrimary: "#ffffff", + background: "#222222", + onBackground: "#ffffff", +}); +/** @param {import("types/service/mpris").MprisPlayer} player */ +export const getMaterialColors = (player) => { + // TODO: Move that to a hook to allow graceful disconnections + player.connect("changed", (player) => { + const cover = player.cover_path; + // TODO: Wait for the cover to be downloaded, currently we hope that it's ready in <100ms + Utils.timeout(100, () => { + Utils.execAsync(["covercolors", cover]) + .then((colors) => { + const col = JSON.parse(colors); + if (!col) return; + ret.setValue(col); + }) + .catch(print); + }); + }); + + return ret; +}; diff --git a/modules/common/ags/style.css b/modules/common/ags/style.css index da5bca4..a9a70f6 100644 --- a/modules/common/ags/style.css +++ b/modules/common/ags/style.css @@ -119,10 +119,10 @@ mark { /* Quick settings */ .qs-container { - min-width: 340px; + min-width: 500px; padding: 25px; margin: 10px; - border-radius: 40px; + border-radius: 20px; } .qs-button { padding: 0px; @@ -170,7 +170,7 @@ mark { background-position: center; margin: 10px 0; min-height: 205px; - border-radius: 30px; + border-radius: 20px; transition: all 0.2s; } .mpris-cover-art > * {