import { timeout } from "ags/time"; import { Astal, Gtk } from "ags/gtk4"; import { Clipboard } from "../../scripts/clipboard"; import { getMediaUrl, player, setPlayer } from "../bar/Media"; import { Accessor, createBinding, createConnection, For, With } from "ags"; import { getPlayerIconFromBusName, pathToURI, variableToBoolean } from "../../scripts/utils"; import AstalMpris from "gi://AstalMpris"; import AstalIO from "gi://AstalIO"; import Pango from "gi://Pango?version=1.0"; export const BigMedia = () => { let dragTimer: (AstalIO.Time|undefined); return pl.available)}> {(player: AstalMpris.Player) => player.available && `background-image: url("${pathToURI(art)}");`)} hexpand={false} vexpand={false} widthRequest={132} heightRequest={128} valign={Gtk.Align.START} halign={Gtk.Align.CENTER}> title ?? "No Title") } label={ createBinding(player, "title").as(title => title ?? "No Title") } ellipsize={Pango.EllipsizeMode.END} maxWidthChars={25} /> artist ?? "No Artist") } label={ createBinding(player, "artist").as(artist => artist ?? "No Artist") } ellipsize={Pango.EllipsizeMode.END} maxWidthChars={28} /> {(hasAlbumArt) => !hasAlbumArt && } { if(type === undefined || type === null) return; if(!dragTimer) { dragTimer = timeout(200, () => player.position = Math.floor(value)); return; } dragTimer.cancel(); dragTimer = timeout(200, () => player.position = Math.floor(value)); }} /> { const sec = Math.floor(pos % 60); return pos > 0 && player.length > 0 ? `${Math.floor(pos / 60)}:${sec < 10 ? "0" : ""}${sec}` : "0:00"; })} $type="start" /> { const url = getMediaUrl(player).get(); url && Clipboard.getDefault().copyAsync(url); }} /> status !== AstalMpris.Shuffle.UNSUPPORTED)} iconName={ createBinding(player, "shuffleStatus").as(status => status === AstalMpris.Shuffle.ON ? "media-playlist-shuffle-symbolic" : "media-playlist-consecutive-symbolic")} tooltipText={ createBinding(player, "shuffleStatus").as(status => status === AstalMpris.Shuffle.ON ? "Shuffle" : "No shuffle")} onClicked={() => player.shuffle()} /> player.canGoPrevious && player.previous()} /> status === AstalMpris.PlaybackStatus.PLAYING ? "Pause" : "Play")} iconName={createBinding(player, "playbackStatus").as(status => status === AstalMpris.PlaybackStatus.PLAYING ? "media-playback-pause-symbolic" : "media-playback-start-symbolic")} onClicked={() => player.play_pause()} /> player.canGoNext && player.next()} /> { if(status === AstalMpris.Loop.TRACK) return "media-playlist-repeat-song-symbolic"; if(status === AstalMpris.Loop.PLAYLIST) return "media-playlist-repeat-symbolic"; return "loop-arrow-symbolic"; })} visible={createBinding(player, "loopStatus").as(status => status !== AstalMpris.Loop.UNSUPPORTED)} tooltipText={createBinding(player, "loopStatus").as(status => { if(status === AstalMpris.Loop.TRACK) return "Loop song"; if(status === AstalMpris.Loop.PLAYLIST) return "Loop playlist"; return "No loop"; })} onClicked={() => player.loop()} /> { /* bananananananana */ const sec = Math.floor(len % 60); return (len > 0 && Number.isFinite(len)) ? `${Math.floor(len / 60)}:${sec < 10 ? "0" : ""}${sec}` : "0:00"; })} $type="end" /> } as Gtk.Box; } export function PlayerSelectButton({ player, reveal, halign = Gtk.Align.CENTER, valign = Gtk.Align.CENTER }: { player: AstalMpris.Player, reveal?: Accessor|boolean, halign?: Gtk.Align; valign?: Gtk.Align; }) { const availablePlayers = createBinding(AstalMpris.get_default(), "players").as(players => players.filter(p => p.available)); return apls.length > 1)}> {(show: boolean) => show && {(pl: AstalMpris.Player) => setPlayer(pl)}> } as Gtk.Popover } $={(self) => { const controllerMotion = Gtk.EventControllerMotion.new(); self.add_controller(controllerMotion); self.set_child( { self.add_css_class("reveal"); return true; }], [controllerMotion, "leave", () => { self.remove_css_class("reveal"); return false; }] ) }> "go-down-symbolic"], [self.popover, "closed", () => "go-next-symbolic"] ) } class={"arrow"} iconSize={Gtk.IconSize.NORMAL} /> as Gtk.Box ); }} /> } ; }