feat: Ghost Shell v2 — AGS v3 statusbar + violet-chaton v2 palette
- AGS v3.1.0 (Astal/GTK3) Ghost Shell avec ghost mode (heartbeat + hover reveal) - Modules : clock, battery, volume (interactif), network, MPRIS, CPU/RAM, systray - Brain Power panel (Super + B) — lecture live focus/todos/session - tetardtek_ prompt avec curseur clignotant - Palette violet-chaton v2 documentée (Mitsuri Kanroji gradient magenta → green) - Autostart COSMIC via .desktop - Archive AGS v1 conservée pour référence
This commit is contained in:
95
ags-v1/widgets/OSD.js
Normal file
95
ags-v1/widgets/OSD.js
Normal file
@@ -0,0 +1,95 @@
|
||||
// ── violet-chaton v2 — OSD widget ───────────────────────────────────────────
|
||||
// Overlay volume / brightness avec gradient Mitsuri
|
||||
|
||||
const audio = Service.import("audio");
|
||||
|
||||
// ── OSD reveal timer ────────────────────────────────────────────────────────
|
||||
|
||||
let osdTimeout = null;
|
||||
|
||||
const showOSD = (window) => {
|
||||
window.visible = true;
|
||||
if (osdTimeout) clearTimeout(osdTimeout);
|
||||
osdTimeout = setTimeout(() => {
|
||||
window.visible = false;
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
// ── Volume OSD ──────────────────────────────────────────────────────────────
|
||||
|
||||
const VolumeOSD = () => {
|
||||
const icon = Widget.Label({ className: "icon" });
|
||||
const progress = Widget.ProgressBar();
|
||||
const label = Widget.Label({ className: "label" });
|
||||
|
||||
const box = Widget.Box({
|
||||
className: "osd",
|
||||
children: [icon, progress, label],
|
||||
connections: [[audio, (self) => {
|
||||
const vol = audio.speaker?.volume || 0;
|
||||
const muted = audio.speaker?.isMuted;
|
||||
icon.label = muted ? "" : vol > 0.66 ? "" : vol > 0.33 ? "" : "";
|
||||
progress.value = vol;
|
||||
label.label = `${Math.round(vol * 100)}%`;
|
||||
}, "speaker-changed"]],
|
||||
});
|
||||
|
||||
return box;
|
||||
};
|
||||
|
||||
// ── Brightness OSD ──────────────────────────────────────────────────────────
|
||||
|
||||
const BrightnessOSD = () => {
|
||||
const icon = Widget.Label({ className: "icon", label: "" });
|
||||
const progress = Widget.ProgressBar();
|
||||
const label = Widget.Label({ className: "label" });
|
||||
|
||||
const getBrightness = () => {
|
||||
try {
|
||||
const max = Number(Utils.exec("brightnessctl max"));
|
||||
const cur = Number(Utils.exec("brightnessctl get"));
|
||||
return max > 0 ? cur / max : 0;
|
||||
} catch {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
const box = Widget.Box({
|
||||
className: "osd",
|
||||
children: [icon, progress, label],
|
||||
connections: [[500, (self) => {
|
||||
const val = getBrightness();
|
||||
progress.value = val;
|
||||
label.label = `${Math.round(val * 100)}%`;
|
||||
}]],
|
||||
});
|
||||
|
||||
return box;
|
||||
};
|
||||
|
||||
// ── OSD windows ─────────────────────────────────────────────────────────────
|
||||
|
||||
export const OSD = (monitor) => {
|
||||
const volumeWin = Widget.Window({
|
||||
name: `osd-volume-${monitor}`,
|
||||
monitor,
|
||||
anchor: ["bottom"],
|
||||
layer: "overlay",
|
||||
visible: false,
|
||||
child: VolumeOSD(),
|
||||
});
|
||||
|
||||
const brightnessWin = Widget.Window({
|
||||
name: `osd-brightness-${monitor}`,
|
||||
monitor,
|
||||
anchor: ["bottom"],
|
||||
layer: "overlay",
|
||||
visible: false,
|
||||
child: BrightnessOSD(),
|
||||
});
|
||||
|
||||
// Auto-show on volume change
|
||||
Utils.merge([audio.speaker?.bind("volume")], () => showOSD(volumeWin));
|
||||
|
||||
return [volumeWin, brightnessWin];
|
||||
};
|
||||
Reference in New Issue
Block a user