feat(ags-v3): brain HUD terminal — kitty toggle + single instance + COSMIC window rule
- BrainPower panel: dashboard only (VTE embed pas compatible AGS JSX) - toggle-brain.sh: ouvre/ferme panel AGS + terminal Kitty (single instance via pgrep) - Kitty class brain-hud-terminal pour COSMIC window rule (floating) - app.ts: cleanup focusBrainTerm removed - style.scss: brain-terminal class + brain-commits-list
This commit is contained in:
@@ -124,4 +124,11 @@ window.BrainPower {
|
|||||||
font-family: "Maple Mono NF", monospace;
|
font-family: "Maple Mono NF", monospace;
|
||||||
padding: 4px 0 4px 16px;
|
padding: 4px 0 4px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.brain-terminal {
|
||||||
|
background: #1a0e27;
|
||||||
|
border-radius: 0 0 $radius 0;
|
||||||
|
padding: 4px;
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,32 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Toggle Brain Power panel via AGS IPC
|
# Toggle Brain Power — dashboard AGS + terminal Kitty (single instance)
|
||||||
ags request "toggle-brain" 2>/dev/null
|
BRAIN_ROOT="${BRAIN_ROOT:-$HOME/Dev/Brain}"
|
||||||
|
KITTY_CLASS="brain-hud-terminal"
|
||||||
|
|
||||||
|
# Check if brain kitty is already running (by window class)
|
||||||
|
kitty_pid=$(pgrep -f "class $KITTY_CLASS" | head -1)
|
||||||
|
|
||||||
|
if [ -n "$kitty_pid" ]; then
|
||||||
|
# Close everything
|
||||||
|
ags request "toggle-brain" 2>/dev/null
|
||||||
|
kill "$kitty_pid" 2>/dev/null
|
||||||
|
else
|
||||||
|
# Open everything
|
||||||
|
ags request "toggle-brain" 2>/dev/null
|
||||||
|
kitty \
|
||||||
|
--class "$KITTY_CLASS" \
|
||||||
|
--title "🧠 Brain HUD" \
|
||||||
|
--override remember_window_size=no \
|
||||||
|
--override initial_window_width=60c \
|
||||||
|
--override initial_window_height=30c \
|
||||||
|
--override background_opacity=0.94 \
|
||||||
|
--override background=#1a0e27 \
|
||||||
|
--override foreground=#f0eaf8 \
|
||||||
|
--override cursor=#ff4da6 \
|
||||||
|
--override font_size=13 \
|
||||||
|
--override confirm_os_window_close=0 \
|
||||||
|
--directory "$BRAIN_ROOT" \
|
||||||
|
-e zsh -c "echo '🧠 Brain HUD — navigate mode'; echo ''; exec zsh" \
|
||||||
|
&
|
||||||
|
disown
|
||||||
|
fi
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import app from "ags/gtk3/app"
|
|||||||
import { Astal, Gtk, Gdk } from "ags/gtk3"
|
import { Astal, Gtk, Gdk } from "ags/gtk3"
|
||||||
import { createPoll } from "ags/time"
|
import { createPoll } from "ags/time"
|
||||||
import { getBrainState } from "../../lib/brain"
|
import { getBrainState } from "../../lib/brain"
|
||||||
|
import GLib from "gi://GLib"
|
||||||
|
|
||||||
function BrainContent() {
|
function BrainContent() {
|
||||||
const state = createPoll("", 10000, () => JSON.stringify(getBrainState()))
|
const state = createPoll("", 10000, () => JSON.stringify(getBrainState()))
|
||||||
@@ -9,109 +10,55 @@ function BrainContent() {
|
|||||||
const version = state((s: string) => {
|
const version = state((s: string) => {
|
||||||
try { return `kernel v${JSON.parse(s).kernelVersion}` } catch { return "" }
|
try { return `kernel v${JSON.parse(s).kernelVersion}` } catch { return "" }
|
||||||
})
|
})
|
||||||
|
|
||||||
const focus = state((s: string) => {
|
const focus = state((s: string) => {
|
||||||
try { return JSON.parse(s).focus } catch { return "..." }
|
try { return JSON.parse(s).focus } catch { return "..." }
|
||||||
})
|
})
|
||||||
|
|
||||||
const session = state((s: string) => {
|
const session = state((s: string) => {
|
||||||
try {
|
try { return JSON.parse(s).session || "aucune session active" } catch { return "..." }
|
||||||
const sess = JSON.parse(s).session
|
|
||||||
return sess || "aucune session active"
|
|
||||||
} catch { return "..." }
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const intentionsTitle = state((s: string) => {
|
const intentionsTitle = state((s: string) => {
|
||||||
try {
|
try {
|
||||||
const i = JSON.parse(s).intentions
|
const i = JSON.parse(s).intentions
|
||||||
return ` INTENTIONS (${i.active} active${i.active > 1 ? "s" : ""})`
|
return ` INTENTIONS (${i.active} active${i.active > 1 ? "s" : ""})`
|
||||||
} catch { return " INTENTIONS" }
|
} catch { return " INTENTIONS" }
|
||||||
})
|
})
|
||||||
|
|
||||||
const intentionsList = state((s: string) => {
|
const intentionsList = state((s: string) => {
|
||||||
try {
|
try {
|
||||||
const names = JSON.parse(s).intentions.names
|
return JSON.parse(s).intentions.names.map((n: string) => ` • ${n}`).join("\n") || " aucune"
|
||||||
return names.map((n: string) => ` • ${n}`).join("\n") || " aucune"
|
|
||||||
} catch { return "..." }
|
} catch { return "..." }
|
||||||
})
|
})
|
||||||
|
|
||||||
const todosTitle = state((s: string) => {
|
const todosTitle = state((s: string) => {
|
||||||
try {
|
try { const t = JSON.parse(s).todos; return `${t.open} ouverts / ${t.done} faits` } catch { return "" }
|
||||||
const t = JSON.parse(s).todos
|
|
||||||
return `${t.open} ouverts / ${t.done} faits`
|
|
||||||
} catch { return "" }
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const todosList = state((s: string) => {
|
const todosList = state((s: string) => {
|
||||||
try {
|
try {
|
||||||
const t = JSON.parse(s).todos.top3
|
return JSON.parse(s).todos.top3.map((item: string) => ` ⬜ ${item}`).join("\n") || " rien"
|
||||||
return t.map((item: string) => ` ⬜ ${item}`).join("\n") || " rien"
|
|
||||||
} catch { return "..." }
|
|
||||||
})
|
|
||||||
|
|
||||||
const reposStatus = state((s: string) => {
|
|
||||||
try {
|
|
||||||
const repos = JSON.parse(s).repos
|
|
||||||
return repos.map((r: any) => ` ${r.name.padEnd(14)} ${r.status}`).join("\n")
|
|
||||||
} catch { return "..." }
|
|
||||||
})
|
|
||||||
|
|
||||||
const commitsList = state((s: string) => {
|
|
||||||
try {
|
|
||||||
const commits = JSON.parse(s).commits
|
|
||||||
return commits.map((c: string) => ` ${c}`).join("\n") || " aucun"
|
|
||||||
} catch { return "..." }
|
} catch { return "..." }
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<box orientation={Gtk.Orientation.VERTICAL} class="brain-content">
|
<box orientation={Gtk.Orientation.VERTICAL} class="brain-content">
|
||||||
{/* FOCUS */}
|
|
||||||
<box class="brain-section">
|
<box class="brain-section">
|
||||||
<label class="brain-section-title" label=" FOCUS" xalign={0} />
|
<label class="brain-section-title" label=" FOCUS" xalign={0} />
|
||||||
<label class="brain-version" label={version} xalign={1} hexpand />
|
<label class="brain-version" label={version} xalign={1} hexpand />
|
||||||
</box>
|
</box>
|
||||||
<label class="brain-focus" label={focus} xalign={0} wrap />
|
<label class="brain-focus" label={focus} xalign={0} wrap />
|
||||||
|
|
||||||
<box class="brain-divider" />
|
<box class="brain-divider" />
|
||||||
|
|
||||||
{/* SESSION */}
|
|
||||||
<box class="brain-section">
|
<box class="brain-section">
|
||||||
<label class="brain-section-title" label=" SESSION" xalign={0} />
|
<label class="brain-section-title" label=" SESSION" xalign={0} />
|
||||||
</box>
|
</box>
|
||||||
<label class="brain-session" label={session} xalign={0} />
|
<label class="brain-session" label={session} xalign={0} />
|
||||||
|
|
||||||
<box class="brain-divider" />
|
<box class="brain-divider" />
|
||||||
|
|
||||||
{/* INTENTIONS */}
|
|
||||||
<box class="brain-section">
|
<box class="brain-section">
|
||||||
<label class="brain-section-title" label={intentionsTitle} xalign={0} />
|
<label class="brain-section-title" label={intentionsTitle} xalign={0} />
|
||||||
</box>
|
</box>
|
||||||
<label class="brain-intentions-list" label={intentionsList} xalign={0} />
|
<label class="brain-intentions-list" label={intentionsList} xalign={0} />
|
||||||
|
|
||||||
<box class="brain-divider" />
|
<box class="brain-divider" />
|
||||||
|
|
||||||
{/* TODOS */}
|
|
||||||
<box class="brain-section">
|
<box class="brain-section">
|
||||||
<label class="brain-section-title" label=" TODOS" xalign={0} />
|
<label class="brain-section-title" label=" TODOS" xalign={0} />
|
||||||
<label class="brain-todos-count" label={todosTitle} xalign={1} hexpand />
|
<label class="brain-todos-count" label={todosTitle} xalign={1} hexpand />
|
||||||
</box>
|
</box>
|
||||||
<label class="brain-todos-list" label={todosList} xalign={0} />
|
<label class="brain-todos-list" label={todosList} xalign={0} />
|
||||||
|
|
||||||
<box class="brain-divider" />
|
|
||||||
|
|
||||||
{/* REPOS */}
|
|
||||||
<box class="brain-section">
|
|
||||||
<label class="brain-section-title" label=" REPOS" xalign={0} />
|
|
||||||
</box>
|
|
||||||
<label class="brain-repos-status" label={reposStatus} xalign={0} />
|
|
||||||
|
|
||||||
<box class="brain-divider" />
|
|
||||||
|
|
||||||
{/* COMMITS */}
|
|
||||||
<box class="brain-section">
|
|
||||||
<label class="brain-section-title" label=" DERNIERS COMMITS" xalign={0} />
|
|
||||||
</box>
|
|
||||||
<label class="brain-commits-list" label={commitsList} xalign={0} />
|
|
||||||
</box>
|
</box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -130,28 +77,21 @@ export default function BrainPower(gdkmonitor: Gdk.Monitor) {
|
|||||||
application={app}
|
application={app}
|
||||||
layer={Astal.Layer.OVERLAY}
|
layer={Astal.Layer.OVERLAY}
|
||||||
>
|
>
|
||||||
<eventbox
|
<box orientation={Gtk.Orientation.VERTICAL} class="brain-panel">
|
||||||
onHoverLost={() => {
|
<box class="brain-header">
|
||||||
const win = app.get_window("brain-power")
|
<label class="brain-title" label=" BRAIN POWER" hexpand xalign={0} />
|
||||||
if (win) win.visible = false
|
<button
|
||||||
}}
|
class="brain-close"
|
||||||
>
|
onClicked={() => {
|
||||||
<box orientation={Gtk.Orientation.VERTICAL} class="brain-panel">
|
const win = app.get_window("brain-power")
|
||||||
<box class="brain-header">
|
if (win) win.visible = false
|
||||||
<label class="brain-title" label=" BRAIN POWER" hexpand xalign={0} />
|
}}
|
||||||
<button
|
>
|
||||||
class="brain-close"
|
<label label="✕" />
|
||||||
onClicked={() => {
|
</button>
|
||||||
const win = app.get_window("brain-power")
|
|
||||||
if (win) win.visible = false
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<label label="✕" />
|
|
||||||
</button>
|
|
||||||
</box>
|
|
||||||
<BrainContent />
|
|
||||||
</box>
|
</box>
|
||||||
</eventbox>
|
<BrainContent />
|
||||||
|
</box>
|
||||||
</window>
|
</window>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user