added media widget
This commit is contained in:
1 parent
8ee6cd6b0e
commit
ceda1adee3
4 files changed
+249
-44
No files matched your search
+36
-3
@@ -12,7 +12,7 @@ window.Bar {
|
|||||||
color: $fg-color;
|
color: $fg-color;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
||||||
>centerbox {
|
> centerbox {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
margin: 2px 5px 0 5px;
|
margin: 2px 5px 0 5px;
|
||||||
@@ -83,7 +83,7 @@ window.Bar {
|
|||||||
transition: 300ms;
|
transition: 300ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Workspaces {
|
.Workspaces {
|
||||||
button {
|
button {
|
||||||
all: unset;
|
all: unset;
|
||||||
background-color: black;
|
background-color: black;
|
||||||
@@ -115,13 +115,46 @@ window.Bar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// button {
|
// button {
|
||||||
// border-radius: 8px;
|
// border-radius: 8px;
|
||||||
// padding: 0 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 {
|
window.Powermenu {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|||||||
+69
-41
@@ -1,57 +1,85 @@
|
|||||||
import { App, Astal, Gtk, Gdk } from "astal/gtk3"
|
import { App, Astal, Gtk, Gdk } from "astal/gtk3";
|
||||||
|
import Mpris from "gi://AstalMpris";
|
||||||
|
import { bind } from "astal";
|
||||||
import {
|
import {
|
||||||
PowerMenu,
|
PowerMenu,
|
||||||
Cpu,
|
Cpu,
|
||||||
BatteryLevel,
|
BatteryLevel,
|
||||||
Ram,
|
Ram,
|
||||||
Storage,
|
Storage,
|
||||||
Workspaces,
|
Workspaces,
|
||||||
FocusedClient,
|
FocusedClient,
|
||||||
Time,
|
Time,
|
||||||
SysTray
|
SysTray,
|
||||||
} from "./modules/export"
|
} from "./modules/export";
|
||||||
|
import { close_all_menus } from "./utils/windows";
|
||||||
|
import Media from "./Media";
|
||||||
|
|
||||||
export default function Bar(gdkmonitor: Gdk.Monitor) {
|
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"
|
className="Bar"
|
||||||
name="Bar"
|
name="Bar"
|
||||||
gdkmonitor={gdkmonitor}
|
gdkmonitor={gdkmonitor}
|
||||||
exclusivity={Astal.Exclusivity.EXCLUSIVE}
|
exclusivity={Astal.Exclusivity.EXCLUSIVE}
|
||||||
anchor={TOP | LEFT | RIGHT}
|
anchor={TOP | LEFT | RIGHT}
|
||||||
application={App}>
|
application={App}
|
||||||
|
>
|
||||||
<centerbox>
|
<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
|
<button
|
||||||
onClicked="/home/tola/dotfiles/rofi/launcher/launcher.sh"
|
onClicked={() => {
|
||||||
halign={Gtk.Align.START}
|
close_all_menus("Mediamenu");
|
||||||
className="Menubutton"
|
App.toggle_window("Mediamenu");
|
||||||
|
}}
|
||||||
|
className="Menubutton"
|
||||||
>
|
>
|
||||||
|
|
||||||
</button>
|
</button>
|
||||||
<Cpu />
|
) : (
|
||||||
<Ram />
|
<></>
|
||||||
<Storage />
|
),
|
||||||
{/*<FocusedClient />*/}
|
)}
|
||||||
</box>
|
<SysTray />
|
||||||
<box hexpand halign={Gtk.Align.CENTER} className="RoudedBlock">
|
<BatteryLevel />
|
||||||
<Workspaces />
|
<Time />
|
||||||
</box>
|
<button
|
||||||
<box hexpand halign={Gtk.Align.END} className="RoudedBlock">
|
onClicked={() => {
|
||||||
<SysTray />
|
close_all_menus("powermenu");
|
||||||
<BatteryLevel />
|
App.toggle_window("powermenu");
|
||||||
<Time />
|
}}
|
||||||
<button
|
halign={Gtk.Align.START}
|
||||||
onClicked={() => App.toggle_window("powermenu")}
|
className="Menubutton"
|
||||||
halign={Gtk.Align.START}
|
>
|
||||||
className="Menubutton"
|
⏻
|
||||||
>
|
</button>
|
||||||
⏻
|
</box>
|
||||||
</button>
|
|
||||||
</box>
|
|
||||||
</centerbox>
|
</centerbox>
|
||||||
</window>
|
</window>
|
||||||
<PowerMenu />
|
<PowerMenu />
|
||||||
|
<Media />
|
||||||
</>
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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 };
|
||||||
Reference in new issue
Block a user