- 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
100 lines
2.9 KiB
JavaScript
100 lines
2.9 KiB
JavaScript
// ── violet-chaton v2 — Launcher widget ──────────────────────────────────────
|
|
// App launcher avec recherche fuzzy
|
|
|
|
const applications = Service.import("applications");
|
|
|
|
const AppItem = (app) => Widget.Button({
|
|
className: "app-item",
|
|
onClicked: () => {
|
|
app.launch();
|
|
App.closeWindow("launcher");
|
|
},
|
|
child: Widget.Box({
|
|
children: [
|
|
Widget.Icon({ icon: app.iconName || "application-x-executable", size: 24 }),
|
|
Widget.Box({
|
|
vertical: true,
|
|
children: [
|
|
Widget.Label({
|
|
label: app.name,
|
|
xalign: 0,
|
|
truncate: "end",
|
|
}),
|
|
Widget.Label({
|
|
label: app.description || "",
|
|
xalign: 0,
|
|
truncate: "end",
|
|
className: "description",
|
|
css: "color: #716686; font-size: 11px; font-weight: normal;",
|
|
}),
|
|
],
|
|
}),
|
|
],
|
|
}),
|
|
});
|
|
|
|
export const Launcher = (monitor) => {
|
|
let apps = applications.list;
|
|
|
|
const list = Widget.Box({
|
|
vertical: true,
|
|
spacing: 2,
|
|
});
|
|
|
|
const entry = Widget.Entry({
|
|
className: "search",
|
|
placeholderText: "Rechercher...",
|
|
onAccept: () => {
|
|
const first = apps[0];
|
|
if (first) {
|
|
first.launch();
|
|
App.closeWindow("launcher");
|
|
}
|
|
},
|
|
onChange: ({ text }) => {
|
|
apps = applications.query(text || "");
|
|
list.children = apps.slice(0, 12).map(AppItem);
|
|
|
|
if (apps.length === 0) {
|
|
list.children = [Widget.Label({
|
|
className: "no-results",
|
|
label: "Aucun resultat",
|
|
})];
|
|
}
|
|
},
|
|
});
|
|
|
|
return Widget.Window({
|
|
name: "launcher",
|
|
monitor,
|
|
anchor: ["top"],
|
|
layer: "overlay",
|
|
visible: false,
|
|
keymode: "exclusive",
|
|
setup: (self) => {
|
|
self.keybind("Escape", () => App.closeWindow("launcher"));
|
|
self.hook(App, (_, name, visible) => {
|
|
if (name === "launcher" && visible) {
|
|
entry.text = "";
|
|
apps = applications.list;
|
|
list.children = apps.slice(0, 12).map(AppItem);
|
|
entry.grab_focus();
|
|
}
|
|
});
|
|
},
|
|
child: Widget.Box({
|
|
className: "launcher",
|
|
vertical: true,
|
|
children: [
|
|
Widget.Scrollable({
|
|
hscroll: "never",
|
|
vscroll: "automatic",
|
|
css: "min-height: 400px;",
|
|
child: list,
|
|
}),
|
|
entry,
|
|
],
|
|
}),
|
|
});
|
|
};
|