Added AGS

This commit is contained in:
2026-04-19 21:28:21 -04:00
parent 24dd3e0271
commit 5fbf61834a
10 changed files with 278 additions and 34 deletions
+10
View File
@@ -0,0 +1,10 @@
import app from "ags/gtk3/app"
import style from "./style.css"
import Media from "./widget/Media"
app.start({
css: style,
main() {
app.get_monitors().map(Media)
},
})
+45
View File
@@ -0,0 +1,45 @@
const mpris = await Service.import('mpris');
const Media = () => Widget.Box({
class_name: 'media-container',
spacing: 10,
children: [
Widget.Button({
class_name: 'media-btn',
on_clicked: () => mpris.players[0]?.previous(),
child: Widget.Label('⏮'),
}),
Widget.Button({
class_name: 'media-btn',
on_clicked: () => mpris.players[0]?.playPause(),
child: Widget.Label().hook(mpris, label => {
const player = mpris.players[0];
label.label = player?.play_back_status === 'Playing' ? '⏸' : '▶';
}),
}),
Widget.Button({
class_name: 'media-btn',
on_clicked: () => mpris.players[0]?.next(),
child: Widget.Label('⏭'),
}),
Widget.Label({
class_name: 'media-text',
}).hook(mpris, label => {
const player = mpris.players[0];
label.label = player ? `${player.track_title} - ${player.track_artists.join(', ')}` : 'No Media Playing';
}),
],
});
App.config({
style: './style.css',
windows: [
Widget.Window({
name: 'media_widget',
anchor: ['bottom', 'left'],
margins: [0, 0, 20, 20],
layer: 'bottom',
child: Media(),
})
]
});
+21
View File
@@ -0,0 +1,21 @@
declare const SRC: string
declare module "inline:*" {
const content: string
export default content
}
declare module "*.scss" {
const content: string
export default content
}
declare module "*.blp" {
const content: string
export default content
}
declare module "*.css" {
const content: string
export default content
}
+10
View File
@@ -0,0 +1,10 @@
{
"dependencies": {
"ags": "*",
"gnim": "*"
},
"prettier": {
"semi": false,
"tabWidth": 2
}
}
+32
View File
@@ -0,0 +1,32 @@
* {
all: unset;
}
.MediaWindow {
background-color: transparent;
}
.media-container {
background-color: rgba(30, 30, 46, 0.85);
border-radius: 8px;
border: 2px solid rgba(137, 180, 250, 0.5);
padding: 8px 15px;
font-family: "JetBrainsMono Nerd Font", sans-serif;
}
.media-btn {
color: #cba6f7;
font-size: 16px;
padding: 0 5px;
transition: all 0.2s;
}
.media-btn:hover {
color: #89b4fa;
}
.media-text {
color: #cdd6f4;
font-size: 14px;
margin-left: 10px;
}
+14
View File
@@ -0,0 +1,14 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"strict": true,
"module": "ES2022",
"target": "ES2020",
"lib": ["ES2023"],
"moduleResolution": "Bundler",
// "checkJs": true,
// "allowJs": true,
"jsx": "react-jsx",
"jsxImportSource": "ags/gtk3"
}
}
+49
View File
@@ -0,0 +1,49 @@
import app from "ags/gtk3/app"
import { Astal, Gtk, Gdk } from "ags/gtk3"
import { execAsync } from "ags/process"
import { createPoll } from "ags/time"
export default function Media(gdkmonitor: Gdk.Monitor) {
const { TOP, LEFT } = Astal.WindowAnchor
// Poll playerctl for metadata and status
const mediaInfo = createPoll("No Media Playing", 1000, 'sh -c "playerctl metadata -f \'{{title}} - {{artist}}\' 2>/dev/null || echo \'No Media Playing\'"')
const statusIcon = createPoll("▶", 1000, 'sh -c "s=\\$(playerctl status 2>/dev/null); if [ \\"\\$s\\" = \\"Playing\\" ]; then echo \\"⏸\\"; else echo \\"▶\\"; fi"')
return (
<window
class="MediaWindow"
gdkmonitor={gdkmonitor}
exclusivity={Astal.Exclusivity.NORMAL}
layer={Astal.Layer.BOTTOM}
anchor={TOP | LEFT}
margin={20}
application={app}
>
<box class="media-container" spacing={10}>
<button
class="media-btn"
onClicked={() => execAsync("playerctl previous").catch(print)}
halign={Gtk.Align.CENTER}
>
<label label="⏮" />
</button>
<button
class="media-btn"
onClicked={() => execAsync("playerctl play-pause").catch(print)}
halign={Gtk.Align.CENTER}
>
<label label={statusIcon} />
</button>
<button
class="media-btn"
onClicked={() => execAsync("playerctl next").catch(print)}
halign={Gtk.Align.CENTER}
>
<label label="⏭" />
</button>
<label class="media-text" label={mediaInfo} />
</box>
</window>
)
}