added media widget

This commit is contained in:
wt
2025-03-11 12:49:58 +07:00
parent 8ee6cd6b0e
commit ceda1adee3
4 changed files with 251 additions and 46 deletions
+37 -4
View File
@@ -12,7 +12,7 @@ window.Bar {
color: $fg-color;
font-weight: bold;
>centerbox {
> centerbox {
background: transparent;
border-radius: 20px;
margin: 2px 5px 0 5px;
@@ -83,7 +83,7 @@ window.Bar {
transition: 300ms;
}
.Workspaces {
.Workspaces {
button {
all: unset;
background-color: black;
@@ -115,13 +115,46 @@ window.Bar {
}
}
// button {
// border-radius: 8px;
// padding: 0 8px;
// }
}
window.Media {
margin: 5px;
padding: 5px;
background-color: transparent;
box {
margin: 5px;
background-color: black;
border-radius: 25px;
padding: 2px;
}
box.title {
padding: 5px;
margin: 0;
label {
font-weight: bold;
font-size: 1.1em;
}
}
.Cover {
min-width: 120px;
min-height: 120px;
border-radius: 9px;
margin-right: 0.6rem;
background-size: contain;
background-position: center;
}
label.artist {
padding: 5px;
}
}
window.Powermenu {
margin: 5px;
background-color: transparent;
@@ -137,7 +170,7 @@ window.Powermenu {
background-color: black;
border-radius: 25px;
transition: 300ms;
&:hover {
background-color: gray;
}
+70 -42
View File
@@ -1,57 +1,85 @@
import { App, Astal, Gtk, Gdk } from "astal/gtk3"
import {
PowerMenu,
Cpu,
BatteryLevel,
Ram,
Storage,
Workspaces,
FocusedClient,
Time,
SysTray
} from "./modules/export"
import { App, Astal, Gtk, Gdk } from "astal/gtk3";
import Mpris from "gi://AstalMpris";
import { bind } from "astal";
import {
PowerMenu,
Cpu,
BatteryLevel,
Ram,
Storage,
Workspaces,
FocusedClient,
Time,
SysTray,
} from "./modules/export";
import { close_all_menus } from "./utils/windows";
import Media from "./Media";
export default function Bar(gdkmonitor: Gdk.Monitor) {
const { TOP, LEFT, RIGHT } = Astal.WindowAnchor
const { TOP, LEFT, RIGHT } = Astal.WindowAnchor;
const mpris = Mpris.get_default();
return <><window
return (
<>
<window
className="Bar"
name="Bar"
gdkmonitor={gdkmonitor}
exclusivity={Astal.Exclusivity.EXCLUSIVE}
anchor={TOP | LEFT | RIGHT}
application={App}>
application={App}
>
<centerbox>
<box hexpand halign={Gtk.Align.START} className="RoudedBlock">
<box hexpand halign={Gtk.Align.START} className="RoudedBlock">
<button
onClicked="/home/tola/dotfiles/rofi/launcher/launcher.sh"
halign={Gtk.Align.START}
className="Menubutton"
>
</button>
<Cpu />
<Ram />
<Storage />
{/*<FocusedClient />*/}
</box>
<box hexpand halign={Gtk.Align.CENTER} className="RoudedBlock">
<Workspaces />
</box>
<box hexpand halign={Gtk.Align.END} className="RoudedBlock">
{bind(mpris, "players").as((ps) =>
ps[0] ? (
<button
onClicked="/home/tola/dotfiles/rofi/launcher/launcher.sh"
halign={Gtk.Align.START}
className="Menubutton"
onClicked={() => {
close_all_menus("Mediamenu");
App.toggle_window("Mediamenu");
}}
className="Menubutton"
>
</button>
<Cpu />
<Ram />
<Storage />
{/*<FocusedClient />*/}
</box>
<box hexpand halign={Gtk.Align.CENTER} className="RoudedBlock">
<Workspaces />
</box>
<box hexpand halign={Gtk.Align.END} className="RoudedBlock">
<SysTray />
<BatteryLevel />
<Time />
<button
onClicked={() => App.toggle_window("powermenu")}
halign={Gtk.Align.START}
className="Menubutton"
>
⏻
</button>
</box>
) : (
<></>
),
)}
<SysTray />
<BatteryLevel />
<Time />
<button
onClicked={() => {
close_all_menus("powermenu");
App.toggle_window("powermenu");
}}
halign={Gtk.Align.START}
className="Menubutton"
>
⏻
</button>
</box>
</centerbox>
</window>
<PowerMenu />
</window>
<PowerMenu />
<Media />
</>
);
}
+122
View File
@@ -0,0 +1,122 @@
import { App } from "astal/gtk3";
import { bind } from "astal";
import { Astal, Gtk } from "astal/gtk3";
import Mpris from "gi://AstalMpris";
function lengthStr(length: number) {
const min = Math.floor(length / 60);
const sec = Math.floor(length % 60);
const sec0 = sec < 10 ? "0" : "";
return `${min}:${sec0}${sec}`;
}
export default function Media() {
const { TOP, RIGHT } = Astal.WindowAnchor;
const mpris = Mpris.get_default();
return (
<window
anchor={TOP | RIGHT}
name="Mediamenu"
className="Media"
application={App}
visible={false}
>
<box>
{bind(mpris, "players").as((ps) =>
ps[0] ? (
<box>
<box
className="Cover"
valign={Gtk.Align.CENTER}
css={bind(ps[0], "coverArt").as(
(cover) => `background-image: url('${cover}');`,
)}
/>
<box vertical>
<box className="title">
<label
truncate
hexpand
halign={Gtk.Align.START}
label={bind(ps[0], "metadata").as(() => `${ps[0].title}`)}
/>
<icon
icon={bind(ps[0], "entry").as((e) =>
Astal.Icon.lookup_icon(e)
? e
: "audio-x-generic-symbolic",
)}
/>
</box>
<label
halign={Gtk.Align.START}
valign={Gtk.Align.START}
className="artist"
vexpand
wrap
label={bind(ps[0], "metadata").as(() => `${ps[0].artist}`)}
/>
<slider
visible={bind(ps[0], "length").as((l) => l > 0)}
onDragged={({ value }) =>
(ps[0].position = value * ps[0].length)
}
value={bind(ps[0], "position").as((p) =>
ps[0].length > 0 ? p / ps[0].length : 0,
)}
/>
<centerbox className="actions">
<label
hexpand
className="position"
halign={Gtk.Align.START}
visible={bind(ps[0], "length").as((l) => l > 0)}
label={bind(ps[0], "position").as(lengthStr)}
/>
<box>
<button
onClicked={() => ps[0].previous()}
visible={bind(ps[0], "canGoPrevious")}
>
<icon icon="media-skip-backward-symbolic" />
</button>
<button
onClicked={() => ps[0].play_pause()}
visible={bind(ps[0], "canControl")}
>
<icon
icon={bind(ps[0], "playbackStatus").as((s) =>
s === Mpris.PlaybackStatus.PLAYING
? "media-playback-pause-symbolic"
: "media-playback-start-symbolic",
)}
/>
</button>
<button
onClicked={() => ps[0].next()}
visible={bind(ps[0], "canGoNext")}
>
<icon icon="media-skip-forward-symbolic" />
</button>
</box>
<label
className="length"
hexpand
halign={Gtk.AlignEND}
visible={bind(ps[0], "length").as((l) => l > 0)}
label={bind(ps[0], "length").as((l) =>
l > 0 ? lengthStr(l) : "0:00",
)}
/>
</centerbox>
</box>
</box>
) : (
<label label="Nothing Playing" />
),
)}
</box>
</window>
);
}
+22
View File
@@ -0,0 +1,22 @@
import { App, Astal, Gtk, Gdk } from "astal/gtk3";
function close_all_menus(safe: string) {
const menuWindows = App.get_windows()
.filter((w) => {
if (w.name) {
return /.*menu/.test(w.name);
}
return false;
})
.map((window) => window.name);
menuWindows.forEach((window) => {
if (window && window != safe) {
App.get_window(window)?.set_visible(false);
}
});
// App.get_window("powermenu").set_visible(false);
// App.get_window("Media").set_visible(false);
}
export { close_all_menus };