- Scaling 16px base pour ultrawide 3440x1440 - Bar: CPU/RAM/GPU visible, media single player (skip playerctld), network tooltip LAN/WAN IPv4 - Volume: class module pour sizing cohérent - Battery: désactivé (PC fixe) - Clock: tooltip calendrier + uptime - BrainPower: panel enrichi (focus, session, intentions, todos, repos git, derniers commits) - App: BrainPower sur moniteur principal uniquement - Heartbeat: Layer.TOP pour compatibilité COSMIC
158 lines
4.7 KiB
TypeScript
158 lines
4.7 KiB
TypeScript
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 version = state((s: string) => {
|
|
try { return `kernel v${JSON.parse(s).kernelVersion}` } catch { return "" }
|
|
})
|
|
|
|
const focus = state((s: string) => {
|
|
try { return JSON.parse(s).focus } catch { return "..." }
|
|
})
|
|
|
|
const session = state((s: string) => {
|
|
try {
|
|
const sess = JSON.parse(s).session
|
|
return sess || "aucune session active"
|
|
} catch { return "..." }
|
|
})
|
|
|
|
const intentionsTitle = state((s: string) => {
|
|
try {
|
|
const i = JSON.parse(s).intentions
|
|
return ` INTENTIONS (${i.active} active${i.active > 1 ? "s" : ""})`
|
|
} catch { return " INTENTIONS" }
|
|
})
|
|
|
|
const intentionsList = state((s: string) => {
|
|
try {
|
|
const names = JSON.parse(s).intentions.names
|
|
return names.map((n: string) => ` • ${n}`).join("\n") || " aucune"
|
|
} catch { return "..." }
|
|
})
|
|
|
|
const todosTitle = 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 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 "..." }
|
|
})
|
|
|
|
return (
|
|
<box orientation={Gtk.Orientation.VERTICAL} class="brain-content">
|
|
{/* FOCUS */}
|
|
<box class="brain-section">
|
|
<label class="brain-section-title" label=" FOCUS" xalign={0} />
|
|
<label class="brain-version" label={version} xalign={1} hexpand />
|
|
</box>
|
|
<label class="brain-focus" label={focus} xalign={0} wrap />
|
|
|
|
<box class="brain-divider" />
|
|
|
|
{/* SESSION */}
|
|
<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" />
|
|
|
|
{/* INTENTIONS */}
|
|
<box class="brain-section">
|
|
<label class="brain-section-title" label={intentionsTitle} xalign={0} />
|
|
</box>
|
|
<label class="brain-intentions-list" label={intentionsList} xalign={0} />
|
|
|
|
<box class="brain-divider" />
|
|
|
|
{/* TODOS */}
|
|
<box class="brain-section">
|
|
<label class="brain-section-title" label=" TODOS" xalign={0} />
|
|
<label class="brain-todos-count" label={todosTitle} xalign={1} hexpand />
|
|
</box>
|
|
<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>
|
|
)
|
|
}
|
|
|
|
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>
|
|
)
|
|
}
|