mirror of
https://github.com/zoriya/flake.git
synced 2026-06-06 12:02:58 +00:00
Mpris material colors
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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 > * {
|
||||
|
||||
Reference in New Issue
Block a user