From 17bee0e3854163c9ce142b502d8dad30caa52c5d Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Sun, 13 Apr 2025 22:15:25 +1000 Subject: feat: add music visualiser --- app.tsx | 2 + scss/mediadisplay.scss | 139 +++++++++++++++++++++++ src/modules/mediadisplay/index.tsx | 188 ++++++++++++++++++++++++++++++++ src/modules/mediadisplay/visualiser.tsx | 76 +++++++++++++ src/modules/sidebar/dashboard.tsx | 6 +- src/modules/sidebar/modules/media.tsx | 6 +- src/utils/strings.ts | 5 + style.scss | 1 + 8 files changed, 413 insertions(+), 10 deletions(-) create mode 100644 scss/mediadisplay.scss create mode 100644 src/modules/mediadisplay/index.tsx create mode 100644 src/modules/mediadisplay/visualiser.tsx diff --git a/app.tsx b/app.tsx index 3ea6413..88312e1 100644 --- a/app.tsx +++ b/app.tsx @@ -1,5 +1,6 @@ import Bar from "@/modules/bar"; import Launcher from "@/modules/launcher"; +import MediaDisplay from "@/modules/mediadisplay"; import NavBar from "@/modules/navbar"; import NotifPopups from "@/modules/notifpopups"; import Osds from "@/modules/osds"; @@ -78,6 +79,7 @@ App.start({ ; ; Monitors.get_default().forEach(m => ); + Monitors.get_default().forEach(m => ); Monitors.get_default().forEach(m => ); Monitors.get_default().forEach(m => ); Monitors.get_default().forEach(m => ); diff --git a/scss/mediadisplay.scss b/scss/mediadisplay.scss new file mode 100644 index 0000000..701a0ce --- /dev/null +++ b/scss/mediadisplay.scss @@ -0,0 +1,139 @@ +@use "sass:color"; +@use "scheme"; +@use "lib"; +@use "font"; + +.mediadisplay { + @include font.mono; + + background-color: scheme.$mantle; + color: scheme.$text; + padding: lib.s(20); + min-height: lib.s(200); + + .visualiser { + background-color: scheme.$primary; // Visualiser colour + margin-right: lib.s(5); // Gaps between bars + min-width: lib.s(10); // Bar width + color: scheme.$error; + font-size: lib.s(24); + font-weight: bold; + } + + .cover-art { + @include lib.rounded(10); + @include lib.element-decel; + + background-position: center; + background-repeat: no-repeat; + background-size: cover; + min-width: lib.s(196); + min-height: lib.s(196); + font-size: lib.s(96); + font-weight: bold; + background-color: scheme.$surface0; + color: scheme.$subtext0; + } + + .details { + @include font.title; + + font-size: lib.s(14); + margin-top: lib.s(5); + margin-left: lib.s(15); + + .title { + font-size: lib.s(28); + font-weight: 500; + color: scheme.$text; + } + + .artist { + font-size: lib.s(18); + color: scheme.$secondary; + } + + .controls { + @include lib.rounded(1000); + @include font.icon; + + margin-top: lib.s(10); + background-color: color.change(scheme.$overlay0, $alpha: 0.4); + font-size: lib.s(28); + padding: lib.s(3) lib.s(8); + + @include lib.spacing; + + & > button { + @include lib.element-decel; + + &:hover, + &:focus { + color: color.mix(scheme.$subtext1, scheme.$subtext0, 50%); + } + + &:active { + color: scheme.$subtext0; + } + + &:disabled { + color: scheme.$subtext0; + } + } + } + } + + .center-module { + @include lib.rounded(20); + margin: 0 lib.s(40); + background-color: color.change(scheme.$surface1, $alpha: 0.4); + } + + .selector { + @include lib.rounded(15); + @include lib.element-decel; + + background-color: color.change(scheme.$overlay0, $alpha: 0.4); + padding: lib.s(8) lib.s(15); + + .identity { + @include lib.spacing(8); + } + + button { + @include lib.element-decel; + + &:hover, + &:focus { + color: color.mix(scheme.$subtext1, scheme.$subtext0, 50%); + } + + &:active { + color: scheme.$subtext0; + } + } + + .list > button { + margin-top: lib.s(5); + color: scheme.$subtext1; + + &:hover, + &:focus { + color: color.mix(scheme.$subtext1, scheme.$subtext0, 50%); + } + + &:active { + color: scheme.$subtext0; + } + } + } + + .time { + @include lib.rounded(1000); + + font-size: lib.s(16); + background-color: color.change(scheme.$overlay0, $alpha: 0.4); + padding: lib.s(5) lib.s(10); + margin-bottom: lib.s(10); + } +} diff --git a/src/modules/mediadisplay/index.tsx b/src/modules/mediadisplay/index.tsx new file mode 100644 index 0000000..307087c --- /dev/null +++ b/src/modules/mediadisplay/index.tsx @@ -0,0 +1,188 @@ +import type { Monitor } from "@/services/monitors"; +import Players from "@/services/players"; +import { lengthStr } from "@/utils/strings"; +import { bind, Variable } from "astal"; +import { App, Astal, Gtk } from "astal/gtk3"; +import AstalMpris from "gi://AstalMpris"; +import Visualiser from "./visualiser"; + +type Selected = Variable; + +const bindIcon = (player: AstalMpris.Player) => + bind(player, "identity").as(i => { + const icon = `caelestia-${i?.toLowerCase().replaceAll(" ", "-")}-symbolic`; + return Astal.Icon.lookup_icon(icon) ? icon : "caelestia-media-generic-symbolic"; + }); + +const PlayerButton = ({ + player, + selected, + showDropdown, +}: { + player: AstalMpris.Player; + selected: Selected; + showDropdown: Variable; +}) => ( + +); + +const Selector = ({ player, selected }: { player?: AstalMpris.Player; selected: Selected }) => { + const showDropdown = Variable(false); + + return ( + + + + + {bind(Players.get_default(), "list").as(ps => + ps + .filter(p => p !== player) + .map(p => ) + )} + + + + ); +}; + +const NoMedia = ({ selected }: { selected: Selected }) => ( + + + + + +