This commit is contained in:
xsghetti 2024-04-11 00:21:35 -04:00
parent 1f8cb3c145
commit 610604e80f
253 changed files with 27055 additions and 44 deletions

View file

@ -0,0 +1,148 @@
import icons from "../../../lib/icons.js"
import options from "../../../options.js"
import { icon } from "../../../lib/utils.js"
const mpris = await Service.import("mpris")
const players = mpris.bind("players")
const { media } = options.quicksettings
function lengthStr(length) {
const min = Math.floor(length / 60)
const sec = Math.floor(length % 60)
const sec0 = sec < 10 ? "0" : ""
return `${min}:${sec0}${sec}`
}
const Player = (player) => {
const cover = Widget.Box({
class_name: "cover",
vpack: "start",
css: player.bind("cover_path").as(path => `
min-width: ${media.coverSize}px;
min-height: ${media.coverSize}px;
background-image: url('${path}');
`),
})
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 = (_, time) => {
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: player.bind("entry").as(e => {
const name = `${e}${media.monochromeIcon ? "-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)),
})