mirror of
https://github.com/Theaninova/TheaninovOS.git
synced 2026-01-03 22:32:49 +00:00
322 lines
7.6 KiB
JavaScript
322 lines
7.6 KiB
JavaScript
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
|
import * as Utils from "resource:///com/github/Aylur/ags/utils.js";
|
|
import icons from "../icons.js";
|
|
import { blurImg } from "../utils.js";
|
|
|
|
/**
|
|
* @param {import('types/service/mpris').MprisPlayer} player
|
|
* @param {import('types/widgets/box').BoxProps=} props
|
|
*/
|
|
export const CoverArt = (player, props) =>
|
|
Widget.Box({
|
|
...props,
|
|
class_name: "cover",
|
|
binds: [
|
|
[
|
|
"css",
|
|
player,
|
|
"cover-path",
|
|
(path) => `background-image: url("${path}")`,
|
|
],
|
|
],
|
|
});
|
|
|
|
/**
|
|
* @param {import('types/service/mpris').MprisPlayer} player
|
|
* @param {import('types/widgets/box').BoxProps=} props
|
|
*/
|
|
export const BlurredCoverArt = (player, props) =>
|
|
Widget.Box({
|
|
...props,
|
|
class_name: "blurred-cover",
|
|
connections: [
|
|
[
|
|
player,
|
|
(box) =>
|
|
blurImg(player.cover_path).then((img) => {
|
|
img && box.setCss(`background-image: url("${img}")`);
|
|
}),
|
|
"notify::cover-path",
|
|
],
|
|
],
|
|
});
|
|
|
|
/**
|
|
* @param {import('types/service/mpris').MprisPlayer} player
|
|
* @param {import('types/widgets/label').Props=} props
|
|
*/
|
|
export const TitleLabel = (player, props) =>
|
|
Widget.Label({
|
|
...props,
|
|
class_name: "title",
|
|
binds: [["label", player, "track-title"]],
|
|
});
|
|
|
|
/**
|
|
* @param {import('types/service/mpris').MprisPlayer} player
|
|
* @param {import('types/widgets/label').Props=} props
|
|
*/
|
|
export const ArtistLabel = (player, props) =>
|
|
Widget.Label({
|
|
...props,
|
|
class_name: "artist",
|
|
binds: [["label", player, "track-artists", (a) => a.join(", ") || ""]],
|
|
});
|
|
|
|
/**
|
|
* @param {import('types/service/mpris').MprisPlayer} player
|
|
* @param {import('types/widgets/icon').Props & { symbolic?: boolean }=} props
|
|
*/
|
|
export const PlayerIcon = (player, { symbolic = true, ...props } = {}) =>
|
|
Widget.Icon({
|
|
...props,
|
|
class_name: "player-icon",
|
|
tooltip_text: player.identity || "",
|
|
connections: [
|
|
[
|
|
player,
|
|
(icon) => {
|
|
const name = `${player.entry}${symbolic ? "-symbolic" : ""}`;
|
|
Utils.lookUpIcon(name)
|
|
? (icon.icon = name)
|
|
: (icon.icon = icons.mpris.fallback);
|
|
},
|
|
],
|
|
],
|
|
});
|
|
|
|
/**
|
|
* @param {import('types/service/mpris').MprisPlayer} player
|
|
* @param {import('types/widgets/slider').SliderProps=} props
|
|
*/
|
|
export const PositionSlider = (player, props) =>
|
|
Widget.Slider({
|
|
...props,
|
|
class_name: "position-slider",
|
|
draw_value: false,
|
|
on_change: ({ value }) => {
|
|
player.position = player.length * value;
|
|
},
|
|
properties: [
|
|
[
|
|
"update",
|
|
(slider) => {
|
|
if (slider.dragging) return;
|
|
|
|
slider.visible = player.length > 0;
|
|
if (player.length > 0) slider.value = player.position / player.length;
|
|
},
|
|
],
|
|
],
|
|
connections: [
|
|
[player, (s) => s._update(s)],
|
|
[player, (s) => s._update(s), "position"],
|
|
[1000, (s) => s._update(s)],
|
|
],
|
|
});
|
|
|
|
/** @param {number} length */
|
|
function lengthStr(length) {
|
|
const min = Math.floor(length / 60);
|
|
const sec = Math.floor(length % 60);
|
|
const sec0 = sec < 10 ? "0" : "";
|
|
return `${min}:${sec0}${sec}`;
|
|
}
|
|
|
|
/** @param {import('types/service/mpris').MprisPlayer} player */
|
|
export const PositionLabel = (player) =>
|
|
Widget.Label({
|
|
properties: [
|
|
[
|
|
"update",
|
|
(label, time) => {
|
|
player.length > 0
|
|
? (label.label = lengthStr(time || player.position))
|
|
: (label.visible = !!player);
|
|
},
|
|
],
|
|
],
|
|
connections: [
|
|
[player, (l, time) => l._update(l, time), "position"],
|
|
[1000, (l) => l._update(l)],
|
|
],
|
|
});
|
|
|
|
/** @param {import('types/service/mpris').MprisPlayer} player */
|
|
export const LengthLabel = (player) =>
|
|
Widget.Label({
|
|
connections: [
|
|
[
|
|
player,
|
|
(label) => {
|
|
player.length > 0
|
|
? (label.label = lengthStr(player.length))
|
|
: (label.visible = !!player);
|
|
},
|
|
],
|
|
],
|
|
});
|
|
|
|
/** @param {import('types/service/mpris').MprisPlayer} player */
|
|
export const Slash = (player) =>
|
|
Widget.Label({
|
|
label: "/",
|
|
connections: [
|
|
[
|
|
player,
|
|
(label) => {
|
|
label.visible = player.length > 0;
|
|
},
|
|
],
|
|
],
|
|
});
|
|
|
|
/**
|
|
* @param {Object} o
|
|
* @param {import('types/service/mpris').MprisPlayer} o.player
|
|
* @param {import('types/widgets/stack').StackProps['items']} o.items
|
|
* @param {'shuffle' | 'loop' | 'playPause' | 'previous' | 'next'} o.onClick
|
|
* @param {string} o.prop
|
|
* @param {string} o.canProp
|
|
* @param {any} o.cantValue
|
|
*/
|
|
const PlayerButton = ({ player, items, onClick, prop, canProp, cantValue }) =>
|
|
Widget.Button({
|
|
child: Widget.Stack({
|
|
items,
|
|
binds: [["shown", player, prop, (p) => `${p}`]],
|
|
}),
|
|
on_clicked: player[onClick].bind(player),
|
|
binds: [["visible", player, canProp, (c) => c !== cantValue]],
|
|
});
|
|
|
|
/** @param {import('types/service/mpris').MprisPlayer} player */
|
|
export const ShuffleButton = (player) =>
|
|
PlayerButton({
|
|
player,
|
|
items: [
|
|
[
|
|
"true",
|
|
Widget.Label({
|
|
class_name: "shuffle enabled",
|
|
label: icons.mpris.shuffle.enabled,
|
|
}),
|
|
],
|
|
[
|
|
"false",
|
|
Widget.Label({
|
|
class_name: "shuffle disabled",
|
|
label: icons.mpris.shuffle.disabled,
|
|
}),
|
|
],
|
|
],
|
|
onClick: "shuffle",
|
|
prop: "shuffle-status",
|
|
canProp: "shuffle-status",
|
|
cantValue: null,
|
|
});
|
|
|
|
/** @param {import('types/service/mpris').MprisPlayer} player */
|
|
export const LoopButton = (player) =>
|
|
PlayerButton({
|
|
player,
|
|
items: [
|
|
[
|
|
"None",
|
|
Widget.Label({
|
|
class_name: "loop none",
|
|
label: icons.mpris.loop.none,
|
|
}),
|
|
],
|
|
[
|
|
"Track",
|
|
Widget.Label({
|
|
class_name: "loop track",
|
|
label: icons.mpris.loop.track,
|
|
}),
|
|
],
|
|
[
|
|
"Playlist",
|
|
Widget.Label({
|
|
class_name: "loop playlist",
|
|
label: icons.mpris.loop.playlist,
|
|
}),
|
|
],
|
|
],
|
|
onClick: "loop",
|
|
prop: "loop-status",
|
|
canProp: "loop-status",
|
|
cantValue: null,
|
|
});
|
|
|
|
/** @param {import('types/service/mpris').MprisPlayer} player */
|
|
export const PlayPauseButton = (player) =>
|
|
PlayerButton({
|
|
player,
|
|
items: [
|
|
[
|
|
"Playing",
|
|
Widget.Label({
|
|
class_name: "playing",
|
|
label: icons.mpris.playing,
|
|
}),
|
|
],
|
|
[
|
|
"Paused",
|
|
Widget.Label({
|
|
class_name: "paused",
|
|
label: icons.mpris.paused,
|
|
}),
|
|
],
|
|
[
|
|
"Stopped",
|
|
Widget.Label({
|
|
class_name: "stopped",
|
|
label: icons.mpris.stopped,
|
|
}),
|
|
],
|
|
],
|
|
onClick: "playPause",
|
|
prop: "play-back-status",
|
|
canProp: "can-play",
|
|
cantValue: false,
|
|
});
|
|
|
|
/** @param {import('types/service/mpris').MprisPlayer} player */
|
|
export const PreviousButton = (player) =>
|
|
PlayerButton({
|
|
player,
|
|
items: [
|
|
[
|
|
"true",
|
|
Widget.Label({
|
|
class_name: "previous",
|
|
label: icons.mpris.prev,
|
|
}),
|
|
],
|
|
],
|
|
onClick: "previous",
|
|
prop: "can-go-prev",
|
|
canProp: "can-go-prev",
|
|
cantValue: false,
|
|
});
|
|
|
|
/** @param {import('types/service/mpris').MprisPlayer} player */
|
|
export const NextButton = (player) =>
|
|
PlayerButton({
|
|
player,
|
|
items: [
|
|
[
|
|
"true",
|
|
Widget.Label({
|
|
class_name: "next",
|
|
label: icons.mpris.next,
|
|
}),
|
|
],
|
|
],
|
|
onClick: "next",
|
|
prop: "can-go-next",
|
|
canProp: "can-go-next",
|
|
cantValue: false,
|
|
});
|