aboutsummaryrefslogtreecommitdiff
path: root/.config/ags/service
diff options
context:
space:
mode:
authorsrdusr <trevorgray@srdusr.com>2025-08-30 19:22:59 +0200
committersrdusr <trevorgray@srdusr.com>2025-08-30 19:22:59 +0200
commit19120d4f9761c67d99ed1ce3da6084b83f5a49c9 (patch)
treef234cad1bdad88114a63c9702144da487024967a /.config/ags/service
parent5928998af5404ae2be84c6cecc10ebf84bd3f3ed (diff)
downloaddotfiles-19120d4f9761c67d99ed1ce3da6084b83f5a49c9.tar.gz
dotfiles-19120d4f9761c67d99ed1ce3da6084b83f5a49c9.zip
Linux-specific dotfiles
Diffstat (limited to '.config/ags/service')
-rw-r--r--.config/ags/service/asusctl.ts52
-rw-r--r--.config/ags/service/brightness.ts69
-rw-r--r--.config/ags/service/colorpicker.ts56
-rw-r--r--.config/ags/service/nix.ts109
-rw-r--r--.config/ags/service/powermenu.ts43
-rw-r--r--.config/ags/service/screenrecord.ts102
-rw-r--r--.config/ags/service/wallpaper.ts127
-rw-r--r--.config/ags/service/weather.ts59
8 files changed, 0 insertions, 617 deletions
diff --git a/.config/ags/service/asusctl.ts b/.config/ags/service/asusctl.ts
deleted file mode 100644
index 16acbd7..0000000
--- a/.config/ags/service/asusctl.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import { sh } from "lib/utils"
-
-type Profile = "Performance" | "Balanced" | "Quiet"
-type Mode = "Hybrid" | "Integrated"
-
-class Asusctl extends Service {
- static {
- Service.register(this, {}, {
- "profile": ["string", "r"],
- "mode": ["string", "r"],
- })
- }
-
- available = !!Utils.exec("which asusctl")
- #profile: Profile = "Balanced"
- #mode: Mode = "Hybrid"
-
- async nextProfile() {
- await sh("asusctl profile -n")
- const profile = await sh("asusctl profile -p")
- const p = profile.split(" ")[3] as Profile
- this.#profile = p
- this.changed("profile")
- }
-
- async setProfile(prof: Profile) {
- await sh(`asusctl profile --profile-set ${prof}`)
- this.#profile = prof
- this.changed("profile")
- }
-
- async nextMode() {
- await sh(`supergfxctl -m ${this.#mode === "Hybrid" ? "Integrated" : "Hybrid"}`)
- this.#mode = await sh("supergfxctl -g") as Mode
- this.changed("profile")
- }
-
- constructor() {
- super()
-
- if (this.available) {
- sh("asusctl profile -p").then(p => this.#profile = p.split(" ")[3] as Profile)
- sh("supergfxctl -g").then(m => this.#mode = m as Mode)
- }
- }
-
- get profiles(): Profile[] { return ["Performance", "Balanced", "Quiet"] }
- get profile() { return this.#profile }
- get mode() { return this.#mode }
-}
-
-export default new Asusctl
diff --git a/.config/ags/service/brightness.ts b/.config/ags/service/brightness.ts
deleted file mode 100644
index a0b8eb5..0000000
--- a/.config/ags/service/brightness.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import { bash, dependencies, sh } from "lib/utils"
-
-if (!dependencies("brightnessctl"))
- App.quit()
-
-const get = (args: string) => Number(Utils.exec(`brightnessctl ${args}`))
-const screen = await bash`ls -w1 /sys/class/backlight | head -1`
-const kbd = await bash`ls -w1 /sys/class/leds | head -1`
-
-class Brightness extends Service {
- static {
- Service.register(this, {}, {
- "screen": ["float", "rw"],
- "kbd": ["int", "rw"],
- })
- }
-
- #kbdMax = get(`--device ${kbd} max`)
- #kbd = get(`--device ${kbd} get`)
- #screenMax = get("max")
- #screen = get("get") / get("max")
-
- get kbd() { return this.#kbd }
- get screen() { return this.#screen }
-
- set kbd(value) {
- if (value < 0 || value > this.#kbdMax)
- return
-
- sh(`brightnessctl -d ${kbd} s ${value} -q`).then(() => {
- this.#kbd = value
- this.changed("kbd")
- })
- }
-
- set screen(percent) {
- if (percent < 0)
- percent = 0
-
- if (percent > 1)
- percent = 1
-
- sh(`brightnessctl set ${Math.floor(percent * 100)}% -q`).then(() => {
- this.#screen = percent
- this.changed("screen")
- })
- }
-
- constructor() {
- super()
-
- const screenPath = `/sys/class/backlight/${screen}/brightness`
- const kbdPath = `/sys/class/leds/${kbd}/brightness`
-
- Utils.monitorFile(screenPath, async f => {
- const v = await Utils.readFileAsync(f)
- this.#screen = Number(v) / this.#screenMax
- this.changed("screen")
- })
-
- Utils.monitorFile(kbdPath, async f => {
- const v = await Utils.readFileAsync(f)
- this.#kbd = Number(v) / this.#kbdMax
- this.changed("kbd")
- })
- }
-}
-
-export default new Brightness
diff --git a/.config/ags/service/colorpicker.ts b/.config/ags/service/colorpicker.ts
deleted file mode 100644
index 5918f31..0000000
--- a/.config/ags/service/colorpicker.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import icons from "lib/icons"
-import { bash, dependencies } from "lib/utils"
-
-const COLORS_CACHE = Utils.CACHE_DIR + "/colorpicker.json"
-const MAX_NUM_COLORS = 10
-
-class ColorPicker extends Service {
- static {
- Service.register(this, {}, {
- "colors": ["jsobject"],
- })
- }
-
- #notifID = 0
- #colors = JSON.parse(Utils.readFile(COLORS_CACHE) || "[]") as string[]
-
- get colors() { return [...this.#colors] }
- set colors(colors) {
- this.#colors = colors
- this.changed("colors")
- }
-
- // TODO: doesn't work?
- async wlCopy(color: string) {
- if (dependencies("wl-copy"))
- bash(`wl-copy ${color}`)
- }
-
- readonly pick = async () => {
- if (!dependencies("hyprpicker"))
- return
-
- const color = await bash("hyprpicker -a -r")
- if (!color)
- return
-
- this.wlCopy(color)
- const list = this.colors
- if (!list.includes(color)) {
- list.push(color)
- if (list.length > MAX_NUM_COLORS)
- list.shift()
-
- this.colors = list
- Utils.writeFile(JSON.stringify(list, null, 2), COLORS_CACHE)
- }
-
- this.#notifID = await Utils.notify({
- id: this.#notifID,
- iconName: icons.ui.colorpicker,
- summary: color,
- })
- }
-}
-
-export default new ColorPicker
diff --git a/.config/ags/service/nix.ts b/.config/ags/service/nix.ts
deleted file mode 100644
index 3bde9fc..0000000
--- a/.config/ags/service/nix.ts
+++ /dev/null
@@ -1,109 +0,0 @@
-import icons from "lib/icons"
-import { bash, dependencies } from "lib/utils"
-import options from "options"
-
-const CACHE = `${Utils.CACHE_DIR}/nixpkgs`
-const PREFIX = "legacyPackages.x86_64-linux."
-const MAX = options.launcher.nix.max
-const nixpkgs = options.launcher.nix.pkgs
-
-export type Nixpkg = {
- name: string
- description: string
- pname: string
- version: string
-}
-
-class Nix extends Service {
- static {
- Service.register(this, {}, {
- "available": ["boolean", "r"],
- "ready": ["boolean", "rw"],
- })
- }
-
- #db: { [name: string]: Nixpkg } = {}
- #ready = true
-
- private set ready(r: boolean) {
- this.#ready = r
- this.changed("ready")
- }
-
- get db() { return this.#db }
- get ready() { return this.#ready }
- get available() { return Utils.exec("which nix") }
-
- constructor() {
- super()
- if (!this.available)
- return this
-
- this.#updateList()
- nixpkgs.connect("changed", this.#updateList)
- }
-
- query = async (filter: string) => {
- if (!dependencies("fzf", "nix") || !this.#ready)
- return [] as string[]
-
- return bash(`cat ${CACHE} | fzf -f ${filter} -e | head -n ${MAX} `)
- .then(str => str.split("\n").filter(i => i))
- }
-
- nix(cmd: string, bin: string, args: string) {
- return Utils.execAsync(`nix ${cmd} ${nixpkgs}#${bin} --impure ${args}`)
- }
-
- run = async (input: string) => {
- if (!dependencies("nix"))
- return
-
- try {
- const [bin, ...args] = input.trim().split(/\s+/)
-
- this.ready = false
- await this.nix("shell", bin, "--command sh -c 'exit'")
- this.ready = true
-
- this.nix("run", bin, ["--", ...args].join(" "))
- } catch (err) {
- if (typeof err === "string")
- Utils.notify("NixRun Error", err, icons.nix.nix)
- else
- logError(err)
- } finally {
- this.ready = true
- }
- }
-
- #updateList = async () => {
- if (!dependencies("nix"))
- return
-
- this.ready = false
- this.#db = {}
-
- // const search = await bash(`nix search ${nixpkgs} --json`)
- const search = ""
- if (!search) {
- this.ready = true
- return
- }
-
- const json = Object.entries(JSON.parse(search) as {
- [name: string]: Nixpkg
- })
-
- for (const [pkg, info] of json) {
- const name = pkg.replace(PREFIX, "")
- this.#db[name] = { ...info, name }
- }
-
- const list = Object.keys(this.#db).join("\n")
- await Utils.writeFile(list, CACHE)
- this.ready = true
- }
-}
-
-export default new Nix
diff --git a/.config/ags/service/powermenu.ts b/.config/ags/service/powermenu.ts
deleted file mode 100644
index fd16bc1..0000000
--- a/.config/ags/service/powermenu.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import options from "options"
-
-const { sleep, reboot, logout, shutdown } = options.powermenu
-
-export type Action = "sleep" | "reboot" | "logout" | "shutdown"
-
-class PowerMenu extends Service {
- static {
- Service.register(this, {}, {
- "title": ["string"],
- "cmd": ["string"],
- })
- }
-
- #title = ""
- #cmd = ""
-
- get title() { return this.#title }
- get cmd() { return this.#cmd }
-
- action(action: Action) {
- [this.#cmd, this.#title] = {
- sleep: [sleep.value, "Sleep"],
- reboot: [reboot.value, "Reboot"],
- logout: [logout.value, "Log Out"],
- shutdown: [shutdown.value, "Shutdown"],
- }[action]
-
- this.notify("cmd")
- this.notify("title")
- this.emit("changed")
- App.closeWindow("powermenu")
- App.openWindow("verification")
- }
-
- readonly shutdown = () => {
- this.action("shutdown")
- }
-}
-
-const powermenu = new PowerMenu
-Object.assign(globalThis, { powermenu })
-export default powermenu
diff --git a/.config/ags/service/screenrecord.ts b/.config/ags/service/screenrecord.ts
deleted file mode 100644
index 58721d2..0000000
--- a/.config/ags/service/screenrecord.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-import GLib from "gi://GLib"
-import icons from "lib/icons"
-import { dependencies, sh, bash } from "lib/utils"
-
-const now = () => GLib.DateTime.new_now_local().format("%Y-%m-%d_%H-%M-%S")
-
-class Recorder extends Service {
- static {
- Service.register(this, {}, {
- "timer": ["int"],
- "recording": ["boolean"],
- })
- }
-
- #recordings = Utils.HOME + "/Videos/Screencasting"
- #screenshots = Utils.HOME + "/Pictures/Screenshots"
- #file = ""
- #interval = 0
-
- recording = false
- timer = 0
-
- async start() {
- if (!dependencies("slurp", "wf-recorder"))
- return
-
- if (this.recording)
- return
-
- Utils.ensureDirectory(this.#recordings)
- this.#file = `${this.#recordings}/${now()}.mp4`
- sh(`wf-recorder -g "${await sh("slurp")}" -f ${this.#file} --pixel-format yuv420p`)
-
- this.recording = true
- this.changed("recording")
-
- this.timer = 0
- this.#interval = Utils.interval(1000, () => {
- this.changed("timer")
- this.timer++
- })
- }
-
- async stop() {
- if (!this.recording)
- return
-
- await bash("killall -INT wf-recorder")
- this.recording = false
- this.changed("recording")
- GLib.source_remove(this.#interval)
-
- Utils.notify({
- iconName: icons.fallback.video,
- summary: "Screenrecord",
- body: this.#file,
- actions: {
- "Show in Files": () => sh(`xdg-open ${this.#recordings}`),
- "View": () => sh(`xdg-open ${this.#file}`),
- },
- })
- }
-
- async screenshot(full = false) {
- if (!dependencies("slurp", "wayshot"))
- return
-
- const file = `${this.#screenshots}/${now()}.png`
- Utils.ensureDirectory(this.#screenshots)
-
- if (full) {
- await sh(`wayshot -f ${file}`)
- }
- else {
- const size = await sh("slurp")
- if (!size)
- return
-
- await sh(`wayshot -f ${file} -s "${size}"`)
- }
-
- bash(`wl-copy < ${file}`)
-
- Utils.notify({
- image: file,
- summary: "Screenshot",
- body: file,
- actions: {
- "Show in Files": () => sh(`xdg-open ${this.#screenshots}`),
- "View": () => sh(`xdg-open ${file}`),
- "Edit": () => {
- if (dependencies("swappy"))
- sh(`swappy -f ${file}`)
- },
- },
- })
- }
-}
-
-const recorder = new Recorder
-Object.assign(globalThis, { recorder })
-export default recorder
diff --git a/.config/ags/service/wallpaper.ts b/.config/ags/service/wallpaper.ts
deleted file mode 100644
index 865c6d9..0000000
--- a/.config/ags/service/wallpaper.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-import options from 'options';
-import { dependencies, sh } from 'lib/utils';
-
-export type Resolution = 1920 | 1366 | 3840;
-export type Market = 'random' | 'en-US' | 'ja-JP' | 'en-AU' | 'en-GB' | 'de-DE' | 'en-NZ' | 'en-CA';
-
-const WP = `${Utils.HOME}/pictures/wallpapers`;
-const Cache = `${Utils.HOME}/Pictures/Wallpapers/Bing`;
-
-class Wallpaper extends Service {
- static {
- Service.register(
- this,
- {},
- {
- wallpaper: ['string'],
- },
- );
- }
-
- #blockMonitor = false;
-
- #wallpaper() {
- if (!dependencies('swww')) return;
-
- sh('hyprctl cursorpos').then(pos => {
- sh(['swww', 'img', '--transition-type', 'grow', '--transition-pos', pos.replace(' ', ''), WP]).then(() => {
- this.changed('wallpaper');
- });
- });
- }
-
- async #setWallpaper(path: string) {
- this.#blockMonitor = true;
-
- await sh(`cp "${path}" "${WP}"`);
- this.#wallpaper();
-
- this.#blockMonitor = false;
- }
-
- async #fetchBing() {
- // Check if wallpaper functionality is enabled
- if (!options.wallpaper.enable.value) {
- console.log('Wallpaper functionality is disabled.');
- return;
- }
-
- try {
- const res = await Utils.fetch('https://bing.biturl.top/', {
- params: {
- resolution: options.wallpaper.resolution.value,
- format: 'json',
- image_format: 'jpg',
- index: 'random',
- mkt: options.wallpaper.market.value,
- },
- });
-
- if (!res.ok) {
- console.warn('Failed to fetch from Bing:', res.statusText);
- return;
- }
-
- const data = await res.json();
- const { url } = data;
-
- if (!url) {
- console.warn('No URL found in Bing response:', data);
- return;
- }
-
- const file = `${Cache}/${url.replace('https://www.bing.com/th?id=', '')}`;
-
- Utils.ensureDirectory(Cache);
-
- if (!(await Utils.fileExists(file))) {
- await sh(`curl "${url}" --output "${file}"`);
- await this.#setWallpaper(file);
- } else {
- console.log(`Wallpaper already exists: ${file}`);
- }
- } catch (error) {
- console.error('Error fetching wallpaper:', error);
- }
- }
-
- readonly random = () => {
- // Check if wallpaper functionality is enabled
- if (!options.wallpaper.enable.value) {
- console.log('Wallpaper functionality is disabled.');
- return;
- }
- this.#fetchBing();
- };
-
- readonly set = (path: string) => {
- this.#setWallpaper(path);
- };
-
- get wallpaper() {
- return WP;
- }
- constructor() {
- super();
-
- // Respect wallpaper.enable option
- if (!options.wallpaper.enable.value) {
- console.log('Wallpaper functionality is disabled, not starting swww-daemon.');
- return;
- }
-
- if (!dependencies('swww')) return;
-
- // Monitor and set wallpaper if enabled
- Utils.monitorFile(WP, () => {
- if (!this.#blockMonitor) this.#wallpaper();
- });
-
- // Start swww-daemon only when wallpaper is enabled
- Utils.execAsync('swww-daemon')
- .then(this.#wallpaper)
- .catch(() => null);
- }
-}
-
-export default new Wallpaper();
diff --git a/.config/ags/service/weather.ts b/.config/ags/service/weather.ts
deleted file mode 100644
index 14f2df2..0000000
--- a/.config/ags/service/weather.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import options from "options"
-
-const { interval, key, cities, unit } = options.datemenu.weather
-
-class Weather extends Service {
- static {
- Service.register(this, {}, {
- "forecasts": ["jsobject"],
- })
- }
-
- #forecasts: Forecast[] = []
- get forecasts() { return this.#forecasts }
-
- async #fetch(placeid: number) {
- const url = "https://api.openweathermap.org/data/2.5/forecast"
- const res = await Utils.fetch(url, {
- params: {
- id: placeid,
- appid: key.value,
- untis: unit.value,
- },
- })
- return await res.json()
- }
-
- constructor() {
- super()
- if (!key.value)
- return this
-
- Utils.interval(interval.value, () => {
- Promise.all(cities.value.map(this.#fetch)).then(forecasts => {
- this.#forecasts = forecasts as Forecast[]
- this.changed("forecasts")
- })
- })
- }
-}
-
-export default new Weather
-
-type Forecast = {
- city: {
- name: string,
- }
- list: Array<{
- dt: number
- main: {
- temp: number
- feels_like: number
- },
- weather: Array<{
- main: string,
- description: string,
- icon: string,
- }>
- }>
-}