Files
TheaninovOS/overlays/asztal/widget/launcher/AppLauncher.ts
2024-04-17 10:03:57 +02:00

131 lines
3.5 KiB
TypeScript

import { type Application } from "types/service/applications"
import { launchApp, icon } from "lib/utils"
import options from "options"
import icons from "lib/icons"
const apps = await Service.import("applications")
const { query } = apps
const { iconSize } = options.launcher.apps
const QuickAppButton = (app: Application) => Widget.Button({
hexpand: true,
tooltip_text: app.name,
on_clicked: () => {
App.closeWindow("launcher")
launchApp(app)
},
child: Widget.Icon({
size: iconSize.bind(),
icon: icon(app.icon_name, icons.fallback.executable),
}),
})
const AppItem = (app: Application) => {
const title = Widget.Label({
class_name: "title",
label: app.name,
hexpand: true,
xalign: 0,
vpack: "center",
truncate: "end",
})
const description = Widget.Label({
class_name: "description",
label: app.description || "",
hexpand: true,
wrap: true,
max_width_chars: 30,
xalign: 0,
justification: "left",
vpack: "center",
})
const appicon = Widget.Icon({
icon: icon(app.icon_name, icons.fallback.executable),
size: iconSize.bind(),
})
const textBox = Widget.Box({
vertical: true,
vpack: "center",
children: app.description ? [title, description] : [title],
})
return Widget.Button({
class_name: "app-item",
attribute: { app },
child: Widget.Box({
children: [appicon, textBox],
}),
on_clicked: () => {
App.closeWindow("launcher")
launchApp(app)
},
})
}
export function Favorites() {
const favs = options.launcher.apps.favorites.bind()
return Widget.Revealer({
visible: favs.as(f => f.length > 0),
child: Widget.Box({
vertical: true,
children: favs.as(favs => favs.flatMap(fs => [
Widget.Separator(),
Widget.Box({
class_name: "quicklaunch horizontal",
children: fs
.map(f => query(f)?.[0])
.filter(f => f)
.map(QuickAppButton),
}),
])),
}),
})
}
export function Launcher() {
const applist = Variable(query(""))
const max = options.launcher.apps.max
let first = applist.value[0]
function SeparatedAppItem(app: Application) {
return Widget.Revealer(
{ attribute: { app } },
Widget.Box(
{ vertical: true },
Widget.Separator(),
AppItem(app),
),
)
}
const list = Widget.Box({
vertical: true,
children: applist.bind().as(list => list.map(SeparatedAppItem)),
setup: self => self
.hook(apps, () => applist.value = query(""), "notify::frequents"),
})
return Object.assign(list, {
filter(text: string | null) {
first = query(text || "")[0]
list.children.reduce((i, item) => {
if (!text || i >= max.value) {
item.reveal_child = false
return i
}
if (item.attribute.app.match(text)) {
item.reveal_child = true
return ++i
}
item.reveal_child = false
return i
}, 0)
},
launchFirst() {
launchApp(first)
},
})
}