diff options
| author | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-01-16 16:35:37 +1100 |
|---|---|---|
| committer | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-01-16 16:35:37 +1100 |
| commit | 02fd2e97f2c8a53bf2344e6fa8b14769cb15ee38 (patch) | |
| tree | 5e2a56becf6ba6961995e541ce9688224f704773 /src/utils | |
| parent | popupwindow: switch to class (diff) | |
| download | caelestia-shell-02fd2e97f2c8a53bf2344e6fa8b14769cb15ee38.tar.gz caelestia-shell-02fd2e97f2c8a53bf2344e6fa8b14769cb15ee38.tar.bz2 caelestia-shell-02fd2e97f2c8a53bf2344e6fa8b14769cb15ee38.zip | |
refactor: move ts to src
Also move popupwindow to own file
Diffstat (limited to 'src/utils')
| -rw-r--r-- | src/utils/icons.ts | 86 | ||||
| -rw-r--r-- | src/utils/mpris.ts | 16 | ||||
| -rw-r--r-- | src/utils/strings.ts | 1 | ||||
| -rw-r--r-- | src/utils/system.ts | 21 | ||||
| -rw-r--r-- | src/utils/widgets.ts | 45 |
5 files changed, 169 insertions, 0 deletions
diff --git a/src/utils/icons.ts b/src/utils/icons.ts new file mode 100644 index 0000000..f12aee0 --- /dev/null +++ b/src/utils/icons.ts @@ -0,0 +1,86 @@ +import { Gio } from "astal"; +import type AstalApps from "gi://AstalApps"; +import { Apps } from "../services/apps"; + +// Code points from https://www.github.com/lukas-w/font-logos +export const osIcons: Record<string, number> = { + almalinux: 0xf31d, + alpine: 0xf300, + arch: 0xf303, + arcolinux: 0xf346, + centos: 0x304, + debian: 0xf306, + elementary: 0xf309, + endeavouros: 0xf322, + fedora: 0xf30a, + gentoo: 0xf30d, + kali: 0xf327, + linuxmint: 0xf30e, + mageia: 0xf310, + manjaro: 0xf312, + nixos: 0xf313, + opensuse: 0xf314, + suse: 0xf314, + sles: 0xf314, + sles_sap: 0xf314, + pop: 0xf32a, + raspbian: 0xf315, + rhel: 0xf316, + rocky: 0xf32b, + slackware: 0xf318, + ubuntu: 0xf31b, +}; + +export const desktopEntrySubs: Record<string, string> = { + Firefox: "firefox", +}; + +const categoryIcons: Record<string, string> = { + WebBrowser: "web", + Printing: "print", + Security: "security", + Network: "chat", + Archiving: "archive", + Compression: "archive", + Development: "code", + IDE: "code", + TextEditor: "edit_note", + Audio: "music_note", + Music: "music_note", + Player: "music_note", + Recorder: "mic", + Game: "sports_esports", + FileTools: "files", + FileManager: "files", + Filesystem: "files", + FileTransfer: "files", + Settings: "settings", + DesktopSettings: "settings", + HardwareSettings: "settings", + TerminalEmulator: "terminal", + ConsoleOnly: "terminal", + Utility: "build", + Monitor: "monitor_heart", + Midi: "graphic_eq", + Mixer: "graphic_eq", + AudioVideoEditing: "video_settings", + AudioVideo: "music_video", + Video: "videocam", + Building: "construction", + Graphics: "photo_library", + "2DGraphics": "photo_library", + RasterGraphics: "photo_library", + TV: "tv", + System: "host", +}; + +export const getAppCategoryIcon = (nameOrApp: string | AstalApps.Application) => { + const categories = + typeof nameOrApp === "string" + ? Gio.DesktopAppInfo.new(`${nameOrApp}.desktop`)?.get_categories()?.split(";") ?? + Apps.fuzzy_query(nameOrApp)[0]?.categories + : nameOrApp.categories; + if (categories) + for (const [key, value] of Object.entries(categoryIcons)) if (categories.includes(key)) return value; + return "terminal"; +}; diff --git a/src/utils/mpris.ts b/src/utils/mpris.ts new file mode 100644 index 0000000..e0cc111 --- /dev/null +++ b/src/utils/mpris.ts @@ -0,0 +1,16 @@ +import { GLib } from "astal"; +import AstalMpris from "gi://AstalMpris"; + +const hasPlasmaIntegration = GLib.find_program_in_path("plasma-browser-integration-host") !== null; + +export const isRealPlayer = (player?: AstalMpris.Player) => + player !== undefined && + // Player closed + player.identity !== null && + // Remove unecessary native buses from browsers if there's plasma integration + !(hasPlasmaIntegration && player.busName.startsWith("org.mpris.MediaPlayer2.firefox")) && + !(hasPlasmaIntegration && player.busName.startsWith("org.mpris.MediaPlayer2.chromium")) && + // playerctld just copies other buses and we don't need duplicates + !player.busName.startsWith("org.mpris.MediaPlayer2.playerctld") && + // Non-instance mpd bus + !(player.busName.endsWith(".mpd") && !player.busName.endsWith("MediaPlayer2.mpd")); diff --git a/src/utils/strings.ts b/src/utils/strings.ts new file mode 100644 index 0000000..e5bc43e --- /dev/null +++ b/src/utils/strings.ts @@ -0,0 +1 @@ +export const ellipsize = (str: string, len = 40) => (str.length > len ? `${str.slice(0, len - 1)}…` : str); diff --git a/src/utils/system.ts b/src/utils/system.ts new file mode 100644 index 0000000..5d77908 --- /dev/null +++ b/src/utils/system.ts @@ -0,0 +1,21 @@ +import { execAsync, GLib } from "astal"; +import type AstalApps from "gi://AstalApps"; +import { osIcons } from "./icons"; + +export const launch = (app: AstalApps.Application) => { + execAsync(["uwsm", "app", "--", app.entry]).catch(() => { + app.frequency--; // Decrement frequency cause launch also increments it + app.launch(); + }); + app.frequency++; +}; + +export const osId = GLib.get_os_info("ID") ?? "unknown"; +export const osIdLike = GLib.get_os_info("ID_LIKE"); +export const osIcon = String.fromCodePoint( + (() => { + if (osIcons.hasOwnProperty(osId)) return osIcons[osId]; + if (osIdLike) for (const id of osIdLike.split(" ")) if (osIcons.hasOwnProperty(id)) return osIcons[id]; + return 0xf31a; + })() +); diff --git a/src/utils/widgets.ts b/src/utils/widgets.ts new file mode 100644 index 0000000..08f9740 --- /dev/null +++ b/src/utils/widgets.ts @@ -0,0 +1,45 @@ +import { Binding } from "astal"; +import { Astal, Widget } from "astal/gtk3"; +import AstalHyprland from "gi://AstalHyprland"; + +export const setupCustomTooltip = (self: any, text: string | Binding<string>) => { + if (!text) return null; + + const window = new Widget.Window({ + visible: false, + namespace: "caelestia-tooltip", + keymode: Astal.Keymode.NONE, + exclusivity: Astal.Exclusivity.IGNORE, + anchor: Astal.WindowAnchor.TOP | Astal.WindowAnchor.LEFT, + child: new Widget.Label({ className: "tooltip", label: text }), + }); + self.set_tooltip_window(window); + + let dirty = true; + let lastX = 0; + self.connect("size-allocate", () => (dirty = true)); + window.connect("size-allocate", () => { + window.marginLeft = lastX + (self.get_allocated_width() - window.get_preferred_width()[1]) / 2; + }); + if (text instanceof Binding) self.hook(text, (_: any, v: string) => !v && window.hide()); + + self.connect("query-tooltip", (_: any, x: number, y: number) => { + if (text instanceof Binding && !text.get()) return false; + if (dirty) { + const { width, height } = self.get_allocation(); + const { x: cx, y: cy } = AstalHyprland.get_default().get_cursor_position(); + window.marginLeft = cx + ((width - window.get_preferred_width()[1]) / 2 - x); + window.marginTop = cy + (height - y); + lastX = cx - x; + dirty = false; + } + return true; + }); + + self.connect("destroy", () => window.destroy()); + + return window; +}; + +export const setupChildClickthrough = (self: any) => + self.connect("size-allocate", () => self.get_window()?.set_child_input_shapes()); |