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:
104
ags-v3/widget/panels/BrainPower.tsx
Normal file
104
ags-v3/widget/panels/BrainPower.tsx
Normal file
@@ -0,0 +1,104 @@
|
||||
import app from "ags/gtk3/app"
|
||||
import { Astal, Gtk, Gdk } from "ags/gtk3"
|
||||
import { createPoll } from "ags/time"
|
||||
import { getBrainState } from "../../lib/brain"
|
||||
|
||||
function BrainContent() {
|
||||
const state = createPoll("", 10000, () => JSON.stringify(getBrainState()))
|
||||
|
||||
const focus = state((s: string) => {
|
||||
try { return JSON.parse(s).focus } catch { return "..." }
|
||||
})
|
||||
|
||||
const todosLabel = state((s: string) => {
|
||||
try {
|
||||
const t = JSON.parse(s).todos
|
||||
return `${t.open} ouverts / ${t.done} faits`
|
||||
} catch { return "..." }
|
||||
})
|
||||
|
||||
const todosList = state((s: string) => {
|
||||
try {
|
||||
const t = JSON.parse(s).todos.top3
|
||||
return t.map((item: string) => ` ⬜ ${item}`).join("\n") || " rien"
|
||||
} catch { return "..." }
|
||||
})
|
||||
|
||||
const session = state((s: string) => {
|
||||
try {
|
||||
const sess = JSON.parse(s).session
|
||||
return sess || "aucune"
|
||||
} catch { return "..." }
|
||||
})
|
||||
|
||||
return (
|
||||
<box orientation={Gtk.Orientation.VERTICAL} class="brain-content">
|
||||
<box class="brain-section">
|
||||
<label class="brain-section-title" label=" FOCUS" xalign={0} />
|
||||
</box>
|
||||
<label class="brain-focus" label={focus} xalign={0} wrap />
|
||||
|
||||
<box class="brain-divider" />
|
||||
|
||||
<box class="brain-section">
|
||||
<label class="brain-section-title" label=" SESSION" xalign={0} />
|
||||
</box>
|
||||
<label class="brain-session" label={session} xalign={0} />
|
||||
|
||||
<box class="brain-divider" />
|
||||
|
||||
<box class="brain-section">
|
||||
<label class="brain-section-title" label=" TODOS" xalign={0} />
|
||||
<label class="brain-todos-count" label={todosLabel} xalign={1} hexpand />
|
||||
</box>
|
||||
<label class="brain-todos-list" label={todosList} xalign={0} />
|
||||
|
||||
<box class="brain-divider" />
|
||||
|
||||
<box class="brain-section">
|
||||
<label class="brain-section-title" label=" TERMINAL" xalign={0} />
|
||||
</box>
|
||||
<label class="brain-terminal-placeholder" label=" bientôt — agent brain-hud" xalign={0} />
|
||||
</box>
|
||||
)
|
||||
}
|
||||
|
||||
export default function BrainPower(gdkmonitor: Gdk.Monitor) {
|
||||
const { TOP, LEFT, BOTTOM } = Astal.WindowAnchor
|
||||
|
||||
return (
|
||||
<window
|
||||
class="BrainPower"
|
||||
name="brain-power"
|
||||
visible={false}
|
||||
gdkmonitor={gdkmonitor}
|
||||
exclusivity={Astal.Exclusivity.NONE}
|
||||
anchor={TOP | LEFT | BOTTOM}
|
||||
application={app}
|
||||
layer={Astal.Layer.OVERLAY}
|
||||
>
|
||||
<eventbox
|
||||
onHoverLost={() => {
|
||||
const win = app.get_window("brain-power")
|
||||
if (win) win.visible = false
|
||||
}}
|
||||
>
|
||||
<box orientation={Gtk.Orientation.VERTICAL} class="brain-panel">
|
||||
<box class="brain-header">
|
||||
<label class="brain-title" label=" BRAIN POWER" hexpand xalign={0} />
|
||||
<button
|
||||
class="brain-close"
|
||||
onClicked={() => {
|
||||
const win = app.get_window("brain-power")
|
||||
if (win) win.visible = false
|
||||
}}
|
||||
>
|
||||
<label label="✕" />
|
||||
</button>
|
||||
</box>
|
||||
<BrainContent />
|
||||
</box>
|
||||
</eventbox>
|
||||
</window>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user