From d0fbb19623e4fb6097e1ff3ee49c6a76a0928d0e Mon Sep 17 00:00:00 2001 From: srdusr Date: Thu, 13 Jun 2024 13:11:05 +0200 Subject: Add ags --- .config/ags/widget/quicksettings/widgets/Media.ts | 153 ++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 .config/ags/widget/quicksettings/widgets/Media.ts (limited to '.config/ags/widget/quicksettings/widgets/Media.ts') diff --git a/.config/ags/widget/quicksettings/widgets/Media.ts b/.config/ags/widget/quicksettings/widgets/Media.ts new file mode 100644 index 0000000..52254ea --- /dev/null +++ b/.config/ags/widget/quicksettings/widgets/Media.ts @@ -0,0 +1,153 @@ +import { type MprisPlayer } from "types/service/mpris" +import icons from "lib/icons" +import options from "options" +import { icon } from "lib/utils" + +const mpris = await Service.import("mpris") +const players = mpris.bind("players") +const { media } = options.quicksettings + +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}` +} + +const Player = (player: MprisPlayer) => { + const cover = Widget.Box({ + class_name: "cover", + vpack: "start", + css: Utils.merge([ + player.bind("cover_path"), + player.bind("track_cover_url"), + media.coverSize.bind(), + ], (path, url, size) => ` + min-width: ${size}px; + min-height: ${size}px; + background-image: url('${path || url}'); + `), + }) + + const title = Widget.Label({ + class_name: "title", + max_width_chars: 20, + truncate: "end", + hpack: "start", + label: player.bind("track_title"), + }) + + const artist = Widget.Label({ + class_name: "artist", + max_width_chars: 20, + truncate: "end", + hpack: "start", + label: player.bind("track_artists").as(a => a.join(", ")), + }) + + const positionSlider = Widget.Slider({ + class_name: "position", + draw_value: false, + on_change: ({ value }) => player.position = value * player.length, + setup: self => { + const update = () => { + const { length, position } = player + self.visible = length > 0 + self.value = length > 0 ? position / length : 0 + } + self.hook(player, update) + self.hook(player, update, "position") + self.poll(1000, update) + }, + }) + + const positionLabel = Widget.Label({ + class_name: "position", + hpack: "start", + setup: self => { + const update = (_: unknown, time?: number) => { + self.label = lengthStr(time || player.position) + self.visible = player.length > 0 + } + self.hook(player, update, "position") + self.poll(1000, update) + }, + }) + + const lengthLabel = Widget.Label({ + class_name: "length", + hpack: "end", + visible: player.bind("length").as(l => l > 0), + label: player.bind("length").as(lengthStr), + }) + + const playericon = Widget.Icon({ + class_name: "icon", + hexpand: true, + hpack: "end", + vpack: "start", + tooltip_text: player.identity || "", + icon: Utils.merge([player.bind("entry"), media.monochromeIcon.bind()], (e, s) => { + const name = `${e}${s ? "-symbolic" : ""}` + return icon(name, icons.fallback.audio) + }), + }) + + const playPause = Widget.Button({ + class_name: "play-pause", + on_clicked: () => player.playPause(), + visible: player.bind("can_play"), + child: Widget.Icon({ + icon: player.bind("play_back_status").as(s => { + switch (s) { + case "Playing": return icons.mpris.playing + case "Paused": + case "Stopped": return icons.mpris.stopped + } + }), + }), + }) + + const prev = Widget.Button({ + on_clicked: () => player.previous(), + visible: player.bind("can_go_prev"), + child: Widget.Icon(icons.mpris.prev), + }) + + const next = Widget.Button({ + on_clicked: () => player.next(), + visible: player.bind("can_go_next"), + child: Widget.Icon(icons.mpris.next), + }) + + return Widget.Box( + { class_name: "player", vexpand: false }, + cover, + Widget.Box( + { vertical: true }, + Widget.Box([ + title, + playericon, + ]), + artist, + Widget.Box({ vexpand: true }), + positionSlider, + Widget.CenterBox({ + class_name: "footer horizontal", + start_widget: positionLabel, + center_widget: Widget.Box([ + prev, + playPause, + next, + ]), + end_widget: lengthLabel, + }), + ), + ) +} + +export const Media = () => Widget.Box({ + vertical: true, + class_name: "media vertical", + children: players.as(p => p.map(Player)), +}) -- cgit v1.2.3