summaryrefslogtreecommitdiff
path: root/core/gjs/src/application.ts
diff options
context:
space:
mode:
Diffstat (limited to 'core/gjs/src/application.ts')
-rw-r--r--core/gjs/src/application.ts105
1 files changed, 105 insertions, 0 deletions
diff --git a/core/gjs/src/application.ts b/core/gjs/src/application.ts
new file mode 100644
index 0000000..0ba247e
--- /dev/null
+++ b/core/gjs/src/application.ts
@@ -0,0 +1,105 @@
+import { Astal, GObject, Gio, GLib } from "./imports.js"
+
+type RequestHandler = {
+ (request: string, res: (response: any) => void): void
+}
+
+type Config = Partial<{
+ icons: string
+ instanceName: string
+ gtkTheme: string
+ iconTheme: string
+ cursorTheme: string
+ css: string
+ requestHandler: RequestHandler
+ main(...args: string[]): void
+ client(message: (msg: string) => string, ...args: string[]): void
+ hold: boolean
+}>
+
+// @ts-expect-error missing types
+// https://github.com/gjsify/ts-for-gir/issues/164
+import { setConsoleLogDomain } from "console"
+import { exit, programArgs } from "system"
+
+class AstalJS extends Astal.Application {
+ static { GObject.registerClass(this) }
+
+ eval(body: string): Promise<any> {
+ return new Promise((res, rej) => {
+ try {
+ const fn = Function(`return (async function() {
+ ${body.includes(";") ? body : `return ${body};`}
+ })`)
+ fn()()
+ .then(res)
+ .catch(rej)
+ }
+ catch (error) {
+ rej(error)
+ }
+ })
+ }
+
+ requestHandler?: RequestHandler
+
+ vfunc_request(msg: string, conn: Gio.SocketConnection): void {
+ if (typeof this.requestHandler === "function") {
+ this.requestHandler(msg, (response) => {
+ Astal.write_sock(conn, String(response), (_, res) =>
+ Astal.write_sock_finish(res),
+ )
+ })
+ }
+ else {
+ super.vfunc_request(msg, conn)
+ }
+ }
+
+ apply_css(style: string, reset = false) {
+ super.apply_css(style, reset)
+ }
+
+ quit(code?: number): void {
+ super.quit()
+ exit(code ?? 0)
+ }
+
+ start({ requestHandler, css, hold, main, client, icons, ...cfg }: Config = {}) {
+ client ??= () => {
+ print(`Astal instance "${this.instanceName}" already running`)
+ exit(1)
+ }
+
+ Object.assign(this, cfg)
+ setConsoleLogDomain(this.instanceName)
+
+ this.requestHandler = requestHandler
+ this.connect("activate", () => {
+ const path: string[] = import.meta.url.split("/").slice(3)
+ const file = path.at(-1)!.replace(".js", ".css")
+ const css = `/${path.slice(0, -1).join("/")}/${file}`
+ if (file.endsWith(".css") && GLib.file_test(css, GLib.FileTest.EXISTS))
+ this.apply_css(css, false)
+
+ main?.(...programArgs)
+ })
+
+ if (!this.acquire_socket())
+ return client(msg => Astal.Application.send_message(this.instanceName, msg)!, ...programArgs)
+
+ if (css)
+ this.apply_css(css, false)
+
+ if (icons)
+ this.add_icons(icons)
+
+ hold ??= true
+ if (hold)
+ this.hold()
+
+ this.runAsync([])
+ }
+}
+
+export default new AstalJS()