From ede8890a08b3fbbb1f6df3b8c277ab6424d1befd Mon Sep 17 00:00:00 2001 From: Aylur Date: Tue, 15 Oct 2024 01:22:24 +0000 Subject: docs: better explain ags --- docs/guide/typescript/faq.md | 266 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 docs/guide/typescript/faq.md (limited to 'docs/guide/typescript/faq.md') diff --git a/docs/guide/typescript/faq.md b/docs/guide/typescript/faq.md new file mode 100644 index 0000000..76d8e72 --- /dev/null +++ b/docs/guide/typescript/faq.md @@ -0,0 +1,266 @@ +# Frequently asked question, common issues, tips and tricks + +## Monitor id does not match compositor + +The monitor id property that windows expect is mapped by Gdk, which is not always +the same as the compositor. Instead use the `gdkmonitor` property which expects +a `Gdk.Monitor` object. + +```tsx +import { App } from "astal" + +function Bar(gdkmonitor) { + return +} + +function main() { + for (const monitor of App.get_monitors()) { + if (monitor.model == "your-desired-model") { + Bar(monitor) + } + } +} + +App.start({ main }) +``` + +## Environment variables + +JavaScript is **not** an bash. + +```ts +const HOME = exec("echo $HOME") // does not work +``` + +`exec` and `execAsync` runs the passed program as is, its **not** run in a +shell environment, so the above example just passes `$HOME` as a string literal +to the `echo` program. + +:::danger Please don't do this +You could pass it to bash, but that is a horrible approach. + +```ts +const HOME = exec("bash -c 'echo $HOME'") +``` + +::: + +You can read environment variables with [GLib.getenv](https://gjs-docs.gnome.org/glib20~2.0/glib.getenv). + +```ts +import GLib from "gi://GLib" + +const HOME = GLib.getenv("HOME") +``` + +## Custom SVG symbolic icons + +Put the svgs in a directory, named `-symbolic.svg` +and use `App.add_icons` or `icons` parameter in `App.start` + +:::code-group + +```ts [app.ts] +App.start({ + icons: `${SRC}/icons`, + main() { + Widget.Icon({ + icon: "custom-symbolic", // custom-symbolic.svg + css: "color: green;", // can be colored, like other named icons + }) + }, +}) +``` + +::: + +:::info +If there is a name clash with an icon from your current icon pack +the icon pack will take precedence +::: + +## Logging + +The `console` API in gjs uses glib logging functions. +If you just want to print some text as is to stdout +use the globally available `print` function or `printerr` for stderr. + +```ts +print("print this line to stdout") +printerr("print this line to stderr") +``` + +## Populate the global scope with frequently accessed variables + +It might be annoying to always import Gtk only for `Gtk.Align` enums. + +:::code-group + +```ts [globals.ts] +import Gtk from "gi://Gtk" + +declare global { + const START: number + const CENTER: number + const END: number + const FILL: number +} + +Object.assign(globalThis, { + START: Gtk.Align.START, + CENTER: Gtk.Align.CENTER, + END: Gtk.Align.END, + FILL: Gtk.Align.FILL, +}) +``` + +::: + +:::code-group + +```tsx [Bar.tsx] +export default function Bar() { + return + + +} +``` + +::: + +:::code-group + +```ts [app.ts] +import "./globals" +import Bar from "./Bar" + +App.start({ + main: Bar +}) +``` + +::: + +:::info +It is considered bad practice to populate the global scope, but its your code, not a public library. +::: + +## Auto create Window for each Monitor + +To have Window widgets appear on a monitor when its plugged in, listen to `App.monitor_added`. + +:::code-group + +```tsx [Bar.tsx] +export default function Bar(gdkmonitor: Gdk.Monitor) { + return +} +``` + +::: + +:::code-group + +```ts [app.ts] +import { Gdk, Gtk } from "astal" +import Bar from "./Bar" + +function main() { + const bars = new Map() + + // initialize + for (const gdkmonitor of App.get_monitors()) { + bars.set(gdkmonitor, Bar(gdkmonitor)) + } + + App.connect("monitor-added", (_, gdkmonitor) => { + bars.set(gdkmonitor, Bar(gdkmonitor)) + }) + + App.connect("monitor-removed", (_, gdkmonitor) => { + bars.get(gdkmonitor)?.destroy() + bars.delete(gdkmonitor) + }) +} + +App.start({ main }) +``` + +::: + +## Error: Can't convert non-null pointer to JS value + +These happen when accessing list type properties. Gjs fails to correctly bind +`List` and other array like types of Vala as a property. + +```ts +import Notifd from "gi://AstalNotifd" +const notifd = Notifd.get_default() + +notifd.notifications // ❌ // [!code error] + +notifd.get_notifications() // ✅ +``` + +## How to create regular floating windows + +Use `Gtk.Window` with [Widget.astalify](/guide/ags/widget#how-to-use-non-builtin-gtk-widgets). + +By default `Gtk.Window` is destroyed on close. To prevent this add a handler for `delete-event`. + +```tsx {4-7} +const RegularWindow = Widget.astalify(Gtk.Window) + +return { + self.hide() + return true + }} +> + {child} + +``` + +## Is there a way to limit the width/height of a widget? + +Unfortunately not. You can set a minimum size with `min-width` and `min-heigth` css attributes, +but you can not set max size. + +## Custom widgets with bindable properties + +In function components you can wrap any primitive to handle both +binding and value cases as one. + +```tsx +function MyWidget(props: { prop: string | Binding }) { + const prop = props.prop instanceof Binding + ? props.prop + : bind({ get: () => props.prop, subscribe: () => () => {} }) + + function setup(self: Widget.Box) { + self.hook(prop, () => { + const value = prop.get() + // handler + }) + } + + return + +} +``` + +You can pass the prop the super constructor in subclasses + +```tsx +@register() +class MyWidget extends Widget.Box { + @property(String) + set prop(v: string) { + // handler + } + + constructor(props: { prop: string | Binding }) { + super(props) + } +} +``` -- cgit v1.2.3 From b33c3bf91dbbea13b1a2c8603e00809b22cd42c8 Mon Sep 17 00:00:00 2001 From: Aylur Date: Tue, 15 Oct 2024 13:36:16 +0000 Subject: docs: fix links --- docs/guide/typescript/faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/guide/typescript/faq.md') diff --git a/docs/guide/typescript/faq.md b/docs/guide/typescript/faq.md index 76d8e72..48c802c 100644 --- a/docs/guide/typescript/faq.md +++ b/docs/guide/typescript/faq.md @@ -204,7 +204,7 @@ notifd.get_notifications() // ✅ ## How to create regular floating windows -Use `Gtk.Window` with [Widget.astalify](/guide/ags/widget#how-to-use-non-builtin-gtk-widgets). +Use `Gtk.Window` with [Widget.astalify](/guide/typescript/widget#how-to-use-non-builtin-gtk-widgets). By default `Gtk.Window` is destroyed on close. To prevent this add a handler for `delete-event`. -- cgit v1.2.3