diff --git a/flake.lock b/flake.lock index d1c3b06..b05e22a 100644 --- a/flake.lock +++ b/flake.lock @@ -5,11 +5,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1698970509, - "narHash": "sha256-5n048xWGUgvqGfnVszh7/8Bv75czYO12gaZWx/KImGg=", + "lastModified": 1703934913, + "narHash": "sha256-ICPSBWQBPVthW1uXxFizOfuNU3SEf+rf/tfJD89mWRk=", "owner": "Aylur", "repo": "ags", - "rev": "7720f98f1aaa73b2a85f70652eb9c3c1cd4485e2", + "rev": "6a892994287b52ee3014dedfb41cec9fb675875b", "type": "github" }, "original": { @@ -141,11 +141,11 @@ ] }, "locked": { - "lastModified": 1701071203, - "narHash": "sha256-lQywA7QU/vzTdZ1apI0PfgCWNyQobXUYghVrR5zuIeM=", + "lastModified": 1703838268, + "narHash": "sha256-SRg5nXcdPnrsQR2MTAp7en0NyJnQ2wB1ivmsgEbvN+o=", "owner": "nix-community", "repo": "home-manager", - "rev": "db1878f013b52ba5e4034db7c1b63e8d04173a86", + "rev": "2aff324cf65f5f98f89d878c056b779466b17db8", "type": "github" }, "original": { @@ -188,11 +188,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1703438236, - "narHash": "sha256-aqVBq1u09yFhL7bj1/xyUeJjzr92fXVvQSSEx6AdB1M=", + "lastModified": 1703637592, + "narHash": "sha256-8MXjxU0RfFfzl57Zy3OfXCITS0qWDNLzlBAdwxGZwfY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5f64a12a728902226210bf01d25ec6cbb9d9265b", + "rev": "cfc3698c31b1fb9cdcf10f36c9643460264d0ca8", "type": "github" }, "original": { @@ -211,11 +211,11 @@ "pre-commit-hooks": "pre-commit-hooks" }, "locked": { - "lastModified": 1701956652, - "narHash": "sha256-PGkn4yCvui0HtJbVfGu0yKSZgwvsP0GdApD0M1MjcZY=", + "lastModified": 1703944758, + "narHash": "sha256-VOe76pyV9zY+1pX09nX4ZDv2dINZylI7U5sWmWm20gA=", "owner": "nix-community", "repo": "nixvim", - "rev": "cc3f5209c1253442608d17055d14e5da2122dabd", + "rev": "9738dae3eac5c9b1c1e3ab787db0cedfc59e49b9", "type": "github" }, "original": { @@ -236,11 +236,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1700922917, - "narHash": "sha256-ej2fch/T584b5K9sk1UhmZF7W6wEfDHuoUYpFN8dtvM=", + "lastModified": 1703426812, + "narHash": "sha256-aODSOH8Og8ne4JylPJn+hZ6lyv6K7vE5jFo4KAGIebM=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "e5ee5c5f3844550c01d2131096c7271cec5e9b78", + "rev": "7f35ec30d16b38fe0eed8005933f418d1a4693ee", "type": "github" }, "original": { diff --git a/home/desktops/hyprland/ags/.eslintrc.yml b/home/desktops/hyprland/ags/.eslintrc.yml new file mode 100644 index 0000000..05b56ca --- /dev/null +++ b/home/desktops/hyprland/ags/.eslintrc.yml @@ -0,0 +1,77 @@ +env: + es2021: true +extends: eslint:recommended +overrides: [] +parserOptions: + ecmaVersion: latest + sourceType: "module" +rules: + arrow-parens: + - error + - as-needed + comma-dangle: + - error + - always-multiline + comma-spacing: + - error + - before: false + after: true + comma-style: + - error + - last + curly: + - error + - multi-or-nest + - consistent + dot-location: + - error + - property + eol-last: error + indent: + - error + - 4 + - SwitchCase: 1 + keyword-spacing: + - error + - before: true + lines-between-class-members: + - error + - always + - exceptAfterSingleLine: true + padded-blocks: + - error + - never + - allowSingleLineBlocks: false + prefer-const: error + quotes: + - error + - single + - avoidEscape: true + semi: + - error + - always + nonblock-statement-body-position: + - error + - below + no-trailing-spaces: + - error + array-bracket-spacing: + - error + - never + key-spacing: + - error + - beforeColon: false + afterColon: true + object-curly-spacing: + - error + - always + no-useless-escape: + - off +globals: + pkg: readonly + ags: readonly + ARGV: readonly + imports: readonly + print: readonly + console: readonly + logError: readonly diff --git a/home/desktops/hyprland/ags/.gitignore b/home/desktops/hyprland/ags/.gitignore new file mode 100644 index 0000000..fd61781 --- /dev/null +++ b/home/desktops/hyprland/ags/.gitignore @@ -0,0 +1,5 @@ +node_modules +types +package-lock.json +weather_key +setup.sh diff --git a/home/desktops/hyprland/ags/.idea/.gitignore b/home/desktops/hyprland/ags/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/home/desktops/hyprland/ags/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/home/desktops/hyprland/ags/.idea/ags.iml b/home/desktops/hyprland/ags/.idea/ags.iml deleted file mode 100644 index e3cfe00..0000000 --- a/home/desktops/hyprland/ags/.idea/ags.iml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/home/desktops/hyprland/ags/.idea/misc.xml b/home/desktops/hyprland/ags/.idea/misc.xml deleted file mode 100644 index 9c9b300..0000000 --- a/home/desktops/hyprland/ags/.idea/misc.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/home/desktops/hyprland/ags/.idea/modules.xml b/home/desktops/hyprland/ags/.idea/modules.xml deleted file mode 100644 index 3509153..0000000 --- a/home/desktops/hyprland/ags/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/home/desktops/hyprland/ags/.stylelintrc.yml b/home/desktops/hyprland/ags/.stylelintrc.yml new file mode 100644 index 0000000..bf75e9a --- /dev/null +++ b/home/desktops/hyprland/ags/.stylelintrc.yml @@ -0,0 +1,14 @@ +extends: stylelint-config-standard-scss +ignoreFiles: + - "**/*.js" + - "**/*.ts" +rules: + selector-type-no-unknown: null + declaration-empty-line-before: null + no-descending-specificity: null + selector-pseudo-class-no-unknown: null + color-function-notation: legacy + alpha-value-notation: number + scss/operator-no-unspaced: null + scss/no-global-function-names: null + scss/dollar-variable-empty-line-before: null diff --git a/home/desktops/hyprland/ags/assets/aylur.jpg b/home/desktops/hyprland/ags/assets/aylur.jpg new file mode 100644 index 0000000..614af5e Binary files /dev/null and b/home/desktops/hyprland/ags/assets/aylur.jpg differ diff --git a/home/desktops/hyprland/ags/assets/ivory.png b/home/desktops/hyprland/ags/assets/ivory.png new file mode 100644 index 0000000..4b1ddf4 Binary files /dev/null and b/home/desktops/hyprland/ags/assets/ivory.png differ diff --git a/home/desktops/hyprland/ags/assets/kitty.jpeg b/home/desktops/hyprland/ags/assets/kitty.jpeg new file mode 100644 index 0000000..70ce6b7 Binary files /dev/null and b/home/desktops/hyprland/ags/assets/kitty.jpeg differ diff --git a/home/desktops/hyprland/ags/assets/kittybl.jpeg b/home/desktops/hyprland/ags/assets/kittybl.jpeg new file mode 100644 index 0000000..47e50c1 Binary files /dev/null and b/home/desktops/hyprland/ags/assets/kittybl.jpeg differ diff --git a/home/desktops/hyprland/ags/assets/leaves.jpg b/home/desktops/hyprland/ags/assets/leaves.jpg new file mode 100644 index 0000000..e123e75 Binary files /dev/null and b/home/desktops/hyprland/ags/assets/leaves.jpg differ diff --git a/home/desktops/hyprland/ags/assets/space.jpg b/home/desktops/hyprland/ags/assets/space.jpg new file mode 100644 index 0000000..6e47c24 Binary files /dev/null and b/home/desktops/hyprland/ags/assets/space.jpg differ diff --git a/home/desktops/hyprland/ags/config.js b/home/desktops/hyprland/ags/config.js index 8e47fb1..1dd0b1a 100644 --- a/home/desktops/hyprland/ags/config.js +++ b/home/desktops/hyprland/ags/config.js @@ -1,58 +1,21 @@ -// Import -import { App, Utils } from "./imports.js"; -// Windows -import Bar from "./windows/bar.js"; -import Cheatsheet from "./windows/cheatsheet.js"; -import { - CornerTopleft, - CornerTopright, - CornerBottomleft, - CornerBottomright, -} from "./windows/corners.js"; -import Indicator from "./windows/osd.js"; -import Osk from "./windows/osk.js"; -import Overview from "./windows/overview.js"; -import Session from "./windows/session.js"; -import SideLeft from "./windows/sideleft.js"; -import SideRight from "./windows/sideright.js"; +import { readFile } from "resource:///com/github/Aylur/ags/utils.js"; +import App from "resource:///com/github/Aylur/ags/app.js"; +import { timeout } from "resource:///com/github/Aylur/ags/utils.js"; +const pkgjson = JSON.parse(readFile(App.configDir + "/package.json")); -const CLOSE_ANIM_TIME = 150; +timeout(1000, () => JSON.stringify(App)); -// Init -Utils.exec(`bash -c 'mkdir -p ~/.cache/ags/user'`); -// SCSS compilation -Utils.exec(`sassc ${App.configDir}/scss/main.scss ${App.configDir}/style.css`); -App.resetCss(); -App.applyCss(`${App.configDir}/style.css`); - -// Config object -export default { - style: `${App.configDir}/style.css`, - stackTraceOnError: true, - closeWindowDelay: { - // For animations - sideright: CLOSE_ANIM_TIME, - sideleft: CLOSE_ANIM_TIME, - osk: CLOSE_ANIM_TIME, - // No anims, but allow menu service update - session: 1, - overview: 1, - cheatsheet: 1, - }, - windows: [ - //Bar(), - ...Array.from({ length: 3 }, (_, i) => [ - CornerTopleft(i), - CornerTopright(i), - CornerBottomleft(i), - CornerBottomright(i), - ]), - //Overview(), - Indicator(), - //Cheatsheet(), - SideRight(), - SideLeft(), - //Osk(), // On-screen keyboard - //Session(), - ], +const v = { + ags: `v${pkg.version}`, + expected: `v${pkgjson.version}`, }; + +function mismatch() { + print(`my config expects ${v.expected}, but your ags is ${v.ags}`); + App.connect("config-parsed", (app) => app.Quit()); + return {}; +} + +export default v.ags === v.expected + ? (await import("./js/main.js")).default + : mismatch(); diff --git a/home/desktops/hyprland/ags/data/keybinds.js b/home/desktops/hyprland/ags/data/keybinds.js deleted file mode 100644 index 3aa0a7d..0000000 --- a/home/desktops/hyprland/ags/data/keybinds.js +++ /dev/null @@ -1,132 +0,0 @@ -export const keybindList = [[ - { - "icon": "pin_drop", - "name": "Workspaces: navigation", - "binds": [ - { "keys": ["", "+", "#"], "action": "Go to workspace #" }, - { "keys": ["", "+", "S"], "action": "Toggle special workspace" }, - { "keys": ["", "+", "(Scroll ↑↓)"], "action": "Go to workspace -1/+1" }, - { "keys": ["Ctrl", "", "+", "←"], "action": "Go to workspace on the left" }, - { "keys": ["Ctrl", "", "+", "→"], "action": "Go to workspace on the right" }, - { "keys": ["", "+", "PageUp"], "action": "Go to workspace on the left" }, - { "keys": ["", "+", "PageDown"], "action": "Go to workspace on the right" } - ], - "appeartick": 1 - }, - { - "icon": "overview_key", - "name": "Workspaces: management", - "binds": [ - { "keys": ["", "Alt", "+", "#"], "action": "Move window to workspace #" }, - { "keys": ["", "Alt", "+", "S"], "action": "Move window to special workspace" }, - { "keys": ["", "Alt", "+", "PageUp"], "action": "Move window to workspace on the left" }, - { "keys": ["", "Alt", "+", "PageDown"], "action": "Move window to workspace on the right" } - ], - "appeartick": 1 - }, - { - "icon": "move_group", - "name": "Windows", - "binds": [ - { "keys": ["", "+", "←↑→↓"], "action": "Focus window in direction" }, - { "keys": ["", "Shift", "+", "←↑→↓"], "action": "Swap window in direction" }, - { "keys": ["", "+", ";"], "action": "Split ratio -" }, - { "keys": ["", "+", "'"], "action": "Split ratio +" }, - { "keys": ["", "+", "Lmb"], "action": "Move window" }, - { "keys": ["", "+", "Mmb"], "action": "Move window" }, - { "keys": ["", "+", "Rmb"], "action": "Resize window" }, - { "keys": ["", "+", "F"], "action": "Fullscreen" }, - { "keys": ["", "Alt", "+", "F"], "action": "Fake fullscreen" } - ], - "appeartick": 1 - } -], -[ - { - "icon": "widgets", - "name": "Widgets (AGS)", - "binds": [ - { "keys": ["", "OR", "", "+", "Tab"], "action": "Toggle overview/launcher" }, - { "keys": ["Ctrl", "", "+", "R"], "action": "Restart AGS" }, - { "keys": ["", "+", "/"], "action": "Toggle this cheatsheet" }, - { "keys": ["", "+", "N"], "action": "Toggle sidebar" }, - { "keys": ["", "+", "K"], "action": "Toggle virtual keyboard" }, - { "keys": ["Ctrl", "Alt", "+", "Del"], "action": "Power/Session menu" }, - - { "keys": ["Esc"], "action": "Exit a window" }, - { "keys": ["rightCtrl"], "action": "Dismiss/close sidebar" }, - - // { "keys": ["", "+", "B"], "action": "Toggle left sidebar" }, - // { "keys": ["", "+", "N"], "action": "Toggle right sidebar" }, - // { "keys": ["", "+", "G"], "action": "Toggle volume mixer" }, - // { "keys": ["", "+", "M"], "action": "Toggle useless audio visualizer" }, - // { "keys": ["(right)Ctrl"], "action": "Dismiss notification & close menus" } - ], - "appeartick": 2 - }, - { - "icon": "construction", - "name": "Utilities", - "binds": [ - { "keys": ["PrtSc"], "action": "Screenshot >> clipboard" }, - { "keys": ["", "Shift", "+", "S"], "action": "Screen snip >> clipboard" }, - { "keys": ["", "Shift", "+", "T"], "action": "Image to text >> clipboard" }, - { "keys": ["", "Shift", "+", "C"], "action": "Color picker" }, - { "keys": ["", "Alt", "+", "R"], "action": "Record region" }, - { "keys": ["Ctrl", "Alt", "+", "R"], "action": "Record region with sound" }, - { "keys": ["", "Shift", "Alt", "+", "R"], "action": "Record screen with sound" } - ], - "appeartick": 2 - }, - // { - // "icon": "edit", - // "name": "Edit mode", - // "binds": [ - // { "keys": ["Esc"], "action": "Exit Edit mode" }, - // { "keys": ["#"], "action": "Go to to workspace #" }, - // { "keys": ["Alt", "+", "#"], "action": "Dump windows to workspace #" }, - // { "keys": ["Shift", "+", "#"], "action": "Swap windows with workspace #" }, - // { "keys": ["Lmb"], "action": "Move window" }, - // { "keys": ["Mmb"], "action": "Move window" }, - // { "keys": ["Rmb"], "action": "Resize window" } - // ], - // "appeartick": 2 - // } -], -[ - { - "icon": "apps", - "name": "Apps", - "binds": [ - { "keys": ["", "+", "T"], "action": "Launch terminal: foot" }, - { "keys": ["", "+", "↵"], "action": "Launch terminal: WezTerm" }, - { "keys": ["", "+", "W"], "action": "Launch browser: Firefox" }, - { "keys": ["", "+", "C"], "action": "Launch editor: vscode" }, - { "keys": ["", "+", "X"], "action": "Launch editor: GNOME Text Editor" }, - { "keys": ["", "+", "I"], "action": "Launch settings: GNOME Control center" } - ], - "appeartick": 3 - }, - { - "icon": "keyboard", - "name": "Typing", - "binds": [ - { "keys": ["", "+", "V"], "action": "Clipboard history >> clipboard" }, - { "keys": ["", "+", "."], "action": "Emoji picker >> clipboard" }, - { "keys": ["", "+", " 󱁐 "], "action": "Switch language" } - ], - "appeartick": 3 - }, - { - "icon": "terminal", - "name": "Launcher commands", - "binds": [ - { "keys": [">raw"], "action": "Toggle mouse acceleration" }, - { "keys": [">img"], "action": "Select wallpaper and generate colorscheme" }, - { "keys": [">light"], "action": "Use light theme for next color generations" }, - { "keys": [">dark"], "action": "Use dark theme for next color generations" }, - { "keys": [">todo"], "action": "Type something after that to add a To-do item" }, - ], - "appeartick": 3 - } -]]; diff --git a/home/desktops/hyprland/ags/data/keyboardlayouts.js b/home/desktops/hyprland/ags/data/keyboardlayouts.js deleted file mode 100644 index f58e378..0000000 --- a/home/desktops/hyprland/ags/data/keyboardlayouts.js +++ /dev/null @@ -1,114 +0,0 @@ -// We're going to use ydotool -// See /usr/include/linux/input-event-codes.h for keycodes - -export const defaultOskLayout = "qwerty_full" -export const oskLayouts = { - qwerty_full: { - name: "QWERTY - Full", - name_short: "US", - comment: "Like physical keyboard", - // A key looks like this: { k: "a", ks: "A", t: "normal" } (key, key-shift, type) - // key types are: normal, tab, caps, shift, control, fn (normal w/ half height), space, expand - // keys: [ - // [{ k: "Esc", t: "fn" }, { k: "F1", t: "fn" }, { k: "F2", t: "fn" }, { k: "F3", t: "fn" }, { k: "F4", t: "fn" }, { k: "F5", t: "fn" }, { k: "F6", t: "fn" }, { k: "F7", t: "fn" }, { k: "F8", t: "fn" }, { k: "F9", t: "fn" }, { k: "F10", t: "fn" }, { k: "F11", t: "fn" }, { k: "F12", t: "fn" }, { k: "PrtSc", t: "fn" }, { k: "Del", t: "fn" }], - // [{ k: "`", ks: "~", t: "normal" }, { k: "1", ks: "!", t: "normal" }, { k: "2", ks: "@", t: "normal" }, { k: "3", ks: "#", t: "normal" }, { k: "4", ks: "$", t: "normal" }, { k: "5", ks: "%", t: "normal" }, { k: "6", ks: "^", t: "normal" }, { k: "7", ks: "&", t: "normal" }, { k: "8", ks: "*", t: "normal" }, { k: "9", ks: "(", t: "normal" }, { k: "0", ks: ")", t: "normal" }, { k: "-", ks: "_", t: "normal" }, { k: "=", ks: "+", t: "normal" }, { k: "Backspace", t: "shift" }], - // [{ k: "Tab", t: "tab" }, { k: "q", ks: "Q", t: "normal" }, { k: "w", ks: "W", t: "normal" }, { k: "e", ks: "E", t: "normal" }, { k: "r", ks: "R", t: "normal" }, { k: "t", ks: "T", t: "normal" }, { k: "y", ks: "Y", t: "normal" }, { k: "u", ks: "U", t: "normal" }, { k: "i", ks: "I", t: "normal" }, { k: "o", ks: "O", t: "normal" }, { k: "p", ks: "P", t: "normal" }, { k: "[", ks: "{", t: "normal" }, { k: "]", ks: "}", t: "normal" }, { k: "\\", ks: "|", t: "expand" }], - // [{ k: "Caps", t: "caps" }, { k: "a", ks: "A", t: "normal" }, { k: "s", ks: "S", t: "normal" }, { k: "d", ks: "D", t: "normal" }, { k: "f", ks: "F", t: "normal" }, { k: "g", ks: "G", t: "normal" }, { k: "h", ks: "H", t: "normal" }, { k: "j", ks: "J", t: "normal" }, { k: "k", ks: "K", t: "normal" }, { k: "l", ks: "L", t: "normal" }, { k: ";", ks: ":", t: "normal" }, { k: "'", ks: '"', t: "normal" }, { k: "Enter", t: "expand" }], - // [{ k: "Shift", t: "shift" }, { k: "z", ks: "Z", t: "normal" }, { k: "x", ks: "X", t: "normal" }, { k: "c", ks: "C", t: "normal" }, { k: "v", ks: "V", t: "normal" }, { k: "b", ks: "B", t: "normal" }, { k: "n", ks: "N", t: "normal" }, { k: "m", ks: "M", t: "normal" }, { k: ",", ks: "<", t: "normal" }, { k: ".", ks: ">", t: "normal" }, { k: "/", ks: "?", t: "normal" }, { k: "Shift", t: "expand" }], - // [{ k: "Ctrl", t: "control" }, { k: "Fn", t: "normal" }, { k: "Win", t: "normal" }, { k: "Alt", t: "normal" }, { k: "Space", t: "space" }, { k: "Alt", t: "normal" }, { k: "Menu", t: "normal" }, { k: "Ctrl", t: "control" }] - // ] - // A normal key looks like this: {label: "a", labelShift: "A", shape: "normal", keycode: 30, type: "normal"} - // A modkey looks like this: {label: "Ctrl", shape: "control", keycode: 29, type: "modkey"} - // key types are: normal, tab, caps, shift, control, fn (normal w/ half height), space, expand - keys: [ - [ - { keytype: "normal", label: "Esc", shape: "fn", keycode: 1 }, - { keytype: "normal", label: "F1", shape: "fn", keycode: 59 }, - { keytype: "normal", label: "F2", shape: "fn", keycode: 60 }, - { keytype: "normal", label: "F3", shape: "fn", keycode: 61 }, - { keytype: "normal", label: "F4", shape: "fn", keycode: 62 }, - { keytype: "normal", label: "F5", shape: "fn", keycode: 63 }, - { keytype: "normal", label: "F6", shape: "fn", keycode: 64 }, - { keytype: "normal", label: "F7", shape: "fn", keycode: 65 }, - { keytype: "normal", label: "F8", shape: "fn", keycode: 66 }, - { keytype: "normal", label: "F9", shape: "fn", keycode: 67 }, - { keytype: "normal", label: "F10", shape: "fn", keycode: 68 }, - { keytype: "normal", label: "F11", shape: "fn", keycode: 87 }, - { keytype: "normal", label: "F12", shape: "fn", keycode: 88 }, - { keytype: "normal", label: "PrtSc", shape: "fn", keycode: 99 }, - { keytype: "normal", label: "Del", shape: "fn", keycode: 111 } - ], - [ - { keytype: "normal", label: "`", labelShift: "~", shape: "normal", keycode: 41 }, - { keytype: "normal", label: "1", labelShift: "!", shape: "normal", keycode: 2 }, - { keytype: "normal", label: "2", labelShift: "@", shape: "normal", keycode: 3 }, - { keytype: "normal", label: "3", labelShift: "#", shape: "normal", keycode: 4 }, - { keytype: "normal", label: "4", labelShift: "$", shape: "normal", keycode: 5 }, - { keytype: "normal", label: "5", labelShift: "%", shape: "normal", keycode: 6 }, - { keytype: "normal", label: "6", labelShift: "^", shape: "normal", keycode: 7 }, - { keytype: "normal", label: "7", labelShift: "&", shape: "normal", keycode: 8 }, - { keytype: "normal", label: "8", labelShift: "*", shape: "normal", keycode: 9 }, - { keytype: "normal", label: "9", labelShift: "(", shape: "normal", keycode: 10 }, - { keytype: "normal", label: "0", labelShift: ")", shape: "normal", keycode: 11 }, - { keytype: "normal", label: "-", labelShift: "_", shape: "normal", keycode: 12 }, - { keytype: "normal", label: "=", labelShift: "+", shape: "normal", keycode: 13 }, - { keytype: "normal", label: "Backspace", shape: "expand", keycode: 14 } - ], - [ - { keytype: "normal", label: "Tab", shape: "tab", keycode: 15 }, - { keytype: "normal", label: "q", labelShift: "Q", shape: "normal", keycode: 16 }, - { keytype: "normal", label: "w", labelShift: "W", shape: "normal", keycode: 17 }, - { keytype: "normal", label: "e", labelShift: "E", shape: "normal", keycode: 18 }, - { keytype: "normal", label: "r", labelShift: "R", shape: "normal", keycode: 19 }, - { keytype: "normal", label: "t", labelShift: "T", shape: "normal", keycode: 20 }, - { keytype: "normal", label: "y", labelShift: "Y", shape: "normal", keycode: 21 }, - { keytype: "normal", label: "u", labelShift: "U", shape: "normal", keycode: 22 }, - { keytype: "normal", label: "i", labelShift: "I", shape: "normal", keycode: 23 }, - { keytype: "normal", label: "o", labelShift: "O", shape: "normal", keycode: 24 }, - { keytype: "normal", label: "p", labelShift: "P", shape: "normal", keycode: 25 }, - { keytype: "normal", label: "[", labelShift: "{", shape: "normal", keycode: 26 }, - { keytype: "normal", label: "]", labelShift: "}", shape: "normal", keycode: 27 }, - { keytype: "normal", label: "\\", labelShift: "|", shape: "expand", keycode: 43 } - ], - [ - { keytype: "normal", label: "Caps", shape: "caps", keycode: 58 }, - { keytype: "normal", label: "a", labelShift: "A", shape: "normal", keycode: 30 }, - { keytype: "normal", label: "s", labelShift: "S", shape: "normal", keycode: 31 }, - { keytype: "normal", label: "d", labelShift: "D", shape: "normal", keycode: 32 }, - { keytype: "normal", label: "f", labelShift: "F", shape: "normal", keycode: 33 }, - { keytype: "normal", label: "g", labelShift: "G", shape: "normal", keycode: 34 }, - { keytype: "normal", label: "h", labelShift: "H", shape: "normal", keycode: 35 }, - { keytype: "normal", label: "j", labelShift: "J", shape: "normal", keycode: 36 }, - { keytype: "normal", label: "k", labelShift: "K", shape: "normal", keycode: 37 }, - { keytype: "normal", label: "l", labelShift: "L", shape: "normal", keycode: 38 }, - { keytype: "normal", label: ";", labelShift: ":", shape: "normal", keycode: 39 }, - { keytype: "normal", label: "'", labelShift: '"', shape: "normal", keycode: 40 }, - { keytype: "normal", label: "Enter", shape: "expand", keycode: 28 } - ], - [ - { keytype: "modkey", label: "Shift", shape: "shift", keycode: 42 }, - { keytype: "normal", label: "z", labelShift: "Z", shape: "normal", keycode: 44 }, - { keytype: "normal", label: "x", labelShift: "X", shape: "normal", keycode: 45 }, - { keytype: "normal", label: "c", labelShift: "C", shape: "normal", keycode: 46 }, - { keytype: "normal", label: "v", labelShift: "V", shape: "normal", keycode: 47 }, - { keytype: "normal", label: "b", labelShift: "B", shape: "normal", keycode: 48 }, - { keytype: "normal", label: "n", labelShift: "N", shape: "normal", keycode: 49 }, - { keytype: "normal", label: "m", labelShift: "M", shape: "normal", keycode: 50 }, - { keytype: "normal", label: ",", labelShift: "<", shape: "normal", keycode: 51 }, - { keytype: "normal", label: ".", labelShift: ">", shape: "normal", keycode: 52 }, - { keytype: "normal", label: "/", labelShift: "?", shape: "normal", keycode: 53 }, - { keytype: "modkey", label: "Shift", shape: "expand", keycode: 54 } - ], - [ - { keytype: "modkey", label: "Ctrl", shape: "control", keycode: 29 }, - // { label: "Super", shape: "normal", keycode: 125 }, // dangerous - { keytype: "modkey", label: "Alt", shape: "normal", keycode: 56 }, - { keytype: "normal", label: "Space", shape: "space", keycode: 57 }, - { keytype: "modkey", label: "Alt", shape: "normal", keycode: 100 }, - // { label: "Super", shape: "normal", keycode: 126 }, // dangerous - { keytype: "normal", label: "Menu", shape: "normal", keycode: 139 }, - { keytype: "modkey", label: "Ctrl", shape: "control", keycode: 97 } - ] - ] - } -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/data/quotes.js b/home/desktops/hyprland/ags/data/quotes.js deleted file mode 100644 index 7cea990..0000000 --- a/home/desktops/hyprland/ags/data/quotes.js +++ /dev/null @@ -1,14 +0,0 @@ -export const quotes = [ - { - quote: 'Nvidia, fuck you', - author: 'Linus Torvalds', - }, - { - quote: 'reproducible system? cock and vagina?', - author: 'vaxry', - }, - { - quote: "haha pointers hee hee i love pointe-\\\nProcess Vaxry exited with signal SIGSEGV", - author: 'vaxry', - } -]; diff --git a/home/desktops/hyprland/ags/imports.js b/home/desktops/hyprland/ags/imports.js deleted file mode 100644 index 89aa0db..0000000 --- a/home/desktops/hyprland/ags/imports.js +++ /dev/null @@ -1,40 +0,0 @@ -const resource = file => `resource:///com/github/Aylur/ags/${file}.js`; -const require = async file => (await import(resource(file))).default; -const service = async file => (await require(`service/${file}`)); - -export const App = await require('app'); -export const Widget = await require('widget'); -export const Service = await require('service'); -export const Variable = await require('variable'); -export const Utils = await import(resource('utils')); - -export const Applications = await service('applications'); -export const Audio = await service('audio'); -export const Battery = await service('battery'); -export const Bluetooth = await service('bluetooth'); -export const Hyprland = await service('hyprland'); -export const Mpris = await service('mpris'); -export const Network = await service('network'); -export const Notifications = await service('notifications'); -export const SystemTray = await service('systemtray'); - -globalThis['App'] = App; ////////////////////////////// -// globalThis['Widget'] = Widget; -// globalThis['Service'] = Service; -// globalThis['Variable'] = Variable; -globalThis['Utils'] = Utils; /////////////////////////// -// globalThis['Applications'] = Applications; -// globalThis['Audio'] = Audio; -// globalThis['Battery'] = Battery; -// globalThis['Bluetooth'] = Bluetooth; -// globalThis['Hyprland'] = Hyprland; -// globalThis['Mpris'] = Mpris; -// globalThis['Network'] = Network; -globalThis['Notifications'] = Notifications; -// globalThis['SystemTray'] = SystemTray; - -const { exec } = Utils; -const SCREEN_WIDTH = Number(exec(`bash -c "xrandr --current | grep '*' | uniq | awk '{print $1}' | cut -d 'x' -f1 | head -1"`)); -const SCREEN_HEIGHT = Number(exec(`bash -c "xrandr --current | grep '*' | uniq | awk '{print $1}' | cut -d 'x' -f2 | head -1"`)); -globalThis['SCREEN_WIDTH'] = SCREEN_WIDTH; -globalThis['SCREEN_HEIGHT'] = SCREEN_HEIGHT; \ No newline at end of file diff --git a/home/desktops/hyprland/ags/js/about/about.js b/home/desktops/hyprland/ags/js/about/about.js new file mode 100644 index 0000000..b4f1877 --- /dev/null +++ b/home/desktops/hyprland/ags/js/about/about.js @@ -0,0 +1,99 @@ +import App from "resource:///com/github/Aylur/ags/app.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import PopupWindow from "../misc/PopupWindow.js"; +import icons from "../icons.js"; + +const pkg = JSON.parse(Utils.readFile(App.configDir + "/package.json")); +const show = JSON.parse( + Utils.readFile(Utils.CACHE_DIR + "/show_about") || "true", +); +const dontShow = () => + Utils.writeFile("false", Utils.CACHE_DIR + "/show_about"); +const avatar = App.configDir + "/assets/aylur.jpg"; + +/** + * @param {Object} o + * @param {string} o.label + * @param {string} o.link + */ +const LinkButton = ({ label, link }) => + Widget.Button({ + on_clicked: () => Utils.execAsync(["xdg-open", link]), + child: Widget.Box({ + children: [ + Widget.Label({ label, hexpand: true, xalign: 0 }), + Widget.Icon(icons.ui.link), + ], + }), + }); + +export default () => + PopupWindow({ + name: "about", + transition: "slide_down", + child: Widget.Box({ + vertical: true, + class_name: "window-content", + children: [ + Widget.Box({ + class_name: "avatar", + hpack: "center", + css: `background-image: url('${avatar}');`, + }), + Widget.Box({ + vertical: true, + class_name: "labels vertical", + children: [ + Widget.Label({ + class_name: "title", + label: pkg.description, + }), + Widget.Label({ + class_name: "author", + label: pkg.author, + }), + Widget.Label({ + class_name: "version", + hpack: "center", + label: pkg.version, + }), + ], + }), + Widget.Box({ + class_name: "buttons", + vertical: true, + vexpand: true, + vpack: "end", + children: [ + LinkButton({ + label: "Support me on Ko-fi", + link: pkg.kofi, + }), + LinkButton({ + label: "Report an Issue", + link: pkg.bugs.url, + }), + ], + }), + Widget.Button({ + class_name: "dont-show", + on_clicked: () => { + dontShow(); + App.toggleWindow("about"); + }, + child: Widget.Box({ + children: [ + Widget.Label("Don't show again"), + Widget.Box({ hexpand: true }), + Widget.Icon(icons.ui.close), + ], + }), + }), + ], + }), + }); + +export function showAbout(force = false) { + if (show || force) App.toggleWindow("about"); +} diff --git a/home/desktops/hyprland/ags/js/applauncher/AppItem.js b/home/desktops/hyprland/ags/js/applauncher/AppItem.js new file mode 100644 index 0000000..e607483 --- /dev/null +++ b/home/desktops/hyprland/ags/js/applauncher/AppItem.js @@ -0,0 +1,47 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import App from "resource:///com/github/Aylur/ags/app.js"; +import options from "../options.js"; +import { lookUpIcon } from "resource:///com/github/Aylur/ags/utils.js"; + +/** @param {import('resource:///com/github/Aylur/ags/service/applications.js').Application} app */ +export default (app) => { + const title = Widget.Label({ + class_name: "title", + label: app.name, + xalign: 0, + vpack: "center", + truncate: "end", + }); + + const description = Widget.Label({ + class_name: "description", + label: app.description || "", + wrap: true, + xalign: 0, + justification: "left", + vpack: "center", + }); + + const icon = Widget.Icon({ + icon: lookUpIcon(app.icon_name || "") ? app.icon_name || "" : "", + size: options.applauncher.icon_size.bind("value"), + }); + + 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: [icon, textBox], + }), + on_clicked: () => { + App.closeWindow("applauncher"); + app.launch(); + }, + }); +}; diff --git a/home/desktops/hyprland/ags/js/applauncher/Applauncher.js b/home/desktops/hyprland/ags/js/applauncher/Applauncher.js new file mode 100644 index 0000000..bc7d856 --- /dev/null +++ b/home/desktops/hyprland/ags/js/applauncher/Applauncher.js @@ -0,0 +1,89 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import App from "resource:///com/github/Aylur/ags/app.js"; +import Applications from "resource:///com/github/Aylur/ags/service/applications.js"; +import PopupWindow from "../misc/PopupWindow.js"; +import AppItem from "./AppItem.js"; +import icons from "../icons.js"; +import { launchApp } from "../utils.js"; + +const WINDOW_NAME = "applauncher"; + +const Applauncher = () => { + const mkItems = () => [ + Widget.Separator({ hexpand: true }), + ...Applications.query("").flatMap((app) => + Widget.Revealer({ + setup: (w) => (w.attribute = { app, revealer: w }), + child: Widget.Box({ + vertical: true, + children: [ + Widget.Separator({ hexpand: true }), + AppItem(app), + Widget.Separator({ hexpand: true }), + ], + }), + }), + ), + Widget.Separator({ hexpand: true }), + ]; + + let items = mkItems(); + + const list = Widget.Box({ + vertical: true, + children: items, + }); + + const entry = Widget.Entry({ + hexpand: true, + primary_icon_name: icons.apps.search, + + // set some text so on-change works the first time + text: "-", + on_accept: ({ text }) => { + const list = Applications.query(text || ""); + if (list[0]) { + App.toggleWindow(WINDOW_NAME); + launchApp(list[0]); + } + }, + on_change: ({ text }) => + items.map((item) => { + if (item.attribute) { + const { app, revealer } = item.attribute; + revealer.reveal_child = app.match(text); + } + }), + }); + + return Widget.Box({ + vertical: true, + children: [ + entry, + Widget.Scrollable({ + hscroll: "never", + child: list, + }), + ], + setup: (self) => + self.hook(App, (_, win, visible) => { + if (win !== WINDOW_NAME) return; + + entry.text = "-"; + entry.text = ""; + if (visible) { + entry.grab_focus(); + } else { + items = mkItems(); + list.children = items; + } + }), + }); +}; + +export default () => + PopupWindow({ + name: WINDOW_NAME, + transition: "slide_down", + child: Applauncher(), + }); diff --git a/home/desktops/hyprland/ags/js/bar/PanelButton.js b/home/desktops/hyprland/ags/js/bar/PanelButton.js new file mode 100644 index 0000000..b0cdc3d --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/PanelButton.js @@ -0,0 +1,45 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import App from "resource:///com/github/Aylur/ags/app.js"; + +/** + * @typedef {Object} PanelButtonProps + * @property {any} content + * @property {string=} window + */ + +/** + * @param {import('types/widgets/button').ButtonProps & PanelButtonProps} o + */ +export default ({ + class_name, + content, + window = "", + connections = [], + ...rest +}) => { + let open = false; + + const connection = [ + App, + (self, win, visible) => { + if (win !== window) return; + + if (open && !visible) { + open = false; + self.toggleClassName("active", false); + } + + if (visible) { + open = true; + self.toggleClassName("active"); + } + }, + ]; + + return Widget.Button({ + class_name: `panel-button ${class_name}`, + child: Widget.Box({ children: [content] }), + connections: connections.concat([connection]), + ...rest, + }); +}; diff --git a/home/desktops/hyprland/ags/js/bar/TopBar.js b/home/desktops/hyprland/ags/js/bar/TopBar.js new file mode 100644 index 0000000..1ac2220 --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/TopBar.js @@ -0,0 +1,117 @@ +import SystemTray from "resource:///com/github/Aylur/ags/service/systemtray.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Variable from "resource:///com/github/Aylur/ags/variable.js"; +import Notifications from "resource:///com/github/Aylur/ags/service/notifications.js"; +import Mpris from "resource:///com/github/Aylur/ags/service/mpris.js"; +import Battery from "resource:///com/github/Aylur/ags/service/battery.js"; +import OverviewButton from "./buttons/OverviewButton.js"; +import Workspaces from "./buttons/Workspaces.js"; +import FocusedClient from "./buttons/FocusedClient.js"; +import MediaIndicator from "./buttons/MediaIndicator.js"; +import DateButton from "./buttons/DateButton.js"; +import NotificationIndicator from "./buttons/NotificationIndicator.js"; +import SysTray from "./buttons/SysTray.js"; +import ColorPicker from "./buttons/ColorPicker.js"; +import SystemIndicators from "./buttons/SystemIndicators.js"; +import PowerMenu from "./buttons/PowerMenu.js"; +import ScreenRecord from "./buttons/ScreenRecord.js"; +import BatteryBar from "./buttons/BatteryBar.js"; +import SubMenu from "./buttons/SubMenu.js"; +import Recorder from "../services/screenrecord.js"; +// import * as System from './buttons/System.js'; +// import Taskbar from './buttons/Taskbar.js'; +import options from "../options.js"; + +const submenuItems = Variable(1); +SystemTray.connect("changed", () => { + submenuItems.setValue(SystemTray.items.length + 1); +}); + +/** + * @template T + * @param {T=} service + * @param {(self: T) => boolean=} condition + */ +const SeparatorDot = (service, condition) => { + const visibility = (self) => { + if (!options.bar.separators.value) return (self.visible = false); + + self.visible = + condition && service ? condition(service) : options.bar.separators.value; + }; + + const conn = service ? [[service, visibility]] : []; + return Widget.Separator({ + connections: [["draw", visibility], ...conn], + binds: [["visible", options.bar.separators]], + vpack: "center", + }); +}; + +const Start = () => + Widget.Box({ + class_name: "start", + children: [ + OverviewButton(), + SeparatorDot(), + Workspaces(), + SeparatorDot(), + FocusedClient(), + Widget.Box({ hexpand: true }), + NotificationIndicator(), + SeparatorDot(Notifications, (n) => n.notifications.length > 0 || n.dnd), + ], + }); + +const Center = () => + Widget.Box({ + class_name: "center", + children: [DateButton()], + }); + +const End = () => + Widget.Box({ + class_name: "end", + children: [ + SeparatorDot(Mpris, (m) => m.players.length > 0), + MediaIndicator(), + Widget.Box({ hexpand: true }), + + SubMenu({ + items: submenuItems, + children: [SysTray(), ColorPicker()], + }), + + SeparatorDot(), + ScreenRecord(), + SeparatorDot(Recorder, (r) => r.recording), + SystemIndicators(), + SeparatorDot(Battery, (b) => b.available), + BatteryBar(), + SeparatorDot(), + PowerMenu(), + ], + }); + +/** @param {number} monitor */ +export default (monitor) => + Widget.Window({ + name: `bar${monitor}`, + class_name: "transparent", + exclusivity: "exclusive", + monitor, + binds: [ + [ + "anchor", + options.bar.position, + "value", + (pos) => [pos, "left", "right"], + ], + ], + child: Widget.CenterBox({ + class_name: "panel", + start_widget: Start(), + center_widget: Center(), + end_widget: End(), + }), + }); diff --git a/home/desktops/hyprland/ags/js/bar/buttons/BatteryBar.js b/home/desktops/hyprland/ags/js/bar/buttons/BatteryBar.js new file mode 100644 index 0000000..99b25b8 --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/buttons/BatteryBar.js @@ -0,0 +1,108 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Battery from "resource:///com/github/Aylur/ags/service/battery.js"; +import icons from "../../icons.js"; +import FontIcon from "../../misc/FontIcon.js"; +import options from "../../options.js"; +import PanelButton from "../PanelButton.js"; + +const Indicator = () => + Widget.Stack({ + items: [ + ["false", Widget.Icon({ binds: [["icon", Battery, "icon-name"]] })], + ["true", FontIcon(icons.battery.charging)], + ], + binds: [["visible", options.battery.bar.show_icon]], + connections: [ + [ + Battery, + (stack) => { + stack.shown = `${Battery.charging || Battery.charged}`; + }, + ], + ], + }); + +const PercentLabel = () => + Widget.Revealer({ + transition: "slide_right", + binds: [["reveal-child", options.battery.show_percentage]], + child: Widget.Label({ + binds: [["label", Battery, "percent", (p) => `${p}%`]], + }), + }); + +const LevelBar = () => + Widget.LevelBar({ + connections: [ + [ + options.battery.bar.full, + (self) => { + const full = options.battery.bar.full.value; + self.vpack = full ? "fill" : "center"; + self.hpack = full ? "fill" : "center"; + }, + ], + ], + binds: [["value", Battery, "percent", (p) => p / 100]], + }); + +const WholeButton = () => + Widget.Overlay({ + class_name: "whole-button", + child: LevelBar(), + pass_through: true, + overlays: [ + Widget.Box({ + hpack: "center", + children: [ + FontIcon({ + icon: icons.battery.charging, + binds: [["visible", Battery, "charging"]], + }), + Widget.Box({ + hpack: "center", + vpack: "center", + child: PercentLabel(), + }), + ], + }), + ], + }); + +export default () => + PanelButton({ + class_name: "battery-bar", + on_clicked: () => { + const v = options.battery.show_percentage.value; + options.battery.show_percentage.value = !v; + }, + content: Widget.Box({ + connections: [ + [ + Battery, + (w) => { + w.toggleClassName("charging", Battery.charging || Battery.charged); + w.toggleClassName( + "medium", + Battery.percent < options.battery.medium.value, + ); + w.toggleClassName( + "low", + Battery.percent < options.battery.low.value, + ); + w.toggleClassName("half", Battery.percent < 48); + }, + ], + ], + binds: [ + ["visible", Battery, "available"], + [ + "children", + options.battery.bar.full, + "value", + (full) => + full ? [WholeButton()] : [Indicator(), PercentLabel(), LevelBar()], + ], + ], + }), + }); diff --git a/home/desktops/hyprland/ags/js/bar/buttons/ColorPicker.js b/home/desktops/hyprland/ags/js/bar/buttons/ColorPicker.js new file mode 100644 index 0000000..3b8f211 --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/buttons/ColorPicker.js @@ -0,0 +1,27 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Colors from "../../services/colorpicker.js"; +import PanelButton from "../PanelButton.js"; +import Gdk from "gi://Gdk"; + +export default () => + PanelButton({ + class_name: "color-picker", + content: Widget.Icon("color-select-symbolic"), + binds: [["tooltip-text", Colors, "colors", (v) => `${v.length} colors`]], + on_clicked: () => Colors.pick(), + + on_secondary_click: (btn) => { + if (Colors.colors.length === 0) return; + + Widget.Menu({ + class_name: "colorpicker", + children: Colors.colors.map((color) => + Widget.MenuItem({ + child: Widget.Label(color), + css: `background-color: ${color}`, + on_activate: () => Colors.wlCopy(color), + }), + ), + }).popup_at_widget(btn, Gdk.Gravity.SOUTH, Gdk.Gravity.NORTH, null); + }, + }); diff --git a/home/desktops/hyprland/ags/js/bar/buttons/DateButton.js b/home/desktops/hyprland/ags/js/bar/buttons/DateButton.js new file mode 100644 index 0000000..0413767 --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/buttons/DateButton.js @@ -0,0 +1,11 @@ +import App from "resource:///com/github/Aylur/ags/app.js"; +import Clock from "../../misc/Clock.js"; +import PanelButton from "../PanelButton.js"; + +export default ({ format = "%H:%M - %A %e." } = {}) => + PanelButton({ + class_name: "dashboard panel-button", + on_clicked: () => App.toggleWindow("dashboard"), + window: "dashboard", + content: Clock({ format }), + }); diff --git a/home/desktops/hyprland/ags/js/bar/buttons/FocusedClient.js b/home/desktops/hyprland/ags/js/bar/buttons/FocusedClient.js new file mode 100644 index 0000000..39423d9 --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/buttons/FocusedClient.js @@ -0,0 +1,55 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Hyprland from "resource:///com/github/Aylur/ags/service/hyprland.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import PanelButton from "../PanelButton.js"; +import options from "../../options.js"; +import { substitute } from "../../utils.js"; + +export const ClientLabel = () => + Widget.Label({ + binds: [ + [ + "label", + Hyprland.active.client, + "class", + (c) => { + const { titles } = options.substitutions; + return substitute(titles, c); + }, + ], + ], + }); + +export const ClientIcon = () => + Widget.Icon({ + connections: [ + [ + Hyprland.active.client, + (self) => { + const { icons } = options.substitutions; + const { client } = Hyprland.active; + + const classIcon = substitute(icons, client.class) + "-symbolic"; + const titleIcon = substitute(icons, client.class) + "-symbolic"; + + const hasTitleIcon = Utils.lookUpIcon(titleIcon); + const hasClassIcon = Utils.lookUpIcon(classIcon); + + if (hasClassIcon) self.icon = classIcon; + + if (hasTitleIcon) self.icon = titleIcon; + + self.visible = !!(hasTitleIcon || hasClassIcon); + }, + ], + ], + }); + +export default () => + PanelButton({ + class_name: "focused-client", + content: Widget.Box({ + children: [ClientIcon(), ClientLabel()], + binds: [["tooltip-text", Hyprland.active, "client", (c) => c.title]], + }), + }); diff --git a/home/desktops/hyprland/ags/js/bar/buttons/MediaIndicator.js b/home/desktops/hyprland/ags/js/bar/buttons/MediaIndicator.js new file mode 100644 index 0000000..16e9488 --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/buttons/MediaIndicator.js @@ -0,0 +1,84 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Mpris from "resource:///com/github/Aylur/ags/service/mpris.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import HoverRevealer from "../../misc/HoverRevealer.js"; +import * as mpris from "../../misc/mpris.js"; +import options from "../../options.js"; + +export const getPlayer = (name = options.mpris.preferred.value) => + Mpris.getPlayer(name) || Mpris.players[0] || null; + +/** + * @param {Object} o + * @param {import('types/service/mpris').MprisPlayer} o.player + * @param {import('../../misc/HoverRevealer').HoverRevealProps['direction']=} o.direction + */ +const Indicator = ({ player, direction = "right" }) => + HoverRevealer({ + class_name: `media panel-button ${player.name}`, + direction, + on_primary_click: () => player.playPause(), + on_scroll_up: () => player.next(), + on_scroll_down: () => player.previous(), + on_secondary_click: () => player.playPause(), + indicator: mpris.PlayerIcon(player), + child: Widget.Label({ + vexpand: true, + truncate: "end", + max_width_chars: 40, + connections: [ + [ + player, + (label) => { + label.label = `${player.track_artists.join(", ")} - ${ + player.track_title + }`; + }, + ], + ], + }), + connections: [ + [ + player, + (revealer) => { + if (revealer._current === player.track_title) return; + + revealer._current = player.track_title; + revealer.reveal_child = true; + Utils.timeout(3000, () => { + revealer.reveal_child = false; + }); + }, + ], + ], + }); + +/** + * @param {Object} o + * @param {import('../../misc/HoverRevealer').HoverRevealProps['direction']=} o.direction + */ +export default ({ direction = "right" } = {}) => { + let current = null; + + const update = (box) => { + const player = getPlayer(); + box.visible = !!player; + + if (!player) { + current = null; + return; + } + + if (current === player) return; + + current = player; + box.children = [Indicator({ player, direction })]; + }; + + return Widget.Box({ + connections: [ + [options.mpris.preferred, update], + [Mpris, update, "notify::players"], + ], + }); +}; diff --git a/home/desktops/hyprland/ags/js/bar/buttons/NotificationIndicator.js b/home/desktops/hyprland/ags/js/bar/buttons/NotificationIndicator.js new file mode 100644 index 0000000..89c8ffd --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/buttons/NotificationIndicator.js @@ -0,0 +1,63 @@ +import App from "resource:///com/github/Aylur/ags/app.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Notifications from "resource:///com/github/Aylur/ags/service/notifications.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import icons from "../../icons.js"; +import HoverRevealer from "../../misc/HoverRevealer.js"; + +/** + * @param {Object} o + * @param {import('../../misc/HoverRevealer').HoverRevealProps['direction']=} o.direction + */ +export default ({ direction = "left" } = {}) => + HoverRevealer({ + class_name: "notifications panel-button", + eventboxConnections: [ + ["button-press-event", () => App.openWindow("dashboard")], + [ + Notifications, + (box) => + (box.visible = + Notifications.notifications.length > 0 || Notifications.dnd), + ], + ], + connections: [ + [ + Notifications, + (revealer) => { + const title = Notifications.notifications[0]?.summary; + if (revealer._title === title) return; + + revealer._title = title; + revealer.reveal_child = true; + Utils.timeout(3000, () => { + revealer.reveal_child = false; + }); + }, + ], + ], + direction, + indicator: Widget.Icon({ + binds: [ + [ + "icon", + Notifications, + "dnd", + (dnd) => + dnd ? icons.notifications.silent : icons.notifications.noisy, + ], + ], + }), + child: Widget.Label({ + truncate: "end", + max_width_chars: 40, + binds: [ + [ + "label", + Notifications, + "notifications", + (n) => n.reverse()[0]?.summary || "", + ], + ], + }), + }); diff --git a/home/desktops/hyprland/ags/js/bar/buttons/OverviewButton.js b/home/desktops/hyprland/ags/js/bar/buttons/OverviewButton.js new file mode 100644 index 0000000..bc7e784 --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/buttons/OverviewButton.js @@ -0,0 +1,24 @@ +import App from "resource:///com/github/Aylur/ags/app.js"; +import PanelButton from "../PanelButton.js"; +import FontIcon from "../../misc/FontIcon.js"; +import { distroIcon } from "../../variables.js"; +import options from "../../options.js"; + +export default () => + PanelButton({ + class_name: "overview", + window: "overview", + on_clicked: () => App.toggleWindow("overview"), + content: FontIcon({ + binds: [ + [ + "icon", + options.bar.icon, + "value", + (v) => { + return v === "distro-icon" ? distroIcon : v; + }, + ], + ], + }), + }); diff --git a/home/desktops/hyprland/ags/js/bar/buttons/PowerMenu.js b/home/desktops/hyprland/ags/js/bar/buttons/PowerMenu.js new file mode 100644 index 0000000..dc7b9cc --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/buttons/PowerMenu.js @@ -0,0 +1,11 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import App from "resource:///com/github/Aylur/ags/app.js"; +import icons from "../../icons.js"; +import PanelButton from "../PanelButton.js"; + +export default () => + PanelButton({ + class_name: "powermenu", + content: Widget.Icon(icons.powermenu.shutdown), + on_clicked: () => App.openWindow("powermenu"), + }); diff --git a/home/desktops/hyprland/ags/js/bar/buttons/ScreenRecord.js b/home/desktops/hyprland/ags/js/bar/buttons/ScreenRecord.js new file mode 100644 index 0000000..26b54cc --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/buttons/ScreenRecord.js @@ -0,0 +1,30 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import PanelButton from "../PanelButton.js"; +import Recorder from "../../services/screenrecord.js"; +import icons from "../../icons.js"; + +export default () => + PanelButton({ + class_name: "recorder", + on_clicked: () => Recorder.stop(), + binds: [["visible", Recorder, "recording"]], + content: Widget.Box({ + children: [ + Widget.Icon(icons.recorder.recording), + Widget.Label({ + binds: [ + [ + "label", + Recorder, + "timer", + (time) => { + const sec = time % 60; + const min = Math.floor(time / 60); + return `${min}:${sec < 10 ? "0" + sec : sec}`; + }, + ], + ], + }), + ], + }), + }); diff --git a/home/desktops/hyprland/ags/js/bar/buttons/SubMenu.js b/home/desktops/hyprland/ags/js/bar/buttons/SubMenu.js new file mode 100644 index 0000000..372d0fc --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/buttons/SubMenu.js @@ -0,0 +1,72 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import Variable from "resource:///com/github/Aylur/ags/variable.js"; +import icons from "../../icons.js"; +import options from "../../options.js"; + +/** + * @param {import('types/widgets/revealer').default} revealer + * @param {'left' | 'right' | 'up' | 'down'} direction + * @param {import('types/variable').Variable} items + */ +const Arrow = (revealer, direction, items) => { + let deg = 0; + + const icon = Widget.Icon({ + icon: icons.ui.arrow[direction], + }); + + const animate = () => { + const t = options.transition.value / 20; + const step = revealer.reveal_child ? 10 : -10; + for (let i = 0; i < 18; ++i) { + Utils.timeout(t * i, () => { + deg += step; + icon.setCss(`-gtk-icon-transform: rotate(${deg}deg);`); + }); + } + }; + + return Widget.Button({ + class_name: "panel-button sub-menu", + connections: [ + [ + items, + (btn) => { + btn.tooltip_text = `${items.value} Items`; + }, + ], + ], + on_clicked: () => { + animate(); + revealer.reveal_child = !revealer.reveal_child; + }, + child: icon, + }); +}; + +/** + * @param {Object} o + * @param {import('types/widgets/box').default['children']} o.children + * @param {'left' | 'right' | 'up' | 'down'=} o.direction + * @param {import('types/variable').Variable} o.items + */ +export default ({ children, direction = "left", items = Variable(0) }) => { + const posStart = direction === "up" || direction === "left"; + const posEnd = direction === "down" || direction === "right"; + const revealer = Widget.Revealer({ + transition: `slide_${direction}`, + child: Widget.Box({ + children, + }), + }); + + return Widget.Box({ + vertical: direction === "up" || direction === "down", + children: [ + posStart && revealer, + Arrow(revealer, direction, items), + posEnd && revealer, + ], + }); +}; diff --git a/home/desktops/hyprland/ags/js/bar/buttons/SysTray.js b/home/desktops/hyprland/ags/js/bar/buttons/SysTray.js new file mode 100644 index 0000000..ee248c4 --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/buttons/SysTray.js @@ -0,0 +1,44 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import SystemTray from "resource:///com/github/Aylur/ags/service/systemtray.js"; +import PanelButton from "../PanelButton.js"; +import Gdk from "gi://Gdk"; + +/** @param {import('types/service/systemtray').TrayItem} item */ +const SysTrayItem = (item) => + PanelButton({ + class_name: "tray-item", + content: Widget.Icon({ icon: item.bind("icon") }), + tooltip_markup: item.bind("tooltip_markup"), + setup: (self) => { + const id = item.menu?.connect("popped-up", (menu) => { + self.toggleClassName("active"); + menu.connect("notify::visible", (menu) => { + self.toggleClassName("active", menu.visible); + }); + menu.disconnect(id); + }); + + if (id) self.connect("destroy", () => item.menu?.disconnect(id)); + }, + + // @ts-expect-error popup_at_widget missing from types? + on_primary_click: (btn) => + item.menu?.popup_at_widget( + btn, + Gdk.Gravity.SOUTH, + Gdk.Gravity.NORTH, + null, + ), + + // @ts-expect-error popup_at_widget missing from types? + on_secondary_click: (btn) => + item.menu?.popup_at_widget( + btn, + Gdk.Gravity.SOUTH, + Gdk.Gravity.NORTH, + null, + ), + }); + +export default () => + Widget.Box().bind("children", SystemTray, "items", (i) => i.map(SysTrayItem)); diff --git a/home/desktops/hyprland/ags/js/bar/buttons/System.js b/home/desktops/hyprland/ags/js/bar/buttons/System.js new file mode 100644 index 0000000..4feb2f3 --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/buttons/System.js @@ -0,0 +1,57 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import PanelButton from "../PanelButton.js"; +import * as variables from "../../variables.js"; +import icons from "../../icons.js"; + +/** @param {'cpu' | 'ram'} type */ +const System = (type) => { + const icon = Widget.Icon({ + class_name: "icon", + icon: icons.system[type], + }); + + const progress = Widget.Box({ + class_name: "progress", + child: Widget.CircularProgress({ + binds: [["value", variables[type]]], + }), + }); + + const revealer = Widget.Revealer({ + transition: "slide_right", + child: Widget.Label({ + binds: [ + [ + "label", + variables[type], + "value", + (v) => { + return ` ${type}: ${Math.round(v * 100)}%`; + }, + ], + ], + }), + }); + + return PanelButton({ + class_name: `system ${type}`, + on_clicked: () => (revealer.reveal_child = !revealer.reveal_child), + content: Widget.EventBox({ + on_hover: () => (revealer.reveal_child = true), + on_hover_lost: () => (revealer.reveal_child = false), + child: Widget.Box({ + children: [ + icon, + Widget.Box({ + class_name: "revealer", + child: revealer, + }), + progress, + ], + }), + }), + }); +}; + +export const CPU = () => System("cpu"); +export const RAM = () => System("ram"); diff --git a/home/desktops/hyprland/ags/js/bar/buttons/SystemIndicators.js b/home/desktops/hyprland/ags/js/bar/buttons/SystemIndicators.js new file mode 100644 index 0000000..b1a1f24 --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/buttons/SystemIndicators.js @@ -0,0 +1,135 @@ +import App from "resource:///com/github/Aylur/ags/app.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Notifications from "resource:///com/github/Aylur/ags/service/notifications.js"; +import Bluetooth from "resource:///com/github/Aylur/ags/service/bluetooth.js"; +import Audio from "resource:///com/github/Aylur/ags/service/audio.js"; +import Network from "resource:///com/github/Aylur/ags/service/network.js"; +import HoverRevealer from "../../misc/HoverRevealer.js"; +import PanelButton from "../PanelButton.js"; +import Asusctl from "../../services/asusctl.js"; +import Indicator from "../../services/onScreenIndicator.js"; +import icons from "../../icons.js"; +import FontIcon from "../../misc/FontIcon.js"; + +const ProfileIndicator = () => + Widget.Icon() + .bind("visible", Asusctl, "profile", (p) => p !== "Balanced") + .bind("icon", Asusctl, "profile", (i) => icons.asusctl.profile[i]); + +const ModeIndicator = () => + FontIcon() + .bind("visible", Asusctl, "mode", (m) => m !== "Hybrid") + .bind("icon", Asusctl, "mode", (i) => icons.asusctl.mode[i]); + +const MicrophoneIndicator = () => + Widget.Icon().hook( + Audio, + (icon) => { + if (!Audio.microphone) return; + + const { muted, low, medium, high } = icons.audio.mic; + if (Audio.microphone.is_muted) return (icon.icon = muted); + + /** @type {Array<[number, string]>} */ + const cons = [ + [67, high], + [34, medium], + [1, low], + [0, muted], + ]; + icon.icon = + cons.find(([n]) => n <= Audio.microphone.volume * 100)?.[1] || ""; + + icon.visible = Audio.recorders.length > 0 || Audio.microphone.is_muted; + }, + "speaker-changed", + ); + +const DNDIndicator = () => + Widget.Icon({ + visible: Notifications.bind("dnd"), + icon: icons.notifications.silent, + }); + +const BluetoothDevicesIndicator = () => + Widget.Box().hook( + Bluetooth, + (box) => { + box.children = Bluetooth.connectedDevices.map(({ iconName, name }) => + HoverRevealer({ + indicator: Widget.Icon(iconName + "-symbolic"), + child: Widget.Label(name), + }), + ); + + box.visible = Bluetooth.connectedDevices.length > 0; + }, + "notify::connected-devices", + ); + +const BluetoothIndicator = () => + Widget.Icon({ + class_name: "bluetooth", + icon: icons.bluetooth.enabled, + visible: Bluetooth.bind("enabled"), + }); + +const NetworkIndicator = () => + Widget.Icon().hook(Network, (self) => { + const icon = Network[Network.primary || "wifi"]?.iconName; + self.icon = icon || ""; + self.visible = !!icon; + }); + +const AudioIndicator = () => + Widget.Icon().hook( + Audio, + (self) => { + if (!Audio.speaker) return; + + const { muted, low, medium, high, overamplified } = icons.audio.volume; + if (Audio.speaker.is_muted) return (self.icon = muted); + + /** @type {Array<[number, string]>} */ + const cons = [ + [101, overamplified], + [67, high], + [34, medium], + [1, low], + [0, muted], + ]; + self.icon = + cons.find(([n]) => n <= Audio.speaker.volume * 100)?.[1] || ""; + }, + "speaker-changed", + ); + +export default () => + PanelButton({ + class_name: "quicksettings panel-button", + on_clicked: () => App.toggleWindow("quicksettings"), + setup: (self) => + self.hook(App, (_, win, visible) => { + self.toggleClassName("active", win === "quicksettings" && visible); + }), + on_scroll_up: () => { + Audio.speaker.volume += 0.02; + Indicator.speaker(); + }, + on_scroll_down: () => { + Audio.speaker.volume -= 0.02; + Indicator.speaker(); + }, + content: Widget.Box({ + children: [ + Asusctl?.available && ProfileIndicator(), + Asusctl?.available && ModeIndicator(), + DNDIndicator(), + BluetoothDevicesIndicator(), + BluetoothIndicator(), + NetworkIndicator(), + AudioIndicator(), + MicrophoneIndicator(), + ], + }), + }); diff --git a/home/desktops/hyprland/ags/js/bar/buttons/Taskbar.js b/home/desktops/hyprland/ags/js/bar/buttons/Taskbar.js new file mode 100644 index 0000000..dd447ea --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/buttons/Taskbar.js @@ -0,0 +1,34 @@ +import Hyprland from "resource:///com/github/Aylur/ags/service/hyprland.js"; +import Applications from "resource:///com/github/Aylur/ags/service/applications.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import PanelButton from "../PanelButton.js"; +import { launchApp } from "../../utils.js"; +import icons from "../../icons.js"; + +const focus = ({ address }) => + Hyprland.sendMessage(`dispatch focuswindow address:${address}`); + +/** @param {import('types/widgets/box').default} box */ +const setChildren = (box) => + (box.children = Hyprland.clients.map((client) => { + if (Hyprland.active.workspace.id !== client.workspace.id) return; + + for (const app of Applications.list) { + if (client.class && app.match(client.class)) { + return PanelButton({ + content: Widget.Icon(app.icon_name || icons.fallback.executable), + tooltip_text: app.name, + on_primary_click: () => focus(client), + on_middle_click: () => launchApp(app), + }); + } + } + })); + +export default () => + Widget.Box({ + connections: [ + [Hyprland, setChildren, "notify::clients"], + [Hyprland, setChildren, "notify::active"], + ], + }); diff --git a/home/desktops/hyprland/ags/js/bar/buttons/Workspaces.js b/home/desktops/hyprland/ags/js/bar/buttons/Workspaces.js new file mode 100644 index 0000000..195f1a7 --- /dev/null +++ b/home/desktops/hyprland/ags/js/bar/buttons/Workspaces.js @@ -0,0 +1,64 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Hyprland from "resource:///com/github/Aylur/ags/service/hyprland.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import options from "../../options.js"; +import { range } from "../../utils.js"; + +/** @param {any} arg */ +const dispatch = (arg) => Utils.execAsync(`hyprctl dispatch workspace ${arg}`); + +const Workspaces = () => { + const ws = options.workspaces.value; + return Widget.Box({ + children: range(ws || 20).map((i) => + Widget.Button({ + setup: (btn) => (btn.id = i), + on_clicked: () => dispatch(i), + child: Widget.Label({ + label: `${i}`, + class_name: "indicator", + vpack: "center", + }), + connections: [ + [ + Hyprland, + (btn) => { + btn.toggleClassName("active", Hyprland.active.workspace.id === i); + btn.toggleClassName( + "occupied", + Hyprland.getWorkspace(i)?.windows > 0, + ); + }, + ], + ], + }), + ), + connections: ws + ? [] + : [ + [ + Hyprland.active.workspace, + (box) => + box.children.map((btn) => { + btn.visible = Hyprland.workspaces.some( + (ws) => ws.id === btn.id, + ); + }), + ], + ], + }); +}; + +export default () => + Widget.EventBox({ + class_name: "workspaces panel-button", + child: Widget.Box({ + // its nested like this to keep it consistent with other PanelButton widgets + child: Widget.EventBox({ + on_scroll_up: () => dispatch("m+1"), + on_scroll_down: () => dispatch("m-1"), + class_name: "eventbox", + binds: [["child", options.workspaces, "value", Workspaces]], + }), + }), + }); diff --git a/home/desktops/hyprland/ags/js/dashboard/Dashboard.js b/home/desktops/hyprland/ags/js/dashboard/Dashboard.js new file mode 100644 index 0000000..3d22305 --- /dev/null +++ b/home/desktops/hyprland/ags/js/dashboard/Dashboard.js @@ -0,0 +1,30 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import DateColumn from "./DateColumn.js"; +import NotificationColumn from "./NotificationColumn.js"; +import PopupWindow from "../misc/PopupWindow.js"; +import options from "../options.js"; + +export default () => + PopupWindow({ + name: "dashboard", + connections: [ + [ + options.bar.position, + (self) => { + self.anchor = [options.bar.position.value]; + if (options.bar.position.value === "top") + self.transition = "slide_down"; + + if (options.bar.position.value === "bottom") + self.transition = "slide_up"; + }, + ], + ], + child: Widget.Box({ + children: [ + NotificationColumn(), + Widget.Separator({ orientation: 1 }), + DateColumn(), + ], + }), + }); diff --git a/home/desktops/hyprland/ags/js/dashboard/DateColumn.js b/home/desktops/hyprland/ags/js/dashboard/DateColumn.js new file mode 100644 index 0000000..0a1c819 --- /dev/null +++ b/home/desktops/hyprland/ags/js/dashboard/DateColumn.js @@ -0,0 +1,70 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import icons from "../icons.js"; +import Clock from "../misc/Clock.js"; +import * as vars from "../variables.js"; +import options from "../options.js"; + +/** + * @param {'cpu' | 'ram' | 'temp'} type + * @param {string} title + * @param {string} unit + */ +const SysProgress = (type, title, unit) => + Widget.Box({ + class_name: `circular-progress-box ${type}`, + hexpand: true, + binds: [ + [ + "tooltipText", + vars[type], + "value", + (v) => `${title}: ${Math.floor(v * 100)}${unit}`, + ], + ], + child: Widget.CircularProgress({ + hexpand: true, + class_name: `circular-progress ${type}`, + child: Widget.Icon(icons.system[type]), + start_at: 0.75, + binds: [ + ["value", vars[type]], + ["rounded", options.radii, "value", (v) => v > 0], + ], + }), + }); + +export default () => + Widget.Box({ + vertical: true, + class_name: "datemenu vertical", + children: [ + Widget.Box({ + class_name: "clock-box", + vertical: true, + children: [ + Clock({ format: "%H:%M" }), + Widget.Label({ + class_name: "uptime", + binds: [["label", vars.uptime, "value", (t) => `uptime: ${t}`]], + }), + ], + }), + Widget.Box({ + class_name: "calendar", + children: [ + Widget.Calendar({ + hexpand: true, + hpack: "center", + }), + ], + }), + Widget.Box({ + class_name: "system-info horizontal", + children: [ + SysProgress("cpu", "Cpu", "%"), + SysProgress("ram", "Ram", "%"), + SysProgress("temp", "Temperature", "°"), + ], + }), + ], + }); diff --git a/home/desktops/hyprland/ags/js/dashboard/NotificationColumn.js b/home/desktops/hyprland/ags/js/dashboard/NotificationColumn.js new file mode 100644 index 0000000..accf0b4 --- /dev/null +++ b/home/desktops/hyprland/ags/js/dashboard/NotificationColumn.js @@ -0,0 +1,90 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Notifications from "resource:///com/github/Aylur/ags/service/notifications.js"; +import icons from "../icons.js"; +import Notification from "../misc/Notification.js"; +import { timeout } from "resource:///com/github/Aylur/ags/utils.js"; + +const ClearButton = () => + Widget.Button({ + on_clicked: () => { + const list = Array.from(Notifications.notifications); + for (let i = 0; i < list.length; i++) + timeout(50 * i, () => list[i]?.close()); + }, + binds: [["sensitive", Notifications, "notifications", (n) => n.length > 0]], + child: Widget.Box({ + children: [ + Widget.Label("Clear "), + Widget.Icon({ + binds: [ + [ + "icon", + Notifications, + "notifications", + (n) => (n.length > 0 ? icons.trash.full : icons.trash.empty), + ], + ], + }), + ], + }), + }); + +const Header = () => + Widget.Box({ + class_name: "header", + children: [ + Widget.Label({ label: "Notifications", hexpand: true, xalign: 0 }), + ClearButton(), + ], + }); + +const NotificationList = () => + Widget.Box({ + vertical: true, + vexpand: true, + connections: [ + [ + Notifications, + (box) => { + box.children = Notifications.notifications + .reverse() + .map(Notification); + + box.visible = Notifications.notifications.length > 0; + }, + ], + ], + }); + +const Placeholder = () => + Widget.Box({ + class_name: "placeholder", + vertical: true, + vpack: "center", + hpack: "center", + vexpand: true, + hexpand: true, + children: [ + Widget.Icon(icons.notifications.silent), + Widget.Label("Your inbox is empty"), + ], + binds: [["visible", Notifications, "notifications", (n) => n.length === 0]], + }); + +export default () => + Widget.Box({ + class_name: "notifications", + vertical: true, + children: [ + Header(), + Widget.Scrollable({ + vexpand: true, + class_name: "notification-scrollable", + child: Widget.Box({ + class_name: "notification-list", + vertical: true, + children: [NotificationList(), Placeholder()], + }), + }), + ], + }); diff --git a/home/desktops/hyprland/ags/js/desktop/Desktop.js b/home/desktops/hyprland/ags/js/desktop/Desktop.js new file mode 100644 index 0000000..198ed1d --- /dev/null +++ b/home/desktops/hyprland/ags/js/desktop/Desktop.js @@ -0,0 +1,74 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Clock from "../misc/Clock.js"; +import DesktopMenu from "./DesktopMenu.js"; +import options from "../options.js"; + +const DesktopClock = () => + Widget.Box({ + class_name: "clock-box-shadow", + child: Widget.CenterBox({ + class_name: "clock-box", + children: [ + Clock({ + class_name: "clock", + hpack: "center", + format: "%H", + }), + Widget.Box({ + class_name: "separator-box", + vertical: true, + hexpand: true, + hpack: "center", + children: [ + Widget.Separator({ vpack: "center", vexpand: true }), + Widget.Separator({ vpack: "center", vexpand: true }), + ], + }), + Clock({ + class_name: "clock", + hpack: "center", + format: "%M", + }), + ], + }), + }); + +const Desktop = () => + Widget.EventBox({ + on_secondary_click: (_, event) => DesktopMenu().popup_at_pointer(event), + child: Widget.Box({ + vertical: true, + vexpand: true, + hexpand: true, + binds: [["visible", options.desktop.clock.enable]], + connections: [ + [ + options.desktop.clock.position, + (box) => { + const [hpack = "center", vpack = "center", offset = 64] = + options.desktop.clock.position.value.split(" ") || []; + + // @ts-expect-error + box.hpack = hpack; + box.vpack = vpack; + box.setCss(`margin: ${Number(offset)}px;`); + }, + ], + ], + children: [ + DesktopClock(), + Clock({ format: "%B %e. %A", class_name: "date" }), + ], + }), + }); + +/** @param {number} monitor */ +export default (monitor) => + Widget.Window({ + monitor, + name: `desktop${monitor}`, + layer: "background", + class_name: "desktop", + anchor: ["top", "bottom", "left", "right"], + child: Desktop(), + }); diff --git a/home/desktops/hyprland/ags/js/desktop/DesktopMenu.js b/home/desktops/hyprland/ags/js/desktop/DesktopMenu.js new file mode 100644 index 0000000..e77b919 --- /dev/null +++ b/home/desktops/hyprland/ags/js/desktop/DesktopMenu.js @@ -0,0 +1,66 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import App from "resource:///com/github/Aylur/ags/app.js"; +import PowerMenu from "../services/powermenu.js"; +import icons from "../icons.js"; +import Gtk from "gi://Gtk"; +import { openSettings } from "../settings/theme.js"; + +/** + * @param {string} label + * @param {string} icon + * @param {import('types/widgets/menu').MenuItemProps['on_activate']} on_activate + */ +const Item = (label, icon, on_activate) => + Widget.MenuItem({ + on_activate, + child: Widget.Box({ + children: [ + Widget.Icon(icon), + Widget.Label({ + label, + hexpand: true, + xalign: 0, + }), + ], + }), + }); + +export default () => + Widget.Menu({ + class_name: "desktop-menu", + children: [ + Widget.MenuItem({ + child: Widget.Box({ + children: [ + Widget.Icon(icons.powermenu.shutdown), + Widget.Label({ + label: "System", + hexpand: true, + xalign: 0, + }), + ], + }), + submenu: Widget.Menu({ + children: [ + Item("Shutdown", icons.powermenu.shutdown, () => + PowerMenu.action("shutdown"), + ), + Item("Log Out", icons.powermenu.logout, () => + PowerMenu.action("logout"), + ), + Item("Reboot", icons.powermenu.reboot, () => + PowerMenu.action("reboot"), + ), + Item("Sleep", icons.powermenu.sleep, () => + PowerMenu.action("reboot"), + ), + ], + }), + }), + Item("Applications", icons.apps.apps, () => + App.openWindow("applauncher"), + ), + new Gtk.SeparatorMenuItem(), + Item("Settings", icons.ui.settings, openSettings), + ], + }); diff --git a/home/desktops/hyprland/ags/js/dock/Dock.js b/home/desktops/hyprland/ags/js/dock/Dock.js new file mode 100644 index 0000000..44410e1 --- /dev/null +++ b/home/desktops/hyprland/ags/js/dock/Dock.js @@ -0,0 +1,155 @@ +import App from "resource:///com/github/Aylur/ags/app.js"; +import Hyprland from "resource:///com/github/Aylur/ags/service/hyprland.js"; +import Applications from "resource:///com/github/Aylur/ags/service/applications.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import icons from "../icons.js"; +import options from "../options.js"; +import { launchApp, range } from "../utils.js"; + +const focus = ({ address }) => + Hyprland.sendMessage(`dispatch focuswindow address:${address}`); + +/** @param {import('types/widgets/button').ButtonProps & { icon: string, pinned?: boolean }} o */ +const AppButton = ({ icon, pinned = false, ...rest }) => { + const indicators = Widget.Box({ + vpack: "end", + hpack: "center", + children: range(5, 0).map(() => + Widget.Box({ + class_name: "indicator", + visible: false, + }), + ), + }); + + const button = Widget.Button({ + ...rest, + child: Widget.Box({ + class_name: "box", + child: Widget.Overlay({ + child: Widget.Icon({ + icon, + binds: [["size", options.desktop.dock.icon_size]], + }), + pass_through: true, + overlays: pinned ? [indicators] : [], + }), + }), + }); + + return Object.assign(button, { indicators }); +}; + +const Taskbar = () => + Widget.Box({ + binds: [ + [ + "children", + Hyprland, + "clients", + (c) => + c.map((client) => { + for (const appName of options.desktop.dock.pinned_apps.value) { + if (client.class.toLowerCase().includes(appName.toLowerCase())) + return null; + } + for (const app of Applications.list) { + if ( + (client.title && app.match(client.title)) || + (client.class && app.match(client.class)) + ) { + return AppButton({ + icon: app.icon_name || "", + tooltip_text: app.name, + on_primary_click: () => focus(client), + on_middle_click: () => launchApp(app), + }); + } + } + }), + ], + ], + }); + +const PinnedApps = () => + Widget.Box({ + class_name: "pins", + homogeneous: true, + binds: [ + [ + "children", + options.desktop.dock.pinned_apps, + "value", + (v) => + v + .map((term) => ({ app: Applications.query(term)?.[0], term })) + .filter(({ app }) => app) + .map(({ app, term = true }) => + AppButton({ + pinned: true, + icon: app.icon_name || "", + on_primary_click: () => { + for (const client of Hyprland.clients) { + if (client.class.toLowerCase().includes(term)) + return focus(client); + } + + launchApp(app); + }, + on_middle_click: () => launchApp(app), + tooltip_text: app.name, + connections: [ + [ + Hyprland, + (button) => { + const running = Hyprland.clients.filter((client) => + client.class.toLowerCase().includes(term), + ); + + const focused = running.find( + (client) => + client.address === Hyprland.active.client.address, + ); + + const index = running.findIndex((c) => c === focused); + + for (let i = 0; i < 5; ++i) { + const indicator = button.indicators.children[i]; + indicator.visible = i < running.length; + indicator.toggleClassName("focused", i === index); + } + + button.set_tooltip_text( + running.length === 1 ? running[0].title : app.name, + ); + }, + ], + ], + }), + ), + ], + ], + }); + +export default () => { + const pinnedapps = PinnedApps(); + const taskbar = Taskbar(); + const applauncher = AppButton({ + class_name: "launcher nonrunning", + icon: icons.apps.apps, + tooltip_text: "Applications", + on_clicked: () => App.toggleWindow("applauncher"), + }); + const separator = Widget.Separator({ + vpack: "center", + hpack: "center", + orientation: 1, + connections: [ + [Hyprland, (box) => (box.visible = taskbar.children.length > 0)], + ], + }); + return Widget.Box({ + class_name: "dock", + children: [applauncher, pinnedapps, separator, taskbar], + }); +}; diff --git a/home/desktops/hyprland/ags/js/dock/FloatingDock.js b/home/desktops/hyprland/ags/js/dock/FloatingDock.js new file mode 100644 index 0000000..667d82c --- /dev/null +++ b/home/desktops/hyprland/ags/js/dock/FloatingDock.js @@ -0,0 +1,54 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Hyprland from "resource:///com/github/Aylur/ags/service/hyprland.js"; +import Dock from "./Dock.js"; +import options from "../options.js"; + +/** @param {number} monitor */ +export default (monitor) => { + const revealer = Widget.Revealer({ + transition: "slide_up", + child: Dock(), + setup: (self) => { + const update = () => { + const ws = Hyprland.getWorkspace(Hyprland.active.workspace.id); + if (Hyprland.getMonitor(monitor)?.name === ws?.monitor) + self.reveal_child = ws?.windows === 0; + }; + self + .hook(Hyprland, update, "client-added") + .hook(Hyprland, update, "client-removed") + .hook(Hyprland.active.workspace, update); + }, + }); + + return Widget.Window({ + monitor, + name: `dock${monitor}`, + class_name: "floating-dock", + anchor: ["bottom"], + child: Widget.Box({ + children: [ + revealer, + Widget.Box({ + class_name: "padding", + css: "padding: 2px;", + }), + ], + }), + connections: [ + [ + "enter-notify-event", + () => { + revealer.reveal_child = true; + }, + ], + [ + "leave-notify-event", + () => { + revealer.reveal_child = false; + }, + ], + ], + binds: [["visible", options.bar.position, "value", (v) => v !== "bottom"]], + }); +}; diff --git a/home/desktops/hyprland/ags/js/icons.js b/home/desktops/hyprland/ags/js/icons.js new file mode 100644 index 0000000..f937169 --- /dev/null +++ b/home/desktops/hyprland/ags/js/icons.js @@ -0,0 +1,121 @@ +export default { + lock: "system-lock-screen-symbolic", + fallback: { + executable: "application-x-executable-symbolic", + }, + audio: { + mic: { + muted: "microphone-disabled-symbolic", + low: "microphone-sensitivity-low-symbolic", + medium: "microphone-sensitivity-medium-symbolic", + high: "microphone-sensitivity-high-symbolic", + }, + volume: { + muted: "audio-volume-muted-symbolic", + low: "audio-volume-low-symbolic", + medium: "audio-volume-medium-symbolic", + high: "audio-volume-high-symbolic", + overamplified: "audio-volume-overamplified-symbolic", + }, + type: { + headset: "audio-headphones-symbolic", + speaker: "audio-speakers-symbolic", + card: "audio-card-symbolic", + }, + mixer: "", + }, + asusctl: { + profile: { + Balanced: "power-profile-balanced-symbolic", + Quiet: "power-profile-power-saver-symbolic", + Performance: "power-profile-performance-symbolic", + }, + mode: { + Integrated: "", + Hybrid: "󰢮", + }, + }, + apps: { + apps: "view-app-grid-symbolic", + search: "folder-saved-search-symbolic", + }, + battery: { + charging: "󱐋", + warning: "battery-empty-symbolic", + }, + bluetooth: { + enabled: "bluetooth-active-symbolic", + disabled: "bluetooth-disabled-symbolic", + }, + brightness: { + indicator: "display-brightness-symbolic", + keyboard: "keyboard-brightness-symbolic", + screen: "display-brightness-symbolic", + }, + powermenu: { + sleep: "weather-clear-night-symbolic", + reboot: "system-reboot-symbolic", + logout: "system-log-out-symbolic", + shutdown: "system-shutdown-symbolic", + }, + recorder: { + recording: "media-record-symbolic", + }, + notifications: { + noisy: "preferences-system-notifications-symbolic", + silent: "notifications-disabled-symbolic", + }, + trash: { + full: "user-trash-full-symbolic", + empty: "user-trash-symbolic", + }, + mpris: { + fallback: "audio-x-generic-symbolic", + shuffle: { + enabled: "󰒟", + disabled: "󰒟", + }, + loop: { + none: "󰓦", + track: "󰓦", + playlist: "󰑐", + }, + playing: "󰏦", + paused: "󰐍", + stopped: "󰐍", + prev: "󰒮", + next: "󰒭", + }, + ui: { + close: "window-close-symbolic", + info: "info-symbolic", + menu: "open-menu-symbolic", + link: "external-link-symbolic", + settings: "emblem-system-symbolic", + tick: "object-select-symbolic", + arrow: { + right: "pan-end-symbolic", + left: "pan-start-symbolic", + down: "pan-down-symbolic", + up: "pan-up-symbolic", + }, + }, + system: { + cpu: "org.gnome.SystemMonitor-symbolic", + ram: "drive-harddisk-solidstate-symbolic", + temp: "temperature-symbolic", + }, + dialog: { + Search: "", + Applauncher: "󰵆", + Bar: "", + Border: "󰃇", + Color: "󰏘", + Desktop: "", + Font: "", + General: "󰒓", + Miscellaneous: "󰠱", + Theme: "󰃟", + Notifications: "󰂚 ", + }, +}; diff --git a/home/desktops/hyprland/ags/js/lockscreen/Lockscreen.js b/home/desktops/hyprland/ags/js/lockscreen/Lockscreen.js new file mode 100644 index 0000000..31fa98c --- /dev/null +++ b/home/desktops/hyprland/ags/js/lockscreen/Lockscreen.js @@ -0,0 +1,59 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Avatar from "../misc/Avatar.js"; +import Lockscreen from "../services/lockscreen.js"; +import Layer from "gi://GtkLayerShell"; + +const PasswordEntry = () => + Widget.Box({ + children: [ + Widget.Entry({ + connections: [[Lockscreen, (entry) => (entry.text = ""), "lock"]], + visibility: false, + placeholder_text: "Password", + on_accept: ({ text }) => Lockscreen.auth(text || ""), + hpack: "center", + hexpand: true, + }), + Widget.Spinner({ + active: true, + vpack: "center", + connections: [ + [Lockscreen, (w, auth) => (w.visible = auth), "authenticating"], + ], + }), + ], + }); + +/** @param {number} monitor */ +export default (monitor) => { + const win = Widget.Window({ + name: `lockscreen${monitor}`, + class_name: "lockscreen", + monitor, + layer: "overlay", + visible: false, + connections: [[Lockscreen, (w, lock) => (w.visible = lock), "lock"]], + child: Widget.Box({ + css: "min-width: 3000px; min-height: 2000px;", + class_name: "shader", + child: Widget.Box({ + class_name: "content", + vertical: true, + hexpand: true, + vexpand: true, + hpack: "center", + vpack: "center", + children: [ + Avatar({ + hpack: "center", + vpack: "center", + }), + PasswordEntry(), + ], + }), + }), + }); + + Layer.set_keyboard_mode(win, Layer.KeyboardMode.EXCLUSIVE); + return win; +}; diff --git a/home/desktops/hyprland/ags/js/lockscreen/auth.py b/home/desktops/hyprland/ags/js/lockscreen/auth.py new file mode 100755 index 0000000..20eab87 --- /dev/null +++ b/home/desktops/hyprland/ags/js/lockscreen/auth.py @@ -0,0 +1,7 @@ +#! /usr/bin/env python + +import pam +import sys +import getpass + +print(pam.authenticate(getpass.getuser(), sys.argv[1])); diff --git a/home/desktops/hyprland/ags/js/main.js b/home/desktops/hyprland/ags/js/main.js new file mode 100644 index 0000000..25e2b4c --- /dev/null +++ b/home/desktops/hyprland/ags/js/main.js @@ -0,0 +1,48 @@ +import Applauncher from "./applauncher/Applauncher.js"; +import Dashboard from "./dashboard/Dashboard.js"; +import Desktop from "./desktop/Desktop.js"; +import FloatingDock from "./dock/FloatingDock.js"; +import Lockscreen from "./lockscreen/Lockscreen.js"; +import Notifications from "./notifications/Notifications.js"; +import OSD from "./osd/OSD.js"; +import Overview from "./overview/Overview.js"; +import PowerMenu from "./powermenu/PowerMenu.js"; +import QuickSettings from "./quicksettings/QuickSettings.js"; +import ScreenCorners from "./screencorner/ScreenCorners.js"; +import TopBar from "./bar/TopBar.js"; +import Verification from "./powermenu/Verification.js"; +import About from "./about/about.js"; +import { init } from "./settings/setup.js"; +import { forMonitors } from "./utils.js"; +import { initWallpaper } from "./settings/wallpaper.js"; +import options from "./options.js"; + +initWallpaper(); + +const windows = () => [ + forMonitors(Desktop), + forMonitors(FloatingDock), + forMonitors(Lockscreen), + forMonitors(Notifications), + forMonitors(OSD), + forMonitors(ScreenCorners), + forMonitors(TopBar), + Applauncher(), + Dashboard(), + Overview(), + PowerMenu(), + QuickSettings(), + Verification(), + About(), +]; + +export default { + onConfigParsed: init, + windows: windows().flat(1), + maxStreamVolume: 1.05, + cacheNotificationActions: false, + closeWindowDelay: { + quicksettings: options.transition.value, + dashboard: options.transition.value, + }, +}; diff --git a/home/desktops/hyprland/ags/js/misc/Avatar.js b/home/desktops/hyprland/ags/js/misc/Avatar.js new file mode 100644 index 0000000..e5b70f6 --- /dev/null +++ b/home/desktops/hyprland/ags/js/misc/Avatar.js @@ -0,0 +1,16 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import options from "../options.js"; + +/** @param {import('types/widgets/box').BoxProps=} props */ +export default (props) => + Widget.Box({ ...props, class_name: "avatar" }) + .hook(options.desktop.avatar, (box) => + box.setCss(` + background-image: url('${options.desktop.avatar.value}'); + background-size: cover; + `), + ) + .on("size-allocate", (box) => { + const h = box.get_allocated_height(); + box.set_size_request(Math.ceil(h * 1.1), -1); + }); diff --git a/home/desktops/hyprland/ags/js/misc/BatteryIcon.js b/home/desktops/hyprland/ags/js/misc/BatteryIcon.js new file mode 100644 index 0000000..754f061 --- /dev/null +++ b/home/desktops/hyprland/ags/js/misc/BatteryIcon.js @@ -0,0 +1,18 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Battery from "resource:///com/github/Aylur/ags/service/battery.js"; + +export default () => + Widget.Icon({ + class_name: "battery", + binds: [["icon", Battery, "icon-name"]], + connections: [ + [ + Battery, + (icon) => { + icon.toggleClassName("charging", Battery.charging); + icon.toggleClassName("charged", Battery.charged); + icon.toggleClassName("low", Battery.percent < 30); + }, + ], + ], + }); diff --git a/home/desktops/hyprland/ags/js/misc/Clock.js b/home/desktops/hyprland/ags/js/misc/Clock.js new file mode 100644 index 0000000..5ab4f7e --- /dev/null +++ b/home/desktops/hyprland/ags/js/misc/Clock.js @@ -0,0 +1,26 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import GLib from "gi://GLib"; + +/** + * @param {import('types/widgets/label').Props & { + * format?: string, + * interval?: number, + * }} o + */ +export default ({ + format = "%H:%M:%S %B %e. %A", + interval = 1000, + ...rest +} = {}) => + Widget.Label({ + class_name: "clock", + ...rest, + connections: [ + [ + interval, + (label) => + (label.label = + GLib.DateTime.new_now_local().format(format) || "wrong format"), + ], + ], + }); diff --git a/home/desktops/hyprland/ags/js/misc/FontIcon.js b/home/desktops/hyprland/ags/js/misc/FontIcon.js new file mode 100644 index 0000000..b37681d --- /dev/null +++ b/home/desktops/hyprland/ags/js/misc/FontIcon.js @@ -0,0 +1,49 @@ +import Gtk from "gi://Gtk"; +import { createCtor } from "resource:///com/github/Aylur/ags/widget.js"; +import AgsLabel from "resource:///com/github/Aylur/ags/widgets/label.js"; +import GObject from "gi://GObject"; + +export default createCtor( + class FontIcon extends AgsLabel { + static { + GObject.registerClass(this); + } + + /** @param {string | import('types/widgets/label').Props & { icon?: string }} params */ + constructor(params = "") { + // @ts-expect-error + const { icon = "", ...rest } = params; + + super(typeof params === "string" ? {} : rest); + this.toggleClassName("font-icon"); + + if (typeof params === "object") this.icon = icon; + + if (typeof params === "string") this.icon = params; + } + + get icon() { + return this.label; + } + set icon(icon) { + this.label = icon; + } + + get size() { + return this.get_style_context().get_property( + "font-size", + Gtk.StateFlags.NORMAL, + ); + } + + /** @returns {[number, number]} */ + vfunc_get_preferred_height() { + return [this.size, this.size]; + } + + /** @returns {[number, number]} */ + vfunc_get_preferred_width() { + return [this.size, this.size]; + } + }, +); diff --git a/home/desktops/hyprland/ags/js/misc/HoverRevealer.js b/home/desktops/hyprland/ags/js/misc/HoverRevealer.js new file mode 100644 index 0000000..8d31fea --- /dev/null +++ b/home/desktops/hyprland/ags/js/misc/HoverRevealer.js @@ -0,0 +1,64 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; + +/** + * @typedef {import('types/widgets/eventbox').EventBoxProps & { + * indicator?: import('types/widgets/box').BoxProps['child'] + * direction?: 'left' | 'right' | 'down' | 'up' + * duration?: number + * eventboxConnections?: import('types/widgets/box').BoxProps['connections'] + * connections?: import('types/widgets/revealer').RevealerProps['connections'] + * }} HoverRevealProps + */ + +/** + * @param {HoverRevealProps} props + */ +export default ({ + indicator, + child, + direction = "left", + duration = 300, + connections = [], + eventboxConnections = [], + binds = [], + ...rest +}) => { + let open = false; + const vertical = direction === "down" || direction === "up"; + const posStart = direction === "down" || direction === "right"; + const posEnd = direction === "up" || direction === "left"; + + const revealer = Widget.Revealer({ + transition: `slide_${direction}`, + connections, + binds, + transition_duration: duration, + child, + }); + + const eventbox = Widget.EventBox({ + ...rest, + connections: eventboxConnections, + on_hover: () => { + if (open) return; + + revealer.reveal_child = true; + Utils.timeout(duration, () => (open = true)); + }, + on_hover_lost: () => { + if (!open) return; + + revealer.reveal_child = false; + open = false; + }, + child: Widget.Box({ + vertical, + children: [posStart && indicator, revealer, posEnd && indicator], + }), + }); + + return Widget.Box({ + children: [eventbox], + }); +}; diff --git a/home/desktops/hyprland/ags/js/misc/IconBrowser.js b/home/desktops/hyprland/ags/js/misc/IconBrowser.js new file mode 100644 index 0000000..bfb3b8b --- /dev/null +++ b/home/desktops/hyprland/ags/js/misc/IconBrowser.js @@ -0,0 +1,63 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import RegularWindow from "./RegularWindow.js"; +import Gtk from "gi://Gtk"; + +export default () => { + const selected = Widget.Label({ + css: "font-size: 1.2em;", + }); + + const flowbox = Widget.FlowBox({ + min_children_per_line: 10, + setup: (self) => { + self.connect("child-activated", (_, child) => { + selected.label = child.get_child().iconName; + }); + + Gtk.IconTheme.get_default() + .list_icons(null) + .sort() + .map((icon) => { + !icon.endsWith(".symbolic") && + self.insert( + Widget.Icon({ + icon, + size: 38, + }), + -1, + ); + }); + + self.show_all(); + }, + }); + + const entry = Widget.Entry({ + on_change: ({ text }) => + flowbox.get_children().forEach((child) => { + child.visible = child.get_child().iconName.includes(text); + }), + }); + + return RegularWindow({ + name: "icons", + visible: true, + child: Widget.Box({ + css: "padding: 30px;", + spacing: 20, + vertical: true, + children: [ + entry, + Widget.Scrollable({ + hscroll: "never", + vscroll: "always", + hexpand: true, + vexpand: true, + css: "min-width: 500px;" + "min-height: 500px;", + child: flowbox, + }), + selected, + ], + }), + }); +}; diff --git a/home/desktops/hyprland/ags/js/misc/Notification.js b/home/desktops/hyprland/ags/js/misc/Notification.js new file mode 100644 index 0000000..2762ce5 --- /dev/null +++ b/home/desktops/hyprland/ags/js/misc/Notification.js @@ -0,0 +1,132 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import GLib from "gi://GLib"; + +/** @param {import('types/service/notifications').Notification} n */ +const NotificationIcon = ({ app_entry, app_icon, image }) => { + if (image) { + return Widget.Box({ + vpack: "start", + hexpand: false, + class_name: "icon img", + css: ` + background-image: url("${image}"); + background-size: cover; + background-repeat: no-repeat; + background-position: center; + min-width: 78px; + min-height: 78px; + `, + }); + } + + let icon = "dialog-information-symbolic"; + if (Utils.lookUpIcon(app_icon)) icon = app_icon; + + if (Utils.lookUpIcon(app_entry || "")) icon = app_entry || ""; + + return Widget.Box({ + vpack: "start", + hexpand: false, + class_name: "icon", + css: ` + min-width: 78px; + min-height: 78px; + `, + child: Widget.Icon({ + icon, + size: 58, + hpack: "center", + hexpand: true, + vpack: "center", + vexpand: true, + }), + }); +}; + +/** @param {import('types/service/notifications').Notification} notification */ +export default (notification) => { + const content = Widget.Box({ + class_name: "content", + children: [ + NotificationIcon(notification), + Widget.Box({ + hexpand: true, + vertical: true, + children: [ + Widget.Box({ + children: [ + Widget.Label({ + class_name: "title", + xalign: 0, + justification: "left", + hexpand: true, + max_width_chars: 24, + truncate: "end", + wrap: true, + label: notification.summary, + use_markup: true, + }), + Widget.Label({ + class_name: "time", + vpack: "start", + label: GLib.DateTime.new_from_unix_local( + notification.time, + ).format("%H:%M"), + }), + Widget.Button({ + class_name: "close-button", + vpack: "start", + child: Widget.Icon("window-close-symbolic"), + on_clicked: () => notification.close(), + }), + ], + }), + Widget.Label({ + class_name: "description", + hexpand: true, + use_markup: true, + xalign: 0, + justification: "left", + label: notification.body, + wrap: true, + }), + ], + }), + ], + }); + + const actionsbox = Widget.Revealer({ + transition: "slide_down", + child: Widget.EventBox({ + child: Widget.Box({ + class_name: "actions horizontal", + children: notification.actions.map((action) => + Widget.Button({ + class_name: "action-button", + on_clicked: () => notification.invoke(action.id), + hexpand: true, + child: Widget.Label(action.label), + }), + ), + }), + }), + }); + + return Widget.EventBox({ + class_name: `notification ${notification.urgency}`, + vexpand: false, + on_primary_click: () => notification.dismiss(), + on_hover() { + actionsbox.reveal_child = true; + }, + on_hover_lost() { + actionsbox.reveal_child = true; + notification.dismiss(); + }, + child: Widget.Box({ + vertical: true, + children: [content, notification.actions.length > 0 && actionsbox], + }), + }); +}; diff --git a/home/desktops/hyprland/ags/js/misc/PopupWindow.js b/home/desktops/hyprland/ags/js/misc/PopupWindow.js new file mode 100644 index 0000000..64bde36 --- /dev/null +++ b/home/desktops/hyprland/ags/js/misc/PopupWindow.js @@ -0,0 +1,65 @@ +import AgsWindow from "resource:///com/github/Aylur/ags/widgets/window.js"; +import App from "resource:///com/github/Aylur/ags/app.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import options from "../options.js"; +import GObject from "gi://GObject"; + +class PopupWindow extends AgsWindow { + static { + GObject.registerClass(this); + } + + /** @param {import('types/widgets/window').WindowProps & { + * name: string + * child: import('types/widgets/box').default + * transition?: import('types/widgets/revealer').RevealerProps['transition'] + * }} o + */ + constructor({ name, child, transition = "none", visible = false, ...rest }) { + super({ + ...rest, + name, + popup: true, + focusable: true, + class_names: ["popup-window", name], + }); + + child.toggleClassName("window-content"); + this.revealer = Widget.Revealer({ + transition, + child, + transitionDuration: options.transition.value, + connections: [ + [ + App, + (_, wname, visible) => { + if (wname === name) this.revealer.reveal_child = visible; + }, + ], + ], + }); + + this.child = Widget.Box({ + css: "padding: 1px;", + child: this.revealer, + }); + + this.show_all(); + this.visible = visible; + } + + set transition(dir) { + this.revealer.transition = dir; + } + get transition() { + return this.revealer.transition; + } +} + +/** @param {import('types/widgets/window').WindowProps & { + * name: string + * child: import('types/widgets/box').default + * transition?: import('types/widgets/revealer').RevealerProps['transition'] + * }} config + */ +export default (config) => new PopupWindow(config); diff --git a/home/desktops/hyprland/ags/js/misc/Progress.js b/home/desktops/hyprland/ags/js/misc/Progress.js new file mode 100644 index 0000000..d7cccfc --- /dev/null +++ b/home/desktops/hyprland/ags/js/misc/Progress.js @@ -0,0 +1,57 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; + +export default ({ + height = 18, + width = 180, + vertical = false, + child, + ...props +}) => { + const fill = Widget.Box({ + class_name: "fill", + hexpand: vertical, + vexpand: !vertical, + hpack: vertical ? "fill" : "start", + vpack: vertical ? "end" : "fill", + children: [child], + }); + + let fill_size = 0; + + return Widget.Box({ + ...props, + class_name: "progress", + css: ` + min-width: ${width}px; + min-height: ${height}px; + `, + children: [fill], + setup: (progress) => + (progress.setValue = (value) => { + if (value < 0) return; + + const axis = vertical ? "height" : "width"; + const axisv = vertical ? height : width; + const min = vertical ? width : height; + const preferred = (axisv - min) * value + min; + + if (!fill_size) { + fill_size = preferred; + fill.setCss(`min-${axis}: ${preferred}px;`); + return; + } + + const frames = 10; + const goal = preferred - fill_size; + const step = goal / frames; + + for (let i = 0; i < frames; ++i) { + Utils.timeout(5 * i, () => { + fill_size += step; + fill.setCss(`min-${axis}: ${fill_size}px`); + }); + } + }), + }); +}; diff --git a/home/desktops/hyprland/ags/js/misc/RegularWindow.js b/home/desktops/hyprland/ags/js/misc/RegularWindow.js new file mode 100644 index 0000000..b4875e4 --- /dev/null +++ b/home/desktops/hyprland/ags/js/misc/RegularWindow.js @@ -0,0 +1,19 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Gtk from "gi://Gtk"; +import AgsWidget from "resource:///com/github/Aylur/ags/widgets/widget.js"; + +class RegularWindow extends AgsWidget(Gtk.Window, "RegularWindow") { + static { + AgsWidget.register(this); + } + /** + * @param {import('types/widgets/widget').BaseProps< + * RegularWindow, Gtk.Window.ConstructorProperties + * >} params */ + constructor(params) { + // @ts-expect-error + super(params); + } +} + +export default Widget.createCtor(RegularWindow); diff --git a/home/desktops/hyprland/ags/js/misc/mpris.js b/home/desktops/hyprland/ags/js/misc/mpris.js new file mode 100644 index 0000000..96ea960 --- /dev/null +++ b/home/desktops/hyprland/ags/js/misc/mpris.js @@ -0,0 +1,321 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import icons from "../icons.js"; +import { blurImg } from "../utils.js"; + +/** + * @param {import('types/service/mpris').MprisPlayer} player + * @param {import('types/widgets/box').BoxProps=} props + */ +export const CoverArt = (player, props) => + Widget.Box({ + ...props, + class_name: "cover", + binds: [ + [ + "css", + player, + "cover-path", + (path) => `background-image: url("${path}")`, + ], + ], + }); + +/** + * @param {import('types/service/mpris').MprisPlayer} player + * @param {import('types/widgets/box').BoxProps=} props + */ +export const BlurredCoverArt = (player, props) => + Widget.Box({ + ...props, + class_name: "blurred-cover", + connections: [ + [ + player, + (box) => + blurImg(player.cover_path).then((img) => { + img && box.setCss(`background-image: url("${img}")`); + }), + "notify::cover-path", + ], + ], + }); + +/** + * @param {import('types/service/mpris').MprisPlayer} player + * @param {import('types/widgets/label').Props=} props + */ +export const TitleLabel = (player, props) => + Widget.Label({ + ...props, + class_name: "title", + binds: [["label", player, "track-title"]], + }); + +/** + * @param {import('types/service/mpris').MprisPlayer} player + * @param {import('types/widgets/label').Props=} props + */ +export const ArtistLabel = (player, props) => + Widget.Label({ + ...props, + class_name: "artist", + binds: [["label", player, "track-artists", (a) => a.join(", ") || ""]], + }); + +/** + * @param {import('types/service/mpris').MprisPlayer} player + * @param {import('types/widgets/icon').Props & { symbolic?: boolean }=} props + */ +export const PlayerIcon = (player, { symbolic = true, ...props } = {}) => + Widget.Icon({ + ...props, + class_name: "player-icon", + tooltip_text: player.identity || "", + connections: [ + [ + player, + (icon) => { + const name = `${player.entry}${symbolic ? "-symbolic" : ""}`; + Utils.lookUpIcon(name) + ? (icon.icon = name) + : (icon.icon = icons.mpris.fallback); + }, + ], + ], + }); + +/** + * @param {import('types/service/mpris').MprisPlayer} player + * @param {import('types/widgets/slider').SliderProps=} props + */ +export const PositionSlider = (player, props) => + Widget.Slider({ + ...props, + class_name: "position-slider", + draw_value: false, + on_change: ({ value }) => { + player.position = player.length * value; + }, + properties: [ + [ + "update", + (slider) => { + if (slider.dragging) return; + + slider.visible = player.length > 0; + if (player.length > 0) slider.value = player.position / player.length; + }, + ], + ], + connections: [ + [player, (s) => s._update(s)], + [player, (s) => s._update(s), "position"], + [1000, (s) => s._update(s)], + ], + }); + +/** @param {number} length */ +function lengthStr(length) { + const min = Math.floor(length / 60); + const sec = Math.floor(length % 60); + const sec0 = sec < 10 ? "0" : ""; + return `${min}:${sec0}${sec}`; +} + +/** @param {import('types/service/mpris').MprisPlayer} player */ +export const PositionLabel = (player) => + Widget.Label({ + properties: [ + [ + "update", + (label, time) => { + player.length > 0 + ? (label.label = lengthStr(time || player.position)) + : (label.visible = !!player); + }, + ], + ], + connections: [ + [player, (l, time) => l._update(l, time), "position"], + [1000, (l) => l._update(l)], + ], + }); + +/** @param {import('types/service/mpris').MprisPlayer} player */ +export const LengthLabel = (player) => + Widget.Label({ + connections: [ + [ + player, + (label) => { + player.length > 0 + ? (label.label = lengthStr(player.length)) + : (label.visible = !!player); + }, + ], + ], + }); + +/** @param {import('types/service/mpris').MprisPlayer} player */ +export const Slash = (player) => + Widget.Label({ + label: "/", + connections: [ + [ + player, + (label) => { + label.visible = player.length > 0; + }, + ], + ], + }); + +/** + * @param {Object} o + * @param {import('types/service/mpris').MprisPlayer} o.player + * @param {import('types/widgets/stack').StackProps['items']} o.items + * @param {'shuffle' | 'loop' | 'playPause' | 'previous' | 'next'} o.onClick + * @param {string} o.prop + * @param {string} o.canProp + * @param {any} o.cantValue + */ +const PlayerButton = ({ player, items, onClick, prop, canProp, cantValue }) => + Widget.Button({ + child: Widget.Stack({ + items, + binds: [["shown", player, prop, (p) => `${p}`]], + }), + on_clicked: player[onClick].bind(player), + binds: [["visible", player, canProp, (c) => c !== cantValue]], + }); + +/** @param {import('types/service/mpris').MprisPlayer} player */ +export const ShuffleButton = (player) => + PlayerButton({ + player, + items: [ + [ + "true", + Widget.Label({ + class_name: "shuffle enabled", + label: icons.mpris.shuffle.enabled, + }), + ], + [ + "false", + Widget.Label({ + class_name: "shuffle disabled", + label: icons.mpris.shuffle.disabled, + }), + ], + ], + onClick: "shuffle", + prop: "shuffle-status", + canProp: "shuffle-status", + cantValue: null, + }); + +/** @param {import('types/service/mpris').MprisPlayer} player */ +export const LoopButton = (player) => + PlayerButton({ + player, + items: [ + [ + "None", + Widget.Label({ + class_name: "loop none", + label: icons.mpris.loop.none, + }), + ], + [ + "Track", + Widget.Label({ + class_name: "loop track", + label: icons.mpris.loop.track, + }), + ], + [ + "Playlist", + Widget.Label({ + class_name: "loop playlist", + label: icons.mpris.loop.playlist, + }), + ], + ], + onClick: "loop", + prop: "loop-status", + canProp: "loop-status", + cantValue: null, + }); + +/** @param {import('types/service/mpris').MprisPlayer} player */ +export const PlayPauseButton = (player) => + PlayerButton({ + player, + items: [ + [ + "Playing", + Widget.Label({ + class_name: "playing", + label: icons.mpris.playing, + }), + ], + [ + "Paused", + Widget.Label({ + class_name: "paused", + label: icons.mpris.paused, + }), + ], + [ + "Stopped", + Widget.Label({ + class_name: "stopped", + label: icons.mpris.stopped, + }), + ], + ], + onClick: "playPause", + prop: "play-back-status", + canProp: "can-play", + cantValue: false, + }); + +/** @param {import('types/service/mpris').MprisPlayer} player */ +export const PreviousButton = (player) => + PlayerButton({ + player, + items: [ + [ + "true", + Widget.Label({ + class_name: "previous", + label: icons.mpris.prev, + }), + ], + ], + onClick: "previous", + prop: "can-go-prev", + canProp: "can-go-prev", + cantValue: false, + }); + +/** @param {import('types/service/mpris').MprisPlayer} player */ +export const NextButton = (player) => + PlayerButton({ + player, + items: [ + [ + "true", + Widget.Label({ + class_name: "next", + label: icons.mpris.next, + }), + ], + ], + onClick: "next", + prop: "can-go-next", + canProp: "can-go-next", + cantValue: false, + }); diff --git a/home/desktops/hyprland/ags/js/notifications/Notifications.js b/home/desktops/hyprland/ags/js/notifications/Notifications.js new file mode 100644 index 0000000..1425c3e --- /dev/null +++ b/home/desktops/hyprland/ags/js/notifications/Notifications.js @@ -0,0 +1,72 @@ +import Notifications from "resource:///com/github/Aylur/ags/service/notifications.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import Notification from "../misc/Notification.js"; +import options from "../options.js"; + +/** @param {import('types/widgets/revealer').default} parent */ +const Popups = (parent) => { + const map = new Map(); + + const onDismissed = (_, id, force = false) => { + if (!id || !map.has(id)) return; + + if (map.get(id).isHovered() && !force) return; + + if (map.size - 1 === 0) parent.reveal_child = false; + + Utils.timeout(200, () => { + map.get(id)?.destroy(); + map.delete(id); + }); + }; + + /** @param {import('types/widgets/box').default} box */ + const onNotified = (box, id) => { + if (!id || Notifications.dnd) return; + + const n = Notifications.getNotification(id); + if (!n) return; + + if (options.notifications.black_list.value.includes(n.app_name || "")) + return; + + map.delete(id); + map.set(id, Notification(n)); + box.children = Array.from(map.values()).reverse(); + Utils.timeout(10, () => { + parent.reveal_child = true; + }); + }; + + return Widget.Box({ + vertical: true, + connections: [ + [Notifications, onNotified, "notified"], + [Notifications, onDismissed, "dismissed"], + [Notifications, (box, id) => onDismissed(box, id, true), "closed"], + ], + }); +}; + +/** @param {import('types/widgets/revealer').RevealerProps['transition']} transition */ +const PopupList = (transition = "slide_down") => + Widget.Box({ + css: "padding: 1px", + children: [ + Widget.Revealer({ + transition, + setup: (self) => (self.child = Popups(self)), + }), + ], + }); + +/** @param {number} monitor */ +export default (monitor) => + Widget.Window({ + monitor, + name: `notifications${monitor}`, + class_name: "notifications", + binds: [["anchor", options.notifications.position]], + child: PopupList(), + }); diff --git a/home/desktops/hyprland/ags/js/options.js b/home/desktops/hyprland/ags/js/options.js new file mode 100644 index 0000000..60211a0 --- /dev/null +++ b/home/desktops/hyprland/ags/js/options.js @@ -0,0 +1,303 @@ +/** + * An object holding Options that are Variables with cached values. + * + * to update an option at runtime simply run + * ags -r "options.path.to.option.setValue('value')" + * + * resetting: + * ags -r "options.reset()" + */ + +import { + Option, + resetOptions, + getValues, + apply, + getOptions, +} from "./settings/option.js"; +import { USER } from "resource:///com/github/Aylur/ags/utils.js"; +import themes from "./themes.js"; + +export default { + reset: resetOptions, + values: getValues, + apply: apply, + list: getOptions, + + spacing: Option(9), + padding: Option(8), + radii: Option(9), + + popover_padding_multiplier: Option(1.4, { + category: "General", + note: "popover-padding: padding × this", + type: "float", + unit: "", + }), + + color: { + red: Option("#e55f86", { scss: "red" }), + green: Option("#00D787", { scss: "green" }), + yellow: Option("#EBFF71", { scss: "yellow" }), + blue: Option("#51a4e7", { scss: "blue" }), + magenta: Option("#9077e7", { scss: "magenta" }), + teal: Option("#51e6e6", { scss: "teal" }), + orange: Option("#E79E64", { scss: "orange" }), + }, + + theme: { + name: Option(themes[0].name, { + category: "exclude", + note: "Name to show as active in quicktoggles", + }), + + icon: Option(themes[0].icon, { + category: "exclude", + note: "Icon to show as active in quicktoggles", + }), + + scheme: Option("dark", { + enums: ["dark", "light"], + type: "enum", + note: "Color scheme to set on Gtk apps: 'ligth' or 'dark'", + title: "Color Scheme", + scss: "color-scheme", + }), + bg: Option("#171717", { + title: "Background Color", + scss: "bg-color", + }), + fg: Option("#eeeeee", { + title: "Foreground Color", + scss: "fg-color", + }), + + accent: { + accent: Option("$blue", { + category: "Theme", + title: "Accent Color", + scss: "accent", + }), + fg: Option("#141414", { + category: "Theme", + title: "Accent Foreground Color", + scss: "accent-fg", + }), + gradient: Option("to right, $accent, lighten($accent, 6%)", { + category: "Theme", + title: "Accent Linear Gradient", + scss: "accent-gradient", + }), + }, + + widget: { + bg: Option("$fg-color", { + category: "Theme", + title: "Widget Background Color", + scss: "_widget-bg", + }), + opacity: Option(94, { + category: "Theme", + title: "Widget Background Opacity", + unit: "", + scss: "widget-opacity", + }), + }, + }, + + border: { + color: Option("$fg-color", { + category: "Border", + title: "Border Color", + scss: "_border-color", + }), + opacity: Option(97, { + category: "Border", + title: "Border Opacity", + unit: "", + }), + width: Option(1, { + category: "Border", + title: "Border Width", + }), + }, + + hypr: { + inactive_border: Option("rgba(333333ff)", { + category: "Border", + title: "Border on Inactive Windows", + scss: "exclude", + }), + wm_gaps_multiplier: Option(2.4, { + category: "General", + scss: "wm-gaps-multiplier", + note: "wm-gaps: padding × this", + type: "float", + unit: "", + }), + }, + + // TODO: use this on revealers + transition: Option(200, { + category: "exclude", + note: "Transition time on aminations in ms, e.g on hover", + unit: "ms", + }), + + font: { + font: Option("Ubuntu Nerd Font", { + type: "font", + title: "Font", + scss: "font", + }), + mono: Option("Mononoki Nerd Font", { + title: "Monospaced Font", + scss: "mono-font", + }), + size: Option(13, { + scss: "font-size", + unit: "pt", + }), + }, + + applauncher: { + width: Option(500), + height: Option(500), + icon_size: Option(52), + }, + + bar: { + position: Option("top", { + enums: ["top", "bottom"], + type: "enum", + }), + style: Option("normal", { + enums: ["floating", "normal", "separated"], + type: "enum", + }), + flat_buttons: Option(true, { scss: "bar-flat-buttons" }), + separators: Option(true), + icon: Option("distro-icon", { + note: '"distro-icon" or a single font', + }), + }, + + battery: { + show_percentage: Option(true, { + persist: true, + noReload: false, + category: "exclude", + }), + bar: { + show_icon: Option(true, { category: "Bar" }), + width: Option(70, { category: "Bar" }), + height: Option(14, { category: "Bar" }), + full: Option(false, { category: "Bar" }), + }, + low: Option(30, { category: "Bar" }), + medium: Option(50, { category: "Bar" }), + }, + + desktop: { + wallpaper: { + fg: Option("#fff", { scss: "wallpaper-fg" }), + img: Option(themes[0].options["desktop.wallpaper.img"], { + scssFormat: (v) => `"${v}"`, + type: "img", + }), + }, + avatar: Option(`/var/lib/AccountsService/icons/${USER}`, { + scssFormat: (v) => `"${v}"`, + type: "img", + note: "displayed in quicksettings and locksreen", + }), + screen_corners: Option(true, { scss: "screen-corners" }), + clock: { + enable: Option(true), + position: Option("center center", { + note: "halign valign", + }), + }, + drop_shadow: Option(true, { scss: "drop-shadow" }), + shadow: Option("rgba(0, 0, 0, .6)", { scss: "shadow" }), + dock: { + icon_size: Option(56), + pinned_apps: Option( + [ + "firefox", + "org.wezfurlong.wezterm", + "org.gnome.Nautilus", + "org.gnome.Calendar", + "obsidian", + "transmission-gtk", + "caprine", + "teams-for-linux", + "discord", + "spotify", + "com.usebottles.bottles", + "org.gnome.Software", + ], + { scss: "exclude" }, + ), + }, + }, + + notifications: { + black_list: Option(["Spotify"], { note: "app-name | entry" }), + position: Option(["top"], { note: "anchor" }), + width: Option(450), + }, + + dashboard: { + sys_info_size: Option(70, { + category: "Desktop", + scss: "sys-info-size", + }), + }, + + mpris: { + black_list: Option(["Caprine"], { + category: "Bar", + title: "List of blacklisted mpris players", + note: "filters for bus-name, name, identity, entry", + }), + preferred: Option("spotify", { + category: "Bar", + title: "Preferred player", + }), + }, + + workspaces: Option(7, { + category: "Bar", + title: "No. workspaces on bar and overview", + note: "Set it to 0 to make it dynamic", + }), + + temperature: "/sys/class/thermal/thermal_zone0/temp", + systemFetchInterval: 5000, + brightnessctlKBD: "asus::kbd_backlight", + substitutions: { + icons: [ + ["transmission-gtk", "transmission"], + ["blueberry.py", "bluetooth"], + ["Caprine", "facebook-messenger"], + ["", "preferences-desktop-display"], + ], + titles: [ + ["com.github.Aylur.ags", "AGS"], + ["transmission-gtk", "Transmission"], + ["com.obsproject.Studio", "OBS"], + ["com.usebottles.bottles", "Bottles"], + ["com.github.wwmm.easyeffects", "Easy Effects"], + ["org.gnome.TextEditor", "Text Editor"], + ["org.gnome.design.IconLibrary", "Icon Library"], + ["blueberry.py", "Blueberry"], + ["org.wezfurlong.wezterm", "Wezterm"], + ["com.raggesilver.BlackBox", "BlackBox"], + ["firefox", "Firefox"], + ["org.gnome.Nautilus", "Files"], + ["libreoffice-writer", "Writer"], + ["", "Desktop"], + ], + }, +}; diff --git a/home/desktops/hyprland/ags/js/osd/OSD.js b/home/desktops/hyprland/ags/js/osd/OSD.js new file mode 100644 index 0000000..5bf44cd --- /dev/null +++ b/home/desktops/hyprland/ags/js/osd/OSD.js @@ -0,0 +1,77 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import FontIcon from "../misc/FontIcon.js"; +import Progress from "../misc/Progress.js"; +import Indicator from "../services/onScreenIndicator.js"; + +export const OnScreenIndicator = ({ height = 300, width = 48 } = {}) => + Widget.Box({ + class_name: "indicator", + css: "padding: 1px;", + child: Widget.Revealer({ + transition: "slide_left", + connections: [ + [ + Indicator, + (revealer, value) => { + revealer.reveal_child = value > -1; + }, + ], + ], + child: Progress({ + width, + height, + vertical: true, + connections: [ + [Indicator, (progress, value) => progress.setValue(value)], + ], + child: Widget.Stack({ + vpack: "start", + hpack: "center", + hexpand: false, + items: [ + [ + "true", + Widget.Icon({ + hpack: "center", + size: width, + connections: [ + [Indicator, (icon, _v, name) => (icon.icon = name || "")], + ], + }), + ], + [ + "false", + FontIcon({ + hpack: "center", + hexpand: true, + css: `font-size: ${width}px;`, + connections: [ + [Indicator, (icon, _v, name) => (icon.icon = name || "")], + ], + }), + ], + ], + connections: [ + [ + Indicator, + (stack, _v, name) => { + stack.shown = `${!!Utils.lookUpIcon(name)}`; + }, + ], + ], + }), + }), + }), + }); + +/** @param {number} monitor */ +export default (monitor) => + Widget.Window({ + name: `indicator${monitor}`, + monitor, + class_name: "indicator", + layer: "overlay", + anchor: ["right"], + child: OnScreenIndicator(), + }); diff --git a/home/desktops/hyprland/ags/js/overview/Client.js b/home/desktops/hyprland/ags/js/overview/Client.js new file mode 100644 index 0000000..eceb608 --- /dev/null +++ b/home/desktops/hyprland/ags/js/overview/Client.js @@ -0,0 +1,50 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import App from "resource:///com/github/Aylur/ags/app.js"; +import { createSurfaceFromWidget, substitute } from "../utils.js"; +import Gdk from "gi://Gdk"; +import Gtk from "gi://Gtk"; +import options from "../options.js"; +import Hyprland from "resource:///com/github/Aylur/ags/service/hyprland.js"; + +const SCALE = 0.08; +const TARGET = [Gtk.TargetEntry.new("text/plain", Gtk.TargetFlags.SAME_APP, 0)]; + +/** @param {string} args */ +const dispatch = (args) => Hyprland.sendMessage(`dispatch ${args}`); + +/** @param {string} str */ +const icon = (str) => substitute(options.substitutions.icons, str); + +export default ({ address, size: [w, h], class: c, title }) => + Widget.Button({ + class_name: "client", + tooltip_text: `${title}`, + child: Widget.Icon({ + css: ` + min-width: ${w * SCALE}px; + min-height: ${h * SCALE}px; + `, + icon: icon(c), + }), + on_secondary_click: () => dispatch(`closewindow address:${address}`), + on_clicked: () => + dispatch(`focuswindow address:${address}`).then(() => + App.closeWindow("overview"), + ), + + setup: (btn) => { + btn.drag_source_set( + Gdk.ModifierType.BUTTON1_MASK, + TARGET, + Gdk.DragAction.COPY, + ); + btn.connect("drag-data-get", (_w, _c, data) => + data.set_text(address, address.length), + ); + btn.connect("drag-begin", (_, context) => { + Gtk.drag_set_icon_surface(context, createSurfaceFromWidget(btn)); + btn.toggleClassName("hidden", true); + }); + btn.connect("drag-end", () => btn.toggleClassName("hidden", false)); + }, + }); diff --git a/home/desktops/hyprland/ags/js/overview/Overview.js b/home/desktops/hyprland/ags/js/overview/Overview.js new file mode 100644 index 0000000..0a23b6d --- /dev/null +++ b/home/desktops/hyprland/ags/js/overview/Overview.js @@ -0,0 +1,53 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import App from "resource:///com/github/Aylur/ags/app.js"; +import Hyprland from "resource:///com/github/Aylur/ags/service/hyprland.js"; +import PopupWindow from "../misc/PopupWindow.js"; +import Workspace from "./Workspace.js"; +import options from "../options.js"; +import { range } from "../utils.js"; + +const ws = options.workspaces; + +/** @param {import('types/widgets/box').default} box */ +const update = (box) => { + if (App.windows.has("overview") && !App.getWindow("overview")?.visible) + return; + + Hyprland.sendMessage("j/clients") + .then((clients) => { + box.children.forEach((ws) => { + // @ts-expect-error + ws.attribute(JSON.parse(clients)); + }); + }) + .catch(console.error); +}; + +/** @param {import('types/widgets/box').default} box */ +const children = (box) => { + if (ws.value === 0) { + box.children = Hyprland.workspaces + .sort((ws1, ws2) => ws1.id - ws2.id) + .map(({ id }) => Workspace(id)); + } +}; + +export default () => + PopupWindow({ + name: "overview", + child: Widget.Box({ + setup: update, + connections: [ + [ + ws, + (box) => { + box.children = range(ws.value).map(Workspace); + update(box); + children(box); + }, + ], + [Hyprland, update], + [Hyprland, children, "notify::workspaces"], + ], + }), + }); diff --git a/home/desktops/hyprland/ags/js/overview/Workspace.js b/home/desktops/hyprland/ags/js/overview/Workspace.js new file mode 100644 index 0000000..5b37f5b --- /dev/null +++ b/home/desktops/hyprland/ags/js/overview/Workspace.js @@ -0,0 +1,64 @@ +import Hyprland from "resource:///com/github/Aylur/ags/service/hyprland.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import Gdk from "gi://Gdk"; +import Gtk from "gi://Gtk"; +import Client from "./Client.js"; + +const SCALE = 0.08; +const TARGET = [Gtk.TargetEntry.new("text/plain", Gtk.TargetFlags.SAME_APP, 0)]; + +/** @param {string} args */ +const dispatch = (args) => Utils.execAsync(`hyprctl dispatch ${args}`); + +/** @param {number} index */ +export default (index) => { + const fixed = Gtk.Fixed.new(); + + return Widget.Box({ + class_name: "workspace", + vpack: "center", + css: ` + min-width: ${1920 * SCALE}px; + min-height: ${1080 * SCALE}px; + `, + connections: [ + [ + Hyprland, + (box) => { + box.toggleClassName("active", Hyprland.active.workspace.id === index); + }, + ], + ], + child: Widget.EventBox({ + hexpand: true, + vexpand: true, + on_primary_click: () => dispatch(`workspace ${index}`), + setup: (eventbox) => { + eventbox.drag_dest_set( + Gtk.DestDefaults.ALL, + TARGET, + Gdk.DragAction.COPY, + ); + eventbox.connect("drag-data-received", (_w, _c, _x, _y, data) => { + dispatch(`movetoworkspacesilent ${index},address:${data.get_text()}`); + }); + }, + child: fixed, + }), + + /** @param {Array} clients */ + attribute: (clients) => { + fixed.get_children().forEach((ch) => ch.destroy()); + clients + .filter(({ workspace: { id } }) => id === index) + .forEach((c) => { + c.at[0] -= Hyprland.getMonitor(c.monitor)?.x || 0; + c.at[1] -= Hyprland.getMonitor(c.monitor)?.y || 0; + c.mapped && fixed.put(Client(c), c.at[0] * SCALE, c.at[1] * SCALE); + }); + + fixed.show_all(); + }, + }); +}; diff --git a/home/desktops/hyprland/ags/js/powermenu/PowerMenu.js b/home/desktops/hyprland/ags/js/powermenu/PowerMenu.js new file mode 100644 index 0000000..1b25fbd --- /dev/null +++ b/home/desktops/hyprland/ags/js/powermenu/PowerMenu.js @@ -0,0 +1,31 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import icons from "../icons.js"; +import PowerMenu from "../services/powermenu.js"; +import ShadedPopup from "./ShadedPopup.js"; + +/** + * @param {'sleep' | 'reboot' | 'logout' | 'shutdown'} action + * @param {string} label + */ +const SysButton = (action, label) => + Widget.Button({ + on_clicked: () => PowerMenu.action(action), + child: Widget.Box({ + vertical: true, + children: [Widget.Icon(icons.powermenu[action]), Widget.Label(label)], + }), + }); + +export default () => + ShadedPopup({ + name: "powermenu", + expand: true, + child: Widget.Box({ + children: [ + SysButton("sleep", "Sleep"), + SysButton("reboot", "Reboot"), + SysButton("logout", "Log Out"), + SysButton("shutdown", "Shutdown"), + ], + }), + }); diff --git a/home/desktops/hyprland/ags/js/powermenu/ShadedPopup.js b/home/desktops/hyprland/ags/js/powermenu/ShadedPopup.js new file mode 100644 index 0000000..0e7f4bf --- /dev/null +++ b/home/desktops/hyprland/ags/js/powermenu/ShadedPopup.js @@ -0,0 +1,42 @@ +import App from "resource:///com/github/Aylur/ags/app.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; + +/** @param {string} windowName */ +const Padding = (windowName) => + Widget.EventBox({ + class_name: "padding", + hexpand: true, + vexpand: true, + connections: [["button-press-event", () => App.toggleWindow(windowName)]], + }); + +/** + * @param {import('types/widgets/window').WindowProps & { + * name: string + * child: import('types/widgets/box').default + * }} o + */ +export default ({ name, child, ...rest }) => + Widget.Window({ + ...rest, + class_names: ["popup-window", name], + name, + visible: false, + popup: true, + focusable: true, + setup() { + child.toggleClassName("window-content"); + }, + child: Widget.CenterBox({ + class_name: "shader", + css: "min-width: 5000px; min-height: 3000px;", + children: [ + Padding(name), + Widget.CenterBox({ + vertical: true, + children: [Padding(name), child, Padding(name)], + }), + Padding(name), + ], + }), + }); diff --git a/home/desktops/hyprland/ags/js/powermenu/Verification.js b/home/desktops/hyprland/ags/js/powermenu/Verification.js new file mode 100644 index 0000000..894ef29 --- /dev/null +++ b/home/desktops/hyprland/ags/js/powermenu/Verification.js @@ -0,0 +1,46 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import App from "resource:///com/github/Aylur/ags/app.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import PowerMenu from "../services/powermenu.js"; +import ShadedPopup from "./ShadedPopup.js"; + +export default () => + ShadedPopup({ + name: "verification", + expand: true, + child: Widget.Box({ + vertical: true, + children: [ + Widget.Box({ + class_name: "text-box", + vertical: true, + children: [ + Widget.Label({ + class_name: "title", + binds: [["label", PowerMenu, "title"]], + }), + Widget.Label({ + class_name: "desc", + label: "Are you sure?", + }), + ], + }), + Widget.Box({ + class_name: "buttons horizontal", + vexpand: true, + vpack: "end", + homogeneous: true, + children: [ + Widget.Button({ + child: Widget.Label("No"), + on_clicked: () => App.toggleWindow("verification"), + }), + Widget.Button({ + child: Widget.Label("Yes"), + on_clicked: () => Utils.exec(PowerMenu.cmd), + }), + ], + }), + ], + }), + }); diff --git a/home/desktops/hyprland/ags/js/quicksettings/QuickSettings.js b/home/desktops/hyprland/ags/js/quicksettings/QuickSettings.js new file mode 100644 index 0000000..c39bc1f --- /dev/null +++ b/home/desktops/hyprland/ags/js/quicksettings/QuickSettings.js @@ -0,0 +1,73 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Header from "./widgets/Header.js"; +import PopupWindow from "../misc/PopupWindow.js"; +import { Volume, Microhone, SinkSelector, AppMixer } from "./widgets/Volume.js"; +import { NetworkToggle, WifiSelection } from "./widgets/Network.js"; +import { BluetoothToggle, BluetoothDevices } from "./widgets/Bluetooth.js"; +import { ThemeToggle, ThemeSelector } from "./widgets/Theme.js"; +import { ProfileToggle, ProfileSelector } from "./widgets/AsusProfile.js"; +import Media from "./widgets/Media.js"; +import Brightness from "./widgets/Brightness.js"; +import DND from "./widgets/DND.js"; +import MicMute from "./widgets/MicMute.js"; +import options from "../options.js"; + +const Row = (toggles = [], menus = []) => + Widget.Box({ + vertical: true, + children: [ + Widget.Box({ + class_name: "row horizontal", + children: toggles, + }), + ...menus, + ], + }); + +const Homogeneous = (toggles) => + Widget.Box({ + homogeneous: true, + children: toggles, + }); + +export default () => + PopupWindow({ + name: "quicksettings", + connections: [ + [ + options.bar.position, + (self) => { + self.anchor = ["right", options.bar.position.value]; + if (options.bar.position.value === "top") + self.transition = "slide_down"; + + if (options.bar.position.value === "bottom") + self.transition = "slide_up"; + }, + ], + ], + child: Widget.Box({ + vertical: true, + children: [ + Header(), + Widget.Box({ + class_name: "sliders-box vertical", + vertical: true, + children: [ + Row([Volume()], [SinkSelector(), AppMixer()]), + Microhone(), + Brightness(), + ], + }), + Row( + [Homogeneous([NetworkToggle(), BluetoothToggle()]), DND()], + [WifiSelection(), BluetoothDevices()], + ), + Row( + [Homogeneous([ProfileToggle(), ThemeToggle()]), MicMute()], + [ProfileSelector(), ThemeSelector()], + ), + Media(), + ], + }), + }); diff --git a/home/desktops/hyprland/ags/js/quicksettings/ToggleButton.js b/home/desktops/hyprland/ags/js/quicksettings/ToggleButton.js new file mode 100644 index 0000000..5012b36 --- /dev/null +++ b/home/desktops/hyprland/ags/js/quicksettings/ToggleButton.js @@ -0,0 +1,149 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import App from "resource:///com/github/Aylur/ags/app.js"; +import Variable from "resource:///com/github/Aylur/ags/variable.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import icons from "../icons.js"; + +/** name of the currently opened menu */ +export const opened = Variable(""); +App.connect("window-toggled", (_, name, visible) => { + if (name === "quicksettings" && !visible) + Utils.timeout(500, () => (opened.value = "")); +}); + +/** + * @param {string} name - menu name + * @param {(() => void) | false=} activate + */ +export const Arrow = (name, activate) => { + let deg = 0; + let iconOpened = false; + return Widget.Button({ + child: Widget.Icon({ + icon: icons.ui.arrow.right, + connections: [ + [ + opened, + (icon) => { + if ( + (opened.value === name && !iconOpened) || + (opened.value !== name && iconOpened) + ) { + const step = opened.value === name ? 10 : -10; + iconOpened = !iconOpened; + for (let i = 0; i < 9; ++i) { + Utils.timeout(15 * i, () => { + deg += step; + icon.setCss(`-gtk-icon-transform: rotate(${deg}deg);`); + }); + } + } + }, + ], + ], + }), + on_clicked: () => { + opened.value = opened.value === name ? "" : name; + if (typeof activate === "function") activate(); + }, + }); +}; + +/** + * @param {Object} o + * @param {string} o.name - menu name + * @param {import('gi://Gtk').Gtk.Widget} o.icon + * @param {import('gi://Gtk').Gtk.Widget} o.label + * @param {() => void} o.activate + * @param {() => void} o.deactivate + * @param {boolean=} o.activateOnArrow + * @param {[import('gi://GObject').GObject.Object, () => boolean]} o.connection + */ +export const ArrowToggleButton = ({ + name, + icon, + label, + activate, + deactivate, + activateOnArrow = true, + connection: [service, condition], +}) => + Widget.Box({ + class_name: "toggle-button", + connections: [ + [ + service, + (box) => { + box.toggleClassName("active", condition()); + }, + ], + ], + children: [ + Widget.Button({ + child: Widget.Box({ + hexpand: true, + class_name: "label-box horizontal", + children: [icon, label], + }), + on_clicked: () => { + if (condition()) { + deactivate(); + if (opened.value === name) opened.value = ""; + } else { + activate(); + } + }, + }), + Arrow(name, activateOnArrow && activate), + ], + }); + +/** + * @param {Object} o + * @param {string} o.name - menu name + * @param {import('gi://Gtk').Gtk.Widget} o.icon + * @param {import('gi://Gtk').Gtk.Widget} o.title + * @param {import('gi://Gtk').Gtk.Widget[]} o.content + */ +export const Menu = ({ name, icon, title, content }) => + Widget.Revealer({ + transition: "slide_down", + binds: [["reveal-child", opened, "value", (v) => v === name]], + child: Widget.Box({ + class_names: ["menu", name], + vertical: true, + children: [ + Widget.Box({ + class_name: "title horizontal", + children: [icon, title], + }), + Widget.Separator(), + ...content, + ], + }), + }); + +/** + * @param {Object} o + * @param {import('gi://Gtk').Gtk.Widget} o.icon + * @param {() => void} o.toggle + * @param {[import('gi://GObject').GObject.Object, () => boolean]} o.connection + */ +export const SimpleToggleButton = ({ + icon, + toggle, + connection: [service, condition], +}) => + Widget.Button({ + class_name: "simple-toggle", + connections: [ + [ + service, + (box) => { + box.toggleClassName("active", condition()); + }, + ], + ], + child: icon, + on_clicked: toggle, + }); diff --git a/home/desktops/hyprland/ags/js/quicksettings/widgets/AsusProfile.js b/home/desktops/hyprland/ags/js/quicksettings/widgets/AsusProfile.js new file mode 100644 index 0000000..e2a919d --- /dev/null +++ b/home/desktops/hyprland/ags/js/quicksettings/widgets/AsusProfile.js @@ -0,0 +1,61 @@ +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import icons from "../../icons.js"; +import Asusctl from "../../services/asusctl.js"; +import { ArrowToggleButton, Menu } from "../ToggleButton.js"; + +export const ProfileToggle = () => + ArrowToggleButton({ + name: "asusctl-profile", + icon: Widget.Icon({ + binds: [["icon", Asusctl, "profile", (p) => icons.asusctl.profile[p]]], + }), + label: Widget.Label({ + binds: [["label", Asusctl, "profile"]], + }), + connection: [Asusctl, () => Asusctl.profile !== "Balanced"], + activate: () => Asusctl.setProfile("Quiet"), + deactivate: () => Asusctl.setProfile("Balanced"), + activateOnArrow: false, + }); + +export const ProfileSelector = () => + Menu({ + name: "asusctl-profile", + icon: Widget.Icon({ + binds: [["icon", Asusctl, "profile", (p) => icons.asusctl.profile[p]]], + }), + title: Widget.Label("Profile Selector"), + content: [ + Widget.Box({ + vertical: true, + hexpand: true, + children: [ + Widget.Box({ + vertical: true, + children: Asusctl.profiles.map((prof) => + Widget.Button({ + on_clicked: () => Asusctl.setProfile(prof), + child: Widget.Box({ + children: [ + Widget.Icon(icons.asusctl.profile[prof]), + Widget.Label(prof), + ], + }), + }), + ), + }), + ], + }), + Widget.Separator(), + Widget.Button({ + on_clicked: () => Utils.execAsync("rog-control-center"), + child: Widget.Box({ + children: [ + Widget.Icon(icons.ui.settings), + Widget.Label("Rog Control Center"), + ], + }), + }), + ], + }); diff --git a/home/desktops/hyprland/ags/js/quicksettings/widgets/Bluetooth.js b/home/desktops/hyprland/ags/js/quicksettings/widgets/Bluetooth.js new file mode 100644 index 0000000..142d8bc --- /dev/null +++ b/home/desktops/hyprland/ags/js/quicksettings/widgets/Bluetooth.js @@ -0,0 +1,95 @@ +import Bluetooth from "resource:///com/github/Aylur/ags/service/bluetooth.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import icons from "../../icons.js"; +import { Menu, ArrowToggleButton } from "../ToggleButton.js"; + +export const BluetoothToggle = () => + ArrowToggleButton({ + name: "bluetooth", + icon: Widget.Icon({ + connections: [ + [ + Bluetooth, + (icon) => { + icon.icon = Bluetooth.enabled + ? icons.bluetooth.enabled + : icons.bluetooth.disabled; + }, + ], + ], + }), + label: Widget.Label({ + truncate: "end", + connections: [ + [ + Bluetooth, + (label) => { + if (!Bluetooth.enabled) return (label.label = "Disabled"); + + if (Bluetooth.connectedDevices.length === 0) + return (label.label = "Not Connected"); + + if (Bluetooth.connectedDevices.length === 1) + return (label.label = Bluetooth.connectedDevices[0].alias); + + label.label = `${Bluetooth.connectedDevices.length} Connected`; + }, + ], + ], + }), + connection: [Bluetooth, () => Bluetooth.enabled], + deactivate: () => (Bluetooth.enabled = false), + activate: () => (Bluetooth.enabled = true), + }); + +const DeviceItem = (device) => + Widget.Box({ + children: [ + Widget.Icon(device.icon_name + "-symbolic"), + Widget.Label(device.name), + Widget.Label({ + label: `${device.battery_percentage}%`, + binds: [["visible", device, "battery-percentage", (p) => p > 0]], + }), + Widget.Box({ hexpand: true }), + Widget.Spinner({ + binds: [ + ["active", device, "connecting"], + ["visible", device, "connecting"], + ], + }), + Widget.Switch({ + active: device.connected, + binds: [["visible", device, "connecting", (c) => !c]], + connections: [ + [ + "notify::active", + ({ active }) => { + device.setConnection(active); + }, + ], + ], + }), + ], + }); + +export const BluetoothDevices = () => + Menu({ + name: "bluetooth", + icon: Widget.Icon(icons.bluetooth.disabled), + title: Widget.Label("Bluetooth"), + content: [ + Widget.Box({ + hexpand: true, + vertical: true, + binds: [ + [ + "children", + Bluetooth, + "devices", + (ds) => ds.filter((d) => d.name).map(DeviceItem), + ], + ], + }), + ], + }); diff --git a/home/desktops/hyprland/ags/js/quicksettings/widgets/Brightness.js b/home/desktops/hyprland/ags/js/quicksettings/widgets/Brightness.js new file mode 100644 index 0000000..35d16e3 --- /dev/null +++ b/home/desktops/hyprland/ags/js/quicksettings/widgets/Brightness.js @@ -0,0 +1,29 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import icons from "../../icons.js"; +import Brightness from "../../services/brightness.js"; + +const BrightnessSlider = () => + Widget.Slider({ + draw_value: false, + hexpand: true, + binds: [["value", Brightness, "screen"]], + on_change: ({ value }) => (Brightness.screen = value), + }); + +export default () => + Widget.Box({ + children: [ + Widget.Button({ + child: Widget.Icon(icons.brightness.indicator), + binds: [ + [ + "tooltip-text", + Brightness, + "screen", + (v) => `Screen Brightness: ${Math.floor(v * 100)}%`, + ], + ], + }), + BrightnessSlider(), + ], + }); diff --git a/home/desktops/hyprland/ags/js/quicksettings/widgets/DND.js b/home/desktops/hyprland/ags/js/quicksettings/widgets/DND.js new file mode 100644 index 0000000..72e6c26 --- /dev/null +++ b/home/desktops/hyprland/ags/js/quicksettings/widgets/DND.js @@ -0,0 +1,23 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Notifications from "resource:///com/github/Aylur/ags/service/notifications.js"; +import icons from "../../icons.js"; +import { SimpleToggleButton } from "../ToggleButton.js"; + +export default () => + SimpleToggleButton({ + icon: Widget.Icon({ + connections: [ + [ + Notifications, + (icon) => { + icon.icon = Notifications.dnd + ? icons.notifications.silent + : icons.notifications.noisy; + }, + "notify::dnd", + ], + ], + }), + toggle: () => (Notifications.dnd = !Notifications.dnd), + connection: [Notifications, () => Notifications.dnd], + }); diff --git a/home/desktops/hyprland/ags/js/quicksettings/widgets/Header.js b/home/desktops/hyprland/ags/js/quicksettings/widgets/Header.js new file mode 100644 index 0000000..7395e4a --- /dev/null +++ b/home/desktops/hyprland/ags/js/quicksettings/widgets/Header.js @@ -0,0 +1,48 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Battery from "resource:///com/github/Aylur/ags/service/battery.js"; +import PowerMenu from "../../services/powermenu.js"; +import Lockscreen from "../../services/lockscreen.js"; +import Avatar from "../../misc/Avatar.js"; +import icons from "../../icons.js"; +import { openSettings } from "../../settings/theme.js"; +import { uptime } from "../../variables.js"; + +export default () => + Widget.Box({ + class_name: "header horizontal", + children: [ + Avatar(), + Widget.Box({ + hpack: "end", + vpack: "center", + hexpand: true, + children: [ + Widget.Box({ + class_name: "battery horizontal", + children: [ + Widget.Icon({ binds: [["icon", Battery, "icon-name"]] }), + Widget.Label({ + binds: [["label", Battery, "percent", (p) => `${p}%`]], + }), + ], + }), + Widget.Label({ + class_name: "uptime", + binds: [["label", uptime, "value", (v) => `up: ${v}`]], + }), + Widget.Button({ + on_clicked: openSettings, + child: Widget.Icon(icons.ui.settings), + }), + Widget.Button({ + on_clicked: () => Lockscreen.lockscreen(), + child: Widget.Icon(icons.lock), + }), + Widget.Button({ + on_clicked: () => PowerMenu.action("shutdown"), + child: Widget.Icon(icons.powermenu.shutdown), + }), + ], + }), + ], + }); diff --git a/home/desktops/hyprland/ags/js/quicksettings/widgets/Media.js b/home/desktops/hyprland/ags/js/quicksettings/widgets/Media.js new file mode 100644 index 0000000..b6c5694 --- /dev/null +++ b/home/desktops/hyprland/ags/js/quicksettings/widgets/Media.js @@ -0,0 +1,106 @@ +import Mpris from "resource:///com/github/Aylur/ags/service/mpris.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import * as mpris from "../../misc/mpris.js"; +import options from "../../options.js"; + +/** @param {import('types/service/mpris').MprisPlayer} player */ +const Footer = (player) => + Widget.CenterBox({ + class_name: "footer-box", + children: [ + Widget.Box({ + class_name: "position", + children: [ + mpris.PositionLabel(player), + mpris.Slash(player), + mpris.LengthLabel(player), + ], + }), + Widget.Box({ + class_name: "controls", + children: [ + mpris.ShuffleButton(player), + mpris.PreviousButton(player), + mpris.PlayPauseButton(player), + mpris.NextButton(player), + mpris.LoopButton(player), + ], + }), + mpris.PlayerIcon(player, { + symbolic: false, + hexpand: true, + hpack: "end", + }), + ], + }); + +/** @param {import('types/service/mpris').MprisPlayer} player */ +const TextBox = (player) => + Widget.Box({ + children: [ + mpris.CoverArt(player, { + hpack: "end", + hexpand: false, + }), + Widget.Box({ + hexpand: true, + vertical: true, + class_name: "labels", + children: [ + mpris.TitleLabel(player, { + xalign: 0, + justification: "left", + wrap: true, + }), + mpris.ArtistLabel(player, { + xalign: 0, + justification: "left", + wrap: true, + }), + ], + }), + ], + }); + +/** @param {import('types/service/mpris').MprisPlayer} player */ +const PlayerBox = (player) => + Widget.Box({ + class_name: `player ${player.name}`, + child: mpris.BlurredCoverArt(player, { + hexpand: true, + child: Widget.Box({ + hexpand: true, + vertical: true, + children: [ + TextBox(player), + mpris.PositionSlider(player), + Footer(player), + ], + }), + }), + }); + +export default () => + Widget.Box({ + vertical: true, + class_name: "media vertical", + connections: [ + [ + "draw", + (self) => { + self.visible = Mpris.players.length > 0; + }, + ], + ], + binds: [ + [ + "children", + Mpris, + "players", + (ps) => + ps + .filter((p) => !options.mpris.black_list.value.includes(p.identity)) + .map(PlayerBox), + ], + ], + }); diff --git a/home/desktops/hyprland/ags/js/quicksettings/widgets/MicMute.js b/home/desktops/hyprland/ags/js/quicksettings/widgets/MicMute.js new file mode 100644 index 0000000..3905c7c --- /dev/null +++ b/home/desktops/hyprland/ags/js/quicksettings/widgets/MicMute.js @@ -0,0 +1,23 @@ +import Audio from "resource:///com/github/Aylur/ags/service/audio.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import icons from "../../icons.js"; +import { SimpleToggleButton } from "../ToggleButton.js"; + +export default () => + SimpleToggleButton({ + icon: Widget.Icon({ + connections: [ + [ + Audio, + (icon) => { + icon.icon = Audio.microphone?.is_muted + ? icons.audio.mic.muted + : icons.audio.mic.high; + }, + "microphone-changed", + ], + ], + }), + toggle: () => (Audio.microphone.is_muted = !Audio.microphone.is_muted), + connection: [Audio, () => Audio.microphone?.is_muted], + }); diff --git a/home/desktops/hyprland/ags/js/quicksettings/widgets/Network.js b/home/desktops/hyprland/ags/js/quicksettings/widgets/Network.js new file mode 100644 index 0000000..87404d6 --- /dev/null +++ b/home/desktops/hyprland/ags/js/quicksettings/widgets/Network.js @@ -0,0 +1,91 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Network from "resource:///com/github/Aylur/ags/service/network.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import icons from "../../icons.js"; +import { Menu, ArrowToggleButton } from "../ToggleButton.js"; +import Applications from "resource:///com/github/Aylur/ags/service/applications.js"; + +export const NetworkToggle = () => + ArrowToggleButton({ + name: "network", + icon: Widget.Icon({ + connections: [ + [ + Network, + (icon) => { + icon.icon = Network.wifi.icon_name || ""; + }, + ], + ], + }), + label: Widget.Label({ + truncate: "end", + connections: [ + [ + Network, + (label) => { + label.label = Network.wifi.ssid || "Not Connected"; + }, + ], + ], + }), + connection: [Network, () => Network.wifi.enabled], + deactivate: () => (Network.wifi.enabled = false), + activate: () => { + Network.wifi.enabled = true; + Network.wifi.scan(); + }, + }); + +export const WifiSelection = () => + Menu({ + name: "network", + icon: Widget.Icon({ + connections: [ + [ + Network, + (icon) => { + icon.icon = Network.wifi.icon_name; + }, + ], + ], + }), + title: Widget.Label("Wifi Selection"), + content: [ + Widget.Box({ + vertical: true, + connections: [ + [ + Network, + (box) => + (box.children = Network.wifi?.access_points.map((ap) => + Widget.Button({ + on_clicked: () => + Utils.execAsync(`nmcli device wifi connect ${ap.bssid}`), + child: Widget.Box({ + children: [ + Widget.Icon(ap.iconName), + Widget.Label(ap.ssid || ""), + ap.active && + Widget.Icon({ + icon: icons.ui.tick, + hexpand: true, + hpack: "end", + }), + ], + }), + }), + )), + ], + ], + }), + Widget.Separator(), + Widget.Button({ + on_clicked: () => + Applications.query("gnome-control-center")?.[0].launch(), + child: Widget.Box({ + children: [Widget.Icon(icons.ui.settings), Widget.Label("Network")], + }), + }), + ], + }); diff --git a/home/desktops/hyprland/ags/js/quicksettings/widgets/Theme.js b/home/desktops/hyprland/ags/js/quicksettings/widgets/Theme.js new file mode 100644 index 0000000..186bf7e --- /dev/null +++ b/home/desktops/hyprland/ags/js/quicksettings/widgets/Theme.js @@ -0,0 +1,57 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import { ArrowToggleButton, Menu, opened } from "../ToggleButton.js"; +import themes from "../../themes.js"; +import icons from "../../icons.js"; +import options from "../../options.js"; +import { setTheme, openSettings } from "../../settings/theme.js"; + +export const ThemeToggle = () => + ArrowToggleButton({ + name: "theme", + icon: Widget.Label({ binds: [["label", options.theme.icon]] }), + label: Widget.Label({ binds: [["label", options.theme.name]] }), + connection: [opened, () => opened.value === "theme"], + activate: () => opened.setValue("theme"), + activateOnArrow: false, + deactivate: () => {}, + }); + +export const ThemeSelector = () => + Menu({ + name: "theme", + icon: Widget.Label({ + binds: [["label", options.theme.icon]], + }), + title: Widget.Label("Theme Selector"), + content: [ + ...themes.map(({ name, icon }) => + Widget.Button({ + on_clicked: () => setTheme(name), + child: Widget.Box({ + children: [ + Widget.Label(icon), + Widget.Label(name), + Widget.Icon({ + icon: icons.ui.tick, + hexpand: true, + hpack: "end", + binds: [ + ["visible", options.theme.name, "value", (v) => v === name], + ], + }), + ], + }), + }), + ), + Widget.Separator(), + Widget.Button({ + on_clicked: openSettings, + child: Widget.Box({ + children: [ + Widget.Icon(icons.ui.settings), + Widget.Label("Theme Settings"), + ], + }), + }), + ], + }); diff --git a/home/desktops/hyprland/ags/js/quicksettings/widgets/Volume.js b/home/desktops/hyprland/ags/js/quicksettings/widgets/Volume.js new file mode 100644 index 0000000..b972a10 --- /dev/null +++ b/home/desktops/hyprland/ags/js/quicksettings/widgets/Volume.js @@ -0,0 +1,194 @@ +import Audio from "resource:///com/github/Aylur/ags/service/audio.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import icons from "../../icons.js"; +import FontIcon from "../../misc/FontIcon.js"; +import { getAudioTypeIcon } from "../../utils.js"; +import { Arrow } from "../ToggleButton.js"; +import { Menu } from "../ToggleButton.js"; + +/** @param {'speaker' | 'microphone'=} type */ +const VolumeIndicator = (type = "speaker") => + Widget.Button({ + on_clicked: () => (Audio[type].is_muted = !Audio[type].is_muted), + child: Widget.Icon({ + connections: [ + [ + Audio, + (icon) => { + if (!Audio[type]) return; + + icon.icon = + type === "speaker" + ? getAudioTypeIcon(Audio[type].icon_name || "") + : icons.audio.mic.high; + + icon.tooltip_text = `Volume ${Math.floor( + Audio[type].volume * 100, + )}%`; + }, + `${type}-changed`, + ], + ], + }), + }); + +/** @param {'speaker' | 'microphone'=} type */ +const VolumeSlider = (type = "speaker") => + Widget.Slider({ + hexpand: true, + draw_value: false, + on_change: ({ value }) => (Audio[type].volume = value), + connections: [ + [ + Audio, + (slider) => { + slider.value = Audio[type]?.volume; + }, + `${type}-changed`, + ], + ], + }); + +export const Volume = () => + Widget.Box({ + children: [ + VolumeIndicator("speaker"), + VolumeSlider("speaker"), + Widget.Box({ + vpack: "center", + child: Arrow("sink-selector"), + }), + Widget.Box({ + vpack: "center", + child: Arrow("app-mixer"), + connections: [ + [ + Audio, + (box) => { + box.visible = Audio.apps.length > 0; + }, + ], + ], + }), + ], + }); + +export const Microhone = () => + Widget.Box({ + class_name: "slider horizontal", + binds: [["visible", Audio, "recorders", (r) => r.length > 0]], + children: [VolumeIndicator("microphone"), VolumeSlider("microphone")], + }); + +/** @param {import('types/service/audio').Stream} stream */ +const MixerItem = (stream) => + Widget.Box({ + hexpand: true, + class_name: "mixer-item horizontal", + children: [ + Widget.Icon({ + binds: [["tooltipText", stream, "name"]], + connections: [ + [ + stream, + (icon) => { + icon.icon = Utils.lookUpIcon(stream.name || "") + ? stream.name || "" + : icons.mpris.fallback; + }, + ], + ], + }), + Widget.Box({ + vertical: true, + children: [ + Widget.Label({ + xalign: 0, + truncate: "end", + binds: [["label", stream, "description"]], + }), + Widget.Slider({ + hexpand: true, + draw_value: false, + binds: [["value", stream, "volume"]], + on_change: ({ value }) => (stream.volume = value), + }), + ], + }), + Widget.Label({ + xalign: 1, + connections: [ + [ + stream, + (l) => { + l.label = `${Math.floor(stream.volume * 100)}%`; + }, + ], + ], + }), + ], + }); + +/** @param {import('types/service/audio').Stream} stream */ +const SinkItem = (stream) => + Widget.Button({ + hexpand: true, + on_clicked: () => (Audio.speaker = stream), + child: Widget.Box({ + children: [ + Widget.Icon({ + icon: getAudioTypeIcon(stream.icon_name || ""), + tooltip_text: stream.icon_name, + }), + Widget.Label( + (stream.description || "").split(" ").slice(0, 4).join(" "), + ), + Widget.Icon({ + icon: icons.ui.tick, + hexpand: true, + hpack: "end", + binds: [["visible", Audio, "speaker", (s) => s === stream]], + }), + ], + }), + }); + +const SettingsButton = () => + Widget.Button({ + on_clicked: () => Utils.execAsync("pavucontrol"), + hexpand: true, + child: Widget.Box({ + children: [Widget.Icon(icons.ui.settings), Widget.Label("Settings")], + }), + }); + +export const AppMixer = () => + Menu({ + name: "app-mixer", + icon: FontIcon(icons.audio.mixer), + title: Widget.Label("App Mixer"), + content: [ + Widget.Box({ + vertical: true, + binds: [["children", Audio, "apps", (a) => a.map(MixerItem)]], + }), + Widget.Separator(), + SettingsButton(), + ], + }); + +export const SinkSelector = () => + Menu({ + name: "sink-selector", + icon: Widget.Icon(icons.audio.type.headset), + title: Widget.Label("Sink Selector"), + content: [ + Widget.Box({ + vertical: true, + binds: [["children", Audio, "speakers", (s) => s.map(SinkItem)]], + }), + Widget.Separator(), + SettingsButton(), + ], + }); diff --git a/home/desktops/hyprland/ags/js/screencorner/ScreenCorners.js b/home/desktops/hyprland/ags/js/screencorner/ScreenCorners.js new file mode 100644 index 0000000..87c7d1b --- /dev/null +++ b/home/desktops/hyprland/ags/js/screencorner/ScreenCorners.js @@ -0,0 +1,76 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Gtk from "gi://Gtk"; +import options from "../options.js"; + +/** @param {'topleft' | 'topright' | 'bottomleft' | 'bottomright'} place */ +const Corner = (place) => + Widget.DrawingArea({ + class_name: "corner", + hexpand: true, + vexpand: true, + hpack: place.includes("left") ? "start" : "end", + vpack: place.includes("top") ? "start" : "end", + connections: [ + [ + options.radii, + (self) => { + const r = options.radii.value * 2; + self.set_size_request(r, r); + }, + ], + ], + setup: (self) => + self.connect("draw", (self, cr) => { + const context = self.get_style_context(); + const c = context.get_property( + "background-color", + Gtk.StateFlags.NORMAL, + ); + const r = context.get_property("border-radius", Gtk.StateFlags.NORMAL); + + switch (place) { + case "topleft": + cr.arc(r, r, r, Math.PI, (3 * Math.PI) / 2); + cr.lineTo(0, 0); + break; + + case "topright": + cr.arc(0, r, r, (3 * Math.PI) / 2, 2 * Math.PI); + cr.lineTo(r, 0); + break; + + case "bottomleft": + cr.arc(r, 0, r, Math.PI / 2, Math.PI); + cr.lineTo(0, r); + break; + + case "bottomright": + cr.arc(0, 0, r, 0, Math.PI / 2); + cr.lineTo(r, r); + break; + } + + cr.closePath(); + cr.setSourceRGBA(c.red, c.green, c.blue, c.alpha); + cr.fill(); + }), + }); + +/** @type {Array<'topleft' | 'topright' | 'bottomleft' | 'bottomright'>} */ +const places = ["topleft", "topright", "bottomleft", "bottomright"]; + +/** @param {number} monitor */ +export default (monitor) => + places.map((place) => + Widget.Window({ + name: `corner${monitor}${place}`, + monitor, + class_name: "corner", + anchor: [ + place.includes("top") ? "top" : "bottom", + place.includes("right") ? "right" : "left", + ], + binds: [["visible", options.desktop.screen_corners]], + child: Corner(place), + }), + ); diff --git a/home/desktops/hyprland/ags/js/services/asusctl.js b/home/desktops/hyprland/ags/js/services/asusctl.js new file mode 100644 index 0000000..df2372c --- /dev/null +++ b/home/desktops/hyprland/ags/js/services/asusctl.js @@ -0,0 +1,70 @@ +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import Service from "resource:///com/github/Aylur/ags/service.js"; + +class Asusctl extends Service { + static { + Service.register( + this, + {}, + { + profile: ["string", "r"], + mode: ["string", "r"], + }, + ); + } + + profiles = Object.freeze(["Performance", "Balanced", "Quiet"]); + #profile = "Balanced"; + #mode = "Hyprid"; + + nextProfile() { + Utils.execAsync("asusctl profile -n") + .then(() => { + this.#profile = Utils.exec("asusctl profile -p").split(" ")[3]; + this.changed("profile"); + }) + .catch(console.error); + } + + /** @param {'Performance' | 'Balanced' | 'Quiet'} prof */ + setProfile(prof) { + Utils.execAsync(`asusctl profile --profile-set ${prof}`) + .then(() => { + this.#profile = prof; + this.changed("profile"); + }) + .catch(console.error); + } + + nextMode() { + Utils.execAsync( + `supergfxctl -m ${this.#mode === "Hybrid" ? "Integrated" : "Hybrid"}`, + ) + .then(() => { + this.#mode = Utils.exec("supergfxctl -g"); + this.changed("profile"); + }) + .catch(console.error); + } + + constructor() { + super(); + + if (Utils.exec("which asusctl")) { + this.available = true; + this.#profile = Utils.exec("asusctl profile -p").split(" ")[3]; + Utils.execAsync("supergfxctl -g").then((mode) => (this.#mode = mode)); + } else { + this.available = false; + } + } + + get profile() { + return this.#profile; + } + get mode() { + return this.#mode; + } +} + +export default new Asusctl(); diff --git a/home/desktops/hyprland/ags/js/services/brightness.js b/home/desktops/hyprland/ags/js/services/brightness.js new file mode 100644 index 0000000..13ee419 --- /dev/null +++ b/home/desktops/hyprland/ags/js/services/brightness.js @@ -0,0 +1,72 @@ +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import Service from "resource:///com/github/Aylur/ags/service.js"; +import options from "../options.js"; +import { dependencies } from "../utils.js"; + +const KBD = options.brightnessctlKBD; + +class Brightness extends Service { + static { + Service.register( + this, + {}, + { + screen: ["float", "rw"], + kbd: ["int", "rw"], + }, + ); + } + + #kbd = 0; + #kbdMax = 3; + #screen = 0; + + get kbd() { + return this.#kbd; + } + get screen() { + return this.#screen; + } + + set kbd(value) { + if (!dependencies(["brightnessctl"])) return; + + if (value < 0 || value > this.#kbdMax) return; + + Utils.execAsync(`brightnessctl -d ${KBD} s ${value} -q`) + .then(() => { + this.#kbd = value; + this.changed("kbd"); + }) + .catch(console.error); + } + + set screen(percent) { + if (!dependencies(["brightnessctl"])) return; + + if (percent < 0) percent = 0; + + if (percent > 1) percent = 1; + + Utils.execAsync(`brightnessctl s ${percent * 100}% -q`) + .then(() => { + this.#screen = percent; + this.changed("screen"); + }) + .catch(console.error); + } + + constructor() { + super(); + + if (dependencies(["brightnessctl"])) { + this.#kbd = Number(Utils.exec(`brightnessctl -d ${KBD} g`)); + this.#kbdMax = Number(Utils.exec(`brightnessctl -d ${KBD} m`)); + this.#screen = + Number(Utils.exec("brightnessctl g")) / + Number(Utils.exec("brightnessctl m")); + } + } +} + +export default new Brightness(); diff --git a/home/desktops/hyprland/ags/js/services/colorpicker.js b/home/desktops/hyprland/ags/js/services/colorpicker.js new file mode 100644 index 0000000..65398a2 --- /dev/null +++ b/home/desktops/hyprland/ags/js/services/colorpicker.js @@ -0,0 +1,73 @@ +import Notifications from "resource:///com/github/Aylur/ags/service/notifications.js"; +import { Variable } from "resource:///com/github/Aylur/ags/variable.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import Service from "resource:///com/github/Aylur/ags/service.js"; +import { dependencies } from "../utils.js"; + +const COLORS_CACHE = Utils.CACHE_DIR + "/colorpicker.json"; + +class Colors extends Service { + static { + Service.register( + this, + {}, + { + colors: ["jsobject"], + }, + ); + } + + /** @type {Variable} */ + #colors = new Variable([]); + get colors() { + return this.#colors.value; + } + + #notifID = 0; + + constructor() { + super(); + + this.#colors.connect("changed", () => this.changed("colors")); + + Utils.readFileAsync(COLORS_CACHE) + .then((out) => this.#colors.setValue(JSON.parse(out || "[]"))) + .catch(() => print("no colorpicker cache found")); + } + + /** @param {string} color */ + wlCopy(color) { + Utils.execAsync(["wl-copy", color]).catch((err) => console.error(err)); + } + + async pick() { + if (!dependencies(["hyprpicker"])) return; + + const color = await Utils.execAsync("hyprpicker"); + if (!color) return; + + this.wlCopy(color); + const list = this.#colors.value; + if (!list.includes(color)) { + list.push(color); + if (list.length > 10) list.shift(); + + this.#colors.value = list; + Utils.writeFile(JSON.stringify(list, null, 2), COLORS_CACHE).catch( + (err) => console.error(err), + ); + } + + this.#notifID = Notifications.Notify( + "Color Picker", + this.#notifID, + "color-select-symbolic", + color, + "", + [], + {}, + ); + } +} + +export default new Colors(); diff --git a/home/desktops/hyprland/ags/js/services/lockscreen.js b/home/desktops/hyprland/ags/js/services/lockscreen.js new file mode 100644 index 0000000..ca3c603 --- /dev/null +++ b/home/desktops/hyprland/ags/js/services/lockscreen.js @@ -0,0 +1,30 @@ +import Service from "resource:///com/github/Aylur/ags/service.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import App from "resource:///com/github/Aylur/ags/app.js"; +const authpy = App.configDir + "/js/lockscreen/auth.py"; + +class Lockscreen extends Service { + static { + Service.register(this, { + lock: ["boolean"], + authenticating: ["boolean"], + }); + } + + lockscreen() { + this.emit("lock", true); + } + + /** @param {string} password */ + auth(password) { + this.emit("authenticating", true); + Utils.execAsync([authpy, password]) + .then((out) => { + this.emit("lock", out !== "True"); + this.emit("authenticating", false); + }) + .catch((err) => console.error(err)); + } +} + +export default new Lockscreen(); diff --git a/home/desktops/hyprland/ags/js/services/onScreenIndicator.js b/home/desktops/hyprland/ags/js/services/onScreenIndicator.js new file mode 100644 index 0000000..f1d16ad --- /dev/null +++ b/home/desktops/hyprland/ags/js/services/onScreenIndicator.js @@ -0,0 +1,58 @@ +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import Service from "resource:///com/github/Aylur/ags/service.js"; +import Audio from "resource:///com/github/Aylur/ags/service/audio.js"; +import icons from "../icons.js"; +import { getAudioTypeIcon } from "../utils.js"; +import Brightness from "./brightness.js"; + +class Indicator extends Service { + static { + Service.register(this, { + popup: ["double", "string"], + }); + } + + #delay = 1500; + #count = 0; + + /** + * @param {number} value - 0 < v < 1 + * @param {string} icon + */ + popup(value, icon) { + this.emit("popup", value, icon); + this.#count++; + Utils.timeout(this.#delay, () => { + this.#count--; + + if (this.#count === 0) this.emit("popup", -1, icon); + }); + } + + speaker() { + this.popup( + Audio.speaker?.volume || 0, + getAudioTypeIcon(Audio.speaker?.icon_name || ""), + ); + } + + display() { + // brightness is async, so lets wait a bit + Utils.timeout(10, () => + this.popup(Brightness.screen, icons.brightness.screen), + ); + } + + kbd() { + // brightness is async, so lets wait a bit + Utils.timeout(10, () => + this.popup((Brightness.kbd * 33 + 1) / 100, icons.brightness.keyboard), + ); + } + + connect(event = "popup", callback) { + return super.connect(event, callback); + } +} + +export default new Indicator(); diff --git a/home/desktops/hyprland/ags/js/services/powermenu.js b/home/desktops/hyprland/ags/js/services/powermenu.js new file mode 100644 index 0000000..c4abd82 --- /dev/null +++ b/home/desktops/hyprland/ags/js/services/powermenu.js @@ -0,0 +1,43 @@ +import App from "resource:///com/github/Aylur/ags/app.js"; +import Service from "resource:///com/github/Aylur/ags/service.js"; + +class PowerMenu extends Service { + static { + Service.register( + this, + {}, + { + title: ["string"], + cmd: ["string"], + }, + ); + } + + #title = ""; + #cmd = ""; + + get title() { + return this.#title; + } + get cmd() { + return this.#cmd; + } + + /** @param {'sleep' | 'reboot' | 'logout' | 'shutdown'} action */ + action(action) { + [this.#cmd, this.#title] = { + sleep: ["systemctl suspend", "Sleep"], + reboot: ["systemctl reboot", "Reboot"], + logout: ["pkill Hyprland", "Log Out"], + shutdown: ["shutdown now", "Shutdown"], + }[action]; + + this.notify("cmd"); + this.notify("title"); + this.emit("changed"); + App.closeWindow("powermenu"); + App.openWindow("verification"); + } +} + +export default new PowerMenu(); diff --git a/home/desktops/hyprland/ags/js/services/screenrecord.js b/home/desktops/hyprland/ags/js/services/screenrecord.js new file mode 100644 index 0000000..3421f4c --- /dev/null +++ b/home/desktops/hyprland/ags/js/services/screenrecord.js @@ -0,0 +1,112 @@ +import Service from "resource:///com/github/Aylur/ags/service.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import App from "resource:///com/github/Aylur/ags/app.js"; +import GLib from "gi://GLib"; +import { dependencies } from "../utils.js"; + +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"], + }, + ); + } + + #path = GLib.get_home_dir() + "/Videos/Screencasting"; + #file = ""; + #interval = 0; + + recording = false; + timer = 0; + + async start() { + if (!dependencies(["slurp", "wf-recorder"])) return; + + if (this.recording) return; + + const area = await Utils.execAsync("slurp"); + Utils.ensureDirectory(this.#path); + this.#file = `${this.#path}/${now()}.mp4`; + Utils.execAsync(["wf-recorder", "-g", area, "-f", this.#file]); + this.recording = true; + this.changed("recording"); + + this.timer = 0; + this.#interval = Utils.interval(1000, () => { + this.changed("timer"); + this.timer++; + }); + } + + async stop() { + if (!dependencies(["notify-send"])) return; + + if (!this.recording) return; + + Utils.execAsync("killall -INT wf-recorder"); + this.recording = false; + this.changed("recording"); + GLib.source_remove(this.#interval); + + const res = await Utils.execAsync([ + "notify-send", + "-A", + "files=Show in Files", + "-A", + "view=View", + "-i", + "video-x-generic-symbolic", + "Screenrecord", + this.#file, + ]); + + if (res === "files") Utils.execAsync("xdg-open " + this.#path); + + if (res === "view") Utils.execAsync("xdg-open " + this.#file); + } + + async screenshot(full = false) { + if (!dependencies(["slurp", "wayshot"])) return; + + const path = GLib.get_home_dir() + "/Pictures/Screenshots"; + const file = `${path}/${now()}.png`; + Utils.ensureDirectory(path); + + await Utils.execAsync( + ["wayshot", "-f", file].concat( + full ? [] : ["-s", await Utils.execAsync("slurp")], + ), + ); + + Utils.execAsync(["bash", "-c", `wl-copy < ${file}`]); + + const res = await Utils.execAsync([ + "notify-send", + "-A", + "files=Show in Files", + "-A", + "view=View", + "-A", + "edit=Edit", + "-i", + file, + "Screenshot", + file, + ]); + if (res === "files") Utils.execAsync("xdg-open " + path); + + if (res === "view") Utils.execAsync("xdg-open " + file); + + if (res === "edit") Utils.execAsync(["swappy", "-f", file]); + + App.closeWindow("dashboard"); + } +} + +export default new Recorder(); diff --git a/home/desktops/hyprland/ags/js/settings/SettingsDialog.js b/home/desktops/hyprland/ags/js/settings/SettingsDialog.js new file mode 100644 index 0000000..e80b15f --- /dev/null +++ b/home/desktops/hyprland/ags/js/settings/SettingsDialog.js @@ -0,0 +1,326 @@ +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import App from "resource:///com/github/Aylur/ags/app.js"; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import RegularWindow from "../misc/RegularWindow.js"; +import Variable from "resource:///com/github/Aylur/ags/variable.js"; +import icons from "../icons.js"; +import { getOptions, getValues } from "./option.js"; +import options from "../options.js"; + +const optionsList = getOptions(); +const categories = Array.from( + new Set(optionsList.map((opt) => opt.category)), +).filter((category) => category !== "exclude"); + +const currentPage = Variable(categories[0]); +const search = Variable(""); +const showSearch = Variable(false); +showSearch.connect("changed", ({ value }) => { + if (!value) search.value = ""; +}); + +/** @param {import('./option.js').Opt} opt */ +const EnumSetter = (opt) => { + const lbl = Widget.Label({ binds: [["label", opt]] }); + const step = (dir = 1) => { + const i = opt.enums.findIndex((i) => i === lbl.label); + opt.setValue( + dir > 0 + ? i + dir > opt.enums.length - 1 + ? opt.enums[0] + : opt.enums[i + dir] + : i + dir < 0 + ? opt.enums[opt.enums.length - 1] + : opt.enums[i + dir], + true, + ); + }; + const next = Widget.Button({ + child: Widget.Icon(icons.ui.arrow.right), + on_clicked: () => step(+1), + }); + const prev = Widget.Button({ + child: Widget.Icon(icons.ui.arrow.left), + on_clicked: () => step(-1), + }); + return Widget.Box({ + class_name: "enum-setter", + children: [prev, lbl, next], + }); +}; + +/** @param {import('./option.js').Opt} opt */ +const Setter = (opt) => { + switch (opt.type) { + case "number": + return Widget.SpinButton({ + setup(self) { + self.set_range(0, 1000); + self.set_increments(1, 5); + }, + connections: [ + ["value-changed", (self) => opt.setValue(self.value, true)], + [opt, (self) => (self.value = opt.value)], + ], + }); + case "float": + case "object": + return Widget.Entry({ + on_accept: (self) => opt.setValue(JSON.parse(self.text || ""), true), + connections: [[opt, (self) => (self.text = JSON.stringify(opt.value))]], + }); + case "string": + return Widget.Entry({ + on_accept: (self) => opt.setValue(self.text, true), + connections: [[opt, (self) => (self.text = opt.value)]], + }); + case "enum": + return EnumSetter(opt); + case "boolean": + return Widget.Switch({ + connections: [ + ["notify::active", (self) => opt.setValue(self.active, true)], + [opt, (self) => (self.active = opt.value)], + ], + }); + case "img": + return Widget.FileChooserButton({ + connections: [ + [ + "selection-changed", + (self) => { + opt.setValue(self.get_uri()?.replace("file://", ""), true); + }, + ], + ], + }); + case "font": + return Widget.FontButton({ + show_size: false, + use_size: false, + connections: [ + ["notify::font", ({ font }) => opt.setValue(font, true)], + [opt, (self) => (self.font = opt.value)], + ], + }); + default: + return Widget.Label({ + label: "no setter with type " + opt.type, + }); + } +}; + +/** @param {import('./option.js').Opt} opt */ +const Row = (opt) => + Widget.Box({ + class_name: "row", + setup: (self) => (self.opt = opt), + children: [ + Widget.Box({ + vertical: true, + vpack: "center", + children: [ + opt.title && + Widget.Label({ + xalign: 0, + class_name: "summary", + label: opt.title, + }), + Widget.Label({ + xalign: 0, + class_name: "id", + label: `id: "${opt.id}"`, + }), + ], + }), + Widget.Box({ hexpand: true }), + Widget.Box({ + vpack: "center", + vertical: true, + children: [ + Widget.Box({ + hpack: "end", + child: Setter(opt), + }), + opt.note && + Widget.Label({ + xalign: 1, + class_name: "note", + label: opt.note, + }), + ], + }), + ], + }); + +/** @param {string} category */ +const Page = (category) => + Widget.Scrollable({ + vexpand: true, + class_name: "page", + child: Widget.Box({ + class_name: "page-content vertical", + vertical: true, + connections: [ + [ + search, + (self) => { + for (const child of self.children) { + child.visible = + child.opt.id.includes(search.value) || + child.opt.title.includes(search.value) || + child.opt.note.includes(search.value); + } + }, + ], + ], + children: optionsList + .filter((opt) => opt.category.includes(category)) + .map(Row), + }), + }); + +const sidebar = Widget.Revealer({ + binds: [["reveal-child", search, "value", (v) => !v]], + transition: "slide_right", + child: Widget.Box({ + hexpand: false, + vertical: true, + children: [ + Widget.Box({ + class_name: "sidebar-header", + children: [ + Widget.Button({ + hexpand: true, + label: icons.dialog.Search + " Search", + on_clicked: () => (showSearch.value = !showSearch.value), + }), + Widget.Button({ + hpack: "end", + child: Widget.Icon(icons.ui.info), + on_clicked: () => App.toggleWindow("about"), + }), + ], + }), + Widget.Scrollable({ + vexpand: true, + hscroll: "never", + child: Widget.Box({ + class_name: "sidebar-box vertical", + vertical: true, + children: [ + ...categories.map((name) => + Widget.Button({ + label: (icons.dialog[name] || "") + " " + name, + xalign: 0, + binds: [ + [ + "class-name", + currentPage, + "value", + (v) => (v === name ? "active" : ""), + ], + ], + on_clicked: () => currentPage.setValue(name), + }), + ), + ], + }), + }), + Widget.Box({ + class_name: "sidebar-footer", + child: Widget.Button({ + class_name: "copy", + child: Widget.Label({ + label: " Save", + xalign: 0, + }), + hexpand: true, + on_clicked: () => { + Utils.execAsync(["wl-copy", getValues()]); + Utils.execAsync([ + "notify-send", + "-i", + "preferences-desktop-theme-symbolic", + "Theme copied to clipboard", + 'To save it permanently, make a new theme in themes.js', + ]); + }, + }), + }), + ], + }), +}); + +const searchEntry = Widget.Revealer({ + transition: "slide_down", + binds: [ + ["reveal-child", showSearch], + ["transition-duration", options.transition], + ], + child: Widget.Entry({ + connections: [ + [ + showSearch, + (self) => { + if (!showSearch.value) self.text = ""; + + if (showSearch.value) self.grab_focus(); + }, + ], + ], + hexpand: true, + class_name: "search", + placeholder_text: "Search Options", + secondary_icon_name: icons.apps.search, + on_change: ({ text }) => (search.value = text || ""), + }), +}); + +const categoriesStack = Widget.Stack({ + transition: "slide_left_right", + items: categories.map((name) => [name, Page(name)]), + binds: [ + ["shown", currentPage], + ["visible", search, "value", (v) => !v], + ], +}); + +const searchPage = Widget.Box({ + binds: [["visible", search, "value", (v) => !!v]], + child: Page(""), +}); + +export default RegularWindow({ + name: "settings-dialog", + title: "Settings", + setup: (win) => win.set_default_size(800, 500), + connections: [ + [ + "delete-event", + (win) => { + win.hide(); + return true; + }, + ], + [ + "key-press-event", + (self, event) => { + if (event.get_keyval()[1] === imports.gi.Gdk.KEY_Escape) { + self.text = ""; + showSearch.setValue(false); + search.setValue(""); + } + }, + ], + ], + child: Widget.Box({ + children: [ + sidebar, + Widget.Box({ + vertical: true, + children: [searchEntry, categoriesStack, searchPage], + }), + ], + }), +}); diff --git a/home/desktops/hyprland/ags/js/settings/globals.js b/home/desktops/hyprland/ags/js/settings/globals.js new file mode 100644 index 0000000..1e72e17 --- /dev/null +++ b/home/desktops/hyprland/ags/js/settings/globals.js @@ -0,0 +1,37 @@ +import Mpris from "resource:///com/github/Aylur/ags/service/mpris.js"; + +export async function globals() { + try { + globalThis.options = (await import("../options.js")).default; + globalThis.iconBrowser = (await import("../misc/IconBrowser.js")).default; + globalThis.app = ( + await import("resource:///com/github/Aylur/ags/app.js") + ).default; + globalThis.audio = ( + await import("resource:///com/github/Aylur/ags/service/audio.js") + ).default; + globalThis.recorder = (await import("../services/screenrecord.js")).default; + globalThis.brightness = (await import("../services/brightness.js")).default; + globalThis.indicator = ( + await import("../services/onScreenIndicator.js") + ).default; + + Mpris.players.forEach((player) => { + player.connect("changed", (player) => { + globalThis.mpris = player || Mpris.players[0]; + }); + }); + + Mpris.connect("player-added", (mpris, bus) => { + mpris.getPlayer(bus)?.connect("changed", (player) => { + globalThis.mpris = player || Mpris.players[0]; + }); + }); + + Mpris.connect("player-closed", () => { + globalThis.mpris = Mpris.players[0]; + }); + } catch (error) { + logError(error); + } +} diff --git a/home/desktops/hyprland/ags/js/settings/hyprland.js b/home/desktops/hyprland/ags/js/settings/hyprland.js new file mode 100644 index 0000000..dc09e8c --- /dev/null +++ b/home/desktops/hyprland/ags/js/settings/hyprland.js @@ -0,0 +1,76 @@ +import App from "resource:///com/github/Aylur/ags/app.js"; +import Hyprland from "resource:///com/github/Aylur/ags/service/hyprland.js"; +import options from "../options.js"; +import { readFile, writeFile } from "resource:///com/github/Aylur/ags/utils.js"; + +const noIgnorealpha = ["verification", "powermenu", "lockscreen"]; + +/** @param {Array} batch */ +function sendBatch(batch) { + const cmd = batch + .filter((x) => !!x) + .map((x) => `keyword ${x}`) + .join("; "); + + Hyprland.sendMessage(`[[BATCH]]/${cmd}`); +} + +/** @param {string} scss */ +function getColor(scss) { + if (scss.includes("#")) return scss.replace("#", ""); + + if (scss.includes("$")) { + const opt = options + .list() + .find((opt) => opt.scss === scss.replace("$", "")); + return opt?.value.replace("#", "") || "ff0000"; + } +} + +export function hyprlandInit() { + if (readFile("/tmp/ags/hyprland-init")) return; + + sendBatch( + Array.from(App.windows).flatMap(([name]) => [ + `layerrule blur, ${name}`, + noIgnorealpha.some((skip) => name.includes(skip)) + ? "" + : `layerrule ignorealpha 0.6, ${name}`, + ]), + ); + + writeFile("init", "/tmp/ags/hyprland-init"); +} + +export async function setupHyprland() { + const wm_gaps = Math.floor( + options.hypr.wm_gaps_multiplier.value * options.spacing.value, + ); + const border_width = options.border.width.value; + const radii = options.radii.value; + const drop_shadow = options.desktop.drop_shadow.value; + const bar_style = options.bar.style.value; + const bar_pos = options.bar.position.value; + const inactive_border = options.hypr.inactive_border.value; + const accent = getColor(options.theme.accent.accent.value); + + const batch = []; + + JSON.parse(await Hyprland.sendMessage("j/monitors")).forEach(({ name }) => { + const v = bar_pos === "top" ? `-${wm_gaps},0,0,0` : `0,-${wm_gaps},0,0`; + if (bar_style !== "normal") batch.push(`monitor ${name},addreserved,${v}`); + else batch.push(`monitor ${name},addreserved,0,0,0,0`); + }); + + batch.push( + `general:border_size ${border_width}`, + `general:gaps_out ${wm_gaps}`, + `general:gaps_in ${Math.floor(wm_gaps / 2)}`, + `general:col.active_border rgba(${accent}ff)`, + `general:col.inactive_border ${inactive_border}`, + `decoration:rounding ${radii}`, + `decoration:drop_shadow ${drop_shadow ? "yes" : "no"}`, + ); + + sendBatch(batch); +} diff --git a/home/desktops/hyprland/ags/js/settings/option.js b/home/desktops/hyprland/ags/js/settings/option.js new file mode 100644 index 0000000..30e00bc --- /dev/null +++ b/home/desktops/hyprland/ags/js/settings/option.js @@ -0,0 +1,198 @@ +import { + CACHE_DIR, + readFile, + writeFile, +} from "resource:///com/github/Aylur/ags/utils.js"; +import { exec } from "resource:///com/github/Aylur/ags/utils.js"; +import options from "../options.js"; +import Service, { Binding } from "resource:///com/github/Aylur/ags/service.js"; +import { reloadScss } from "./scss.js"; +import { setupHyprland } from "./hyprland.js"; +const CACHE_FILE = CACHE_DIR + "/options.json"; + +/** object that holds the overriedden values */ +let cacheObj = JSON.parse(readFile(CACHE_FILE) || "{}"); + +/** + * @template T + * @typedef {Object} OptionConfig + * @property {string=} scss - name of scss variable set to "exclude" to not include it in the generated scss file + * @property {string=} unit - scss unit on numbers, default is "px" + * @property {string=} title + * @property {string=} note + * @property {string=} category + * @property {boolean=} noReload - don't reload css & hyprland on change + * @property {boolean=} persist - ignore reset call + * @property {'object' | 'string' | 'img' | 'number' | 'float' | 'font' | 'enum' =} type + * @property {Array =} enums + * @property {(value: T) => any=} format + * @property {(value: T) => any=} scssFormat + */ + +/** @template T */ +export class Opt extends Service { + static { + Service.register( + this, + {}, + { + value: ["jsobject"], + }, + ); + } + + #value; + #scss = ""; + unit = "px"; + noReload = false; + persist = false; + id = ""; + title = ""; + note = ""; + type = ""; + category = ""; + + /** @type {Array} */ + enums = []; + + /** @type {(v: T) => any} */ + format = (v) => v; + + /** @type {(v: T) => any} */ + scssFormat = (v) => v; + + /** + * @param {T} value + * @param {OptionConfig =} config + */ + constructor(value, config) { + super(); + this.#value = value; + this.defaultValue = value; + this.type = typeof value; + + if (config) Object.keys(config).forEach((c) => (this[c] = config[c])); + + import("../options.js").then(this.#init.bind(this)); + } + + set scss(scss) { + this.#scss = scss; + } + get scss() { + return this.#scss || this.id.split(".").join("-").split("_").join("-"); + } + + #init() { + getOptions(); // sets the ids as a side effect + + if (cacheObj[this.id] !== undefined) this.setValue(cacheObj[this.id]); + + const words = this.id + .split(".") + .flatMap((w) => w.split("_")) + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)); + + this.title ||= words.join(" "); + this.category ||= words.length === 1 ? "General" : words.at(0) || "General"; + + this.connect("changed", () => { + cacheObj[this.id] = this.value; + writeFile(JSON.stringify(cacheObj, null, 2), CACHE_FILE); + }); + } + + get value() { + return this.#value; + } + set value(value) { + this.setValue(value); + } + + /** @param {T} value */ + setValue(value, reload = false) { + if (typeof value !== typeof this.defaultValue) { + console.error( + Error( + `WrongType: Option "${this.id}" can't be set to ${value}, ` + + `expected "${typeof this.defaultValue}", but got "${typeof value}"`, + ), + ); + + return; + } + + if (this.value !== value) { + this.#value = this.format(value); + this.changed("value"); + + if (reload && !this.noReload) { + reloadScss(); + setupHyprland(); + } + } + } + + reset(reload = false) { + if (!this.persist) this.setValue(this.defaultValue, reload); + } +} + +/** + * @template T + * @param {T} value + * @param {OptionConfig =} config + * @returns {Opt} + */ +export function Option(value, config) { + return new Opt(value, config); +} + +/** @returns {Array>} */ +export function getOptions(object = options, path = "") { + return Object.keys(object).flatMap((key) => { + /** @type Option */ + const obj = object[key]; + const id = path ? path + "." + key : key; + + if (obj instanceof Opt) { + obj.id = id; + return obj; + } + + if (typeof obj === "object") return getOptions(obj, id); + + return []; + }); +} + +export function resetOptions() { + exec(`rm -rf ${CACHE_FILE}`); + cacheObj = {}; + getOptions().forEach((opt) => opt.reset()); +} + +export function getValues() { + const obj = {}; + for (const opt of getOptions()) { + if (opt.category !== "exclude") obj[opt.id] = opt.value; + } + + return JSON.stringify(obj, null, 2); +} + +/** @param {string | object} config */ +export function apply(config) { + const options = getOptions(); + const settings = typeof config === "string" ? JSON.parse(config) : config; + + for (const id of Object.keys(settings)) { + const opt = options.find((opt) => opt.id === id); + if (!opt) { + print(`No option with id: "${id}"`); + continue; + } + + opt.setValue(settings[id]); + } +} diff --git a/home/desktops/hyprland/ags/js/settings/scss.js b/home/desktops/hyprland/ags/js/settings/scss.js new file mode 100644 index 0000000..45bba7a --- /dev/null +++ b/home/desktops/hyprland/ags/js/settings/scss.js @@ -0,0 +1,65 @@ +import App from "resource:///com/github/Aylur/ags/app.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import { getOptions } from "./option.js"; +import { dependencies } from "../utils.js"; + +export function scssWatcher() { + return Utils.subprocess( + [ + "inotifywait", + "--recursive", + "--event", + "create,modify", + "-m", + App.configDir + "/scss", + ], + reloadScss, + () => print("missing dependancy for css hotreload: inotify-tools"), + ); +} + +/** + * generate an scss file that makes every option available as a variable + * based on the passed scss parameter or the path in the object + * + * e.g + * options.bar.style.value => $bar-style + */ +export async function reloadScss() { + if (!dependencies(["sassc"])) return; + + const opts = getOptions(); + const vars = opts.map((opt) => { + if (opt.scss === "exclude") return ""; + + const unit = typeof opt.value === "number" ? opt.unit : ""; + const value = opt.scssFormat ? opt.scssFormat(opt.value) : opt.value; + return `$${opt.scss}: ${value}${unit};`; + }); + + const bar_style = opts.find((opt) => opt.id === "bar.style")?.value || ""; + const additional = + bar_style === "normal" + ? "//" + : ` + window#quicksettings .window-content { + margin-right: $wm-gaps; + } + `; + + try { + const tmp = "/tmp/ags/scss"; + Utils.ensureDirectory(tmp); + await Utils.writeFile(vars.join("\n"), `${tmp}/options.scss`); + await Utils.writeFile(additional, `${tmp}/additional.scss`); + await Utils.execAsync( + `sassc ${App.configDir}/scss/main.scss ${tmp}/style.css`, + ); + App.resetCss(); + App.applyCss(`${tmp}/style.css`); + } catch (error) { + if (error instanceof Error) console.error(error.message); + + if (typeof error === "string") console.error(error); + } +} diff --git a/home/desktops/hyprland/ags/js/settings/setup.js b/home/desktops/hyprland/ags/js/settings/setup.js new file mode 100644 index 0000000..8bcb1c0 --- /dev/null +++ b/home/desktops/hyprland/ags/js/settings/setup.js @@ -0,0 +1,114 @@ +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import Battery from "resource:///com/github/Aylur/ags/service/battery.js"; +import Notifications from "resource:///com/github/Aylur/ags/service/notifications.js"; +import options from "../options.js"; +import icons from "../icons.js"; +import { reloadScss, scssWatcher } from "./scss.js"; +import { wallpaper } from "./wallpaper.js"; +import { hyprlandInit, setupHyprland } from "./hyprland.js"; +import { globals } from "./globals.js"; +import { showAbout } from "../about/about.js"; +import Gtk from "gi://Gtk"; + +export function init() { + notificationBlacklist(); + warnOnLowBattery(); + globals(); + tmux(); + gsettigsColorScheme(); + gtkFontSettings(); + scssWatcher(); + dependandOptions(); + + reloadScss(); + hyprlandInit(); + setupHyprland(); + wallpaper(); + showAbout(); +} + +function dependandOptions() { + options.bar.style.connect("changed", ({ value }) => { + if (value !== "normal") + options.desktop.screen_corners.setValue(false, true); + }); +} + +function tmux() { + if (!Utils.exec("which tmux")) return; + + /** @param {string} scss */ + function getColor(scss) { + if (scss.includes("#")) return scss; + + if (scss.includes("$")) { + const opt = options + .list() + .find((opt) => opt.scss === scss.replace("$", "")); + return opt?.value; + } + } + + options.theme.accent.accent.connect("changed", ({ value }) => + Utils.execAsync(`tmux set @main_accent ${getColor(value)}`).catch((err) => + console.error(err.message), + ), + ); +} + +function gsettigsColorScheme() { + if (!Utils.exec("which gsettings")) return; + + options.theme.scheme.connect("changed", ({ value }) => { + const gsettings = "gsettings set org.gnome.desktop.interface color-scheme"; + Utils.execAsync(`${gsettings} "prefer-${value}"`).catch((err) => + console.error(err.message), + ); + }); +} + +function gtkFontSettings() { + const settings = Gtk.Settings.get_default(); + if (!settings) { + console.error(Error("Gtk.Settings unavailable")); + return; + } + + const callback = () => { + const { size, font } = options.font; + settings.gtk_font_name = `${font.value} ${size.value}`; + }; + + options.font.font.connect("notify::value", callback); + options.font.size.connect("notify::value", callback); +} + +function notificationBlacklist() { + Notifications.connect("notified", (_, id) => { + const n = Notifications.getNotification(id); + options.notifications.black_list.value.forEach((item) => { + if (n?.app_name.includes(item) || n?.app_entry?.includes(item)) n.close(); + }); + }); +} + +function warnOnLowBattery() { + Battery.connect("notify::percent", () => { + const low = options.battery.low.value; + if ( + Battery.percent !== low || + Battery.percent !== low / 2 || + !Battery.charging + ) + return; + + Utils.execAsync([ + "notify-send", + `${Battery.percent}% Battery Percentage`, + "-i", + icons.battery.warning, + "-u", + "critical", + ]); + }); +} diff --git a/home/desktops/hyprland/ags/js/settings/theme.js b/home/desktops/hyprland/ags/js/settings/theme.js new file mode 100644 index 0000000..624432e --- /dev/null +++ b/home/desktops/hyprland/ags/js/settings/theme.js @@ -0,0 +1,55 @@ +import App from "resource:///com/github/Aylur/ags/app.js"; +import options from "../options.js"; +import themes from "../themes.js"; +import { reloadScss } from "./scss.js"; +import { setupHyprland } from "./hyprland.js"; +import { wallpaper } from "./wallpaper.js"; + +/** @param {string} name */ +export function setTheme(name) { + options.reset(); + const theme = themes.find((t) => t.name === name); + if (!theme) return print("No theme named " + name); + + options.apply(theme.options); + reloadScss(); + setupHyprland(); + wallpaper(); +} + +export const WP = App.configDir + "/assets/"; + +export const lightColors = { + "theme.scheme": "light", + "color.red": "#e55f86", + "color.green": "#00D787", + "color.yellow": "#EBFF71", + "color.blue": "#51a4e7", + "color.magenta": "#9077e7", + "color.teal": "#51e6e6", + "color.orange": "#E79E64", + "theme.bg": "#fffffa", + "theme.fg": "#141414", +}; + +export const Theme = ({ name, icon = " ", ...options }) => ({ + name, + icon, + options: { + "theme.name": name, + "theme.icon": icon, + ...options, + }, +}); + +let settingsDialog; +export async function openSettings() { + if (settingsDialog) return settingsDialog.present(); + + try { + settingsDialog = (await import("./SettingsDialog.js")).default; + settingsDialog.present(); + } catch (error) { + if (error instanceof Error) console.error(error.message); + } +} diff --git a/home/desktops/hyprland/ags/js/settings/wallpaper.js b/home/desktops/hyprland/ags/js/settings/wallpaper.js new file mode 100644 index 0000000..6fbeffb --- /dev/null +++ b/home/desktops/hyprland/ags/js/settings/wallpaper.js @@ -0,0 +1,25 @@ +import options from "../options.js"; +import { exec, execAsync } from "resource:///com/github/Aylur/ags/utils.js"; +import { dependencies } from "../utils.js"; + +export function initWallpaper() { + if (dependencies(["swww"])) { + exec("swww init"); + + options.desktop.wallpaper.img.connect("changed", wallpaper); + } +} + +export function wallpaper() { + if (!dependencies(["swww"])) return; + + execAsync([ + "swww", + "img", + "--transition-type", + "grow", + "--transition-pos", + exec("hyprctl cursorpos").replace(" ", ""), + options.desktop.wallpaper.img.value, + ]).catch((err) => console.error(err)); +} diff --git a/home/desktops/hyprland/ags/js/themes.js b/home/desktops/hyprland/ags/js/themes.js new file mode 100644 index 0000000..2b027a0 --- /dev/null +++ b/home/desktops/hyprland/ags/js/themes.js @@ -0,0 +1,66 @@ +/** + * A Theme is a set of options that will be applied + * ontop of the default values. see options.js for possible options + */ +import { Theme, WP, lightColors } from "./settings/theme.js"; + +export default [ + Theme({ + name: "Kitty Dark", + icon: "󰄛", + "desktop.wallpaper.img": WP + "kittybl.jpeg", + }), + Theme({ + name: "Kitty Light", + icon: "󰄛", + "desktop.wallpaper.img": WP + "kitty.jpeg", + ...lightColors, + "theme.widget.bg": "$accent", + "theme.widget.opacity": 64, + }), + Theme({ + name: "Leaves", + icon: "󰌪", + "desktop.wallpaper.img": WP + "leaves.jpg", + "theme.accent.accent": "$green", + "theme.accent.gradient": "to right, $accent, darken($accent, 14%)", + "theme.widget.opacity": 92, + "border.opacity": 86, + "theme.bg": "transparentize(#171717, 0.3)", + "bar.style": "floating", + radii: 0, + }), + Theme({ + name: "Ivory", + icon: "󰟆", + ...lightColors, + "desktop.wallpaper.img": WP + "ivory.png", + "desktop.wallpaper.fg": "$bg_color", + "desktop.screen_corners": false, + "bar.style": "separated", + "theme.widget.bg": "$accent", + "theme.widget.opacity": 64, + "desktop.drop_shadow": false, + "border.width": 2, + "border.opacity": 0, + "theme.accent.gradient": "to right, $accent, darken($accent, 6%)", + "hypr.inactive_border": "rgba(111111FF)", + "bar.separators": false, + }), + Theme({ + name: "Space", + icon: "", + "desktop.wallpaper.img": WP + "space.jpg", + spacing: 11, + padding: 10, + radii: 12, + "theme.accent.accent": "$magenta", + "desktop.screen_corners": false, + "desktop.clock.enable": false, + "bar.separators": false, + "bar.icon": "", + "theme.bg": "transparentize(#171717, 0.3)", + "theme.widget.opacity": 95, + "bar.flat_buttons": false, + }), +]; diff --git a/home/desktops/hyprland/ags/js/utils.js b/home/desktops/hyprland/ags/js/utils.js new file mode 100644 index 0000000..c4ce70f --- /dev/null +++ b/home/desktops/hyprland/ags/js/utils.js @@ -0,0 +1,99 @@ +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import cairo from "cairo"; +import icons from "./icons.js"; +import Gdk from "gi://Gdk"; +import GLib from "gi://GLib"; + +/** + * @param {number} length + * @param {number=} start + * @returns {Array} + */ +export function range(length, start = 1) { + return Array.from({ length }, (_, i) => i + start); +} + +/** + * @param {Array<[string, string] | string[]>} collection + * @param {string} item + * @returns {string} + */ +export function substitute(collection, item) { + return collection.find(([from]) => from === item)?.[1] || item; +} + +/** + * @param {(monitor: number) => any} widget + * @returns {Array} + */ +export function forMonitors(widget) { + const n = Gdk.Display.get_default()?.get_n_monitors() || 1; + return range(n, 0).map(widget).flat(1); +} + +/** + * @param {import('gi://Gtk').Gtk.Widget} widget + * @returns {any} - missing cairo type + */ +export function createSurfaceFromWidget(widget) { + const alloc = widget.get_allocation(); + const surface = new cairo.ImageSurface( + cairo.Format.ARGB32, + alloc.width, + alloc.height, + ); + const cr = new cairo.Context(surface); + cr.setSourceRGBA(255, 255, 255, 0); + cr.rectangle(0, 0, alloc.width, alloc.height); + cr.fill(); + widget.draw(cr); + + return surface; +} + +/** @param {string} icon */ +export function getAudioTypeIcon(icon) { + const substitues = [ + ["audio-headset-bluetooth", icons.audio.type.headset], + ["audio-card-analog-usb", icons.audio.type.speaker], + ["audio-card-analog-pci", icons.audio.type.card], + ]; + + return substitute(substitues, icon); +} + +/** @param {import('types/service/applications').Application} app */ +export function launchApp(app) { + Utils.execAsync(["hyprctl", "dispatch", "exec", `sh -c ${app.executable}`]); + app.frequency += 1; +} + +/** @param {Array} bins */ +export function dependencies(bins) { + const deps = bins.map((bin) => { + const has = Utils.exec(`which ${bin}`); + if (!has) print(`missing dependency: ${bin}`); + + return !!has; + }); + + return deps.every((has) => has); +} + +/** @param {string} img - path to an img file */ +export function blurImg(img) { + const cache = Utils.CACHE_DIR + "/media"; + return new Promise((resolve) => { + if (!img) resolve(""); + + const dir = cache + "/blurred"; + const blurred = dir + img.substring(cache.length); + + if (GLib.file_test(blurred, GLib.FileTest.EXISTS)) return resolve(blurred); + + Utils.ensureDirectory(dir); + Utils.execAsync(["convert", img, "-blur", "0x22", blurred]) + .then(() => resolve(blurred)) + .catch(() => resolve("")); + }); +} diff --git a/home/desktops/hyprland/ags/js/variables.js b/home/desktops/hyprland/ags/js/variables.js new file mode 100644 index 0000000..6c306f1 --- /dev/null +++ b/home/desktops/hyprland/ags/js/variables.js @@ -0,0 +1,88 @@ +import Variable from "resource:///com/github/Aylur/ags/variable.js"; +import GLib from "gi://GLib"; +import options from "./options.js"; + +const intval = options.systemFetchInterval; + +export const uptime = Variable("", { + poll: [ + 60_000, + "cat /proc/uptime", + (line) => { + const uptime = Number.parseInt(line.split(".")[0]) / 60; + if (uptime > 18 * 60) return "Go Sleep"; + + const h = Math.floor(uptime / 60); + const s = Math.floor(uptime % 60); + return `${h}:${s < 10 ? "0" + s : s}`; + }, + ], +}); + +export const distro = GLib.get_os_info("ID"); + +export const distroIcon = (() => { + switch (distro) { + case "fedora": + return ""; + case "arch": + return ""; + case "nixos": + return ""; + case "debian": + return ""; + case "opensuse-tumbleweed": + return ""; + case "ubuntu": + return ""; + case "endeavouros": + return ""; + default: + return ""; + } +})(); + +/** @type {function([string, string] | string[]): number} */ +const divide = ([total, free]) => + Number.parseInt(free) / Number.parseInt(total); + +export const cpu = Variable(0, { + poll: [ + intval, + "top -b -n 1", + (out) => + divide([ + "100", + out + .split("\n") + .find((line) => line.includes("Cpu(s)")) + ?.split(/\s+/)[1] + .replace(",", ".") || "0", + ]), + ], +}); + +export const ram = Variable(0, { + poll: [ + intval, + "free", + (out) => + divide( + out + .split("\n") + .find((line) => line.includes("Mem:")) + ?.split(/\s+/) + .splice(1, 2) || ["1", "1"], + ), + ], +}); + +export const temp = Variable(0, { + poll: [ + intval, + "cat " + options.temperature, + (n) => { + return Number.parseInt(n) / 100_000; + }, + ], +}); diff --git a/home/desktops/hyprland/ags/modules/calendar.js b/home/desktops/hyprland/ags/modules/calendar.js deleted file mode 100644 index 7e2f28f..0000000 --- a/home/desktops/hyprland/ags/modules/calendar.js +++ /dev/null @@ -1,364 +0,0 @@ -const { Gio, Gdk, Gtk } = imports.gi; -import { App, Widget, Utils } from '../imports.js'; -const { Box, CenterBox, Label, Button } = Widget; -import { MaterialIcon } from "./lib/materialicon.js"; -import { getCalendarLayout } from "../scripts/calendarlayout.js"; -import Todo from "../scripts/todo.js"; -import { setupCursorHover } from "./lib/cursorhover.js"; -import { NavigationIndicator } from "./lib/navigationindicator.js"; - -let calendarJson = getCalendarLayout(undefined, true); -let monthshift = 0; - -function fileExists(filePath) { - let file = Gio.File.new_for_path(filePath); - return file.query_exists(null); -} - -function getDateInXMonthsTime(x) { - var currentDate = new Date(); // Get the current date - var targetMonth = currentDate.getMonth() + x; // Calculate the target month - var targetYear = currentDate.getFullYear(); // Get the current year - - // Adjust the year and month if necessary - targetYear += Math.floor(targetMonth / 12); - targetMonth = (targetMonth % 12 + 12) % 12; - - // Create a new date object with the target year and month - var targetDate = new Date(targetYear, targetMonth, 1); - - // Set the day to the last day of the month to get the desired date - // targetDate.setDate(0); - - return targetDate; -} - -const weekDays = [ // stupid stupid stupid!! how tf is Sunday the first day of the week?? - { day: 'Su', today: 0 }, - { day: 'Mo', today: 0 }, - { day: 'Tu', today: 0 }, - { day: 'We', today: 0 }, - { day: 'Th', today: 0 }, - { day: 'Fr', today: 0 }, - { day: 'Sa', today: 0 }, -] - -const CalendarDay = (day, today) => Widget.Button({ - className: `sidebar-calendar-btn ${today == 1 ? 'sidebar-calendar-btn-today' : (today == -1 ? 'sidebar-calendar-btn-othermonth' : '')}`, - child: Widget.Overlay({ - child: Box({}), - overlays: [Label({ - halign: 'center', - className: 'txt-smallie txt-semibold sidebar-calendar-btn-txt', - label: String(day), - })], - }) -}) - -const CalendarWidget = () => { - const calendarMonthYear = Widget.Button({ - className: 'txt txt-large sidebar-calendar-monthyear-btn', - onClicked: () => shiftCalendarXMonths(0), - setup: (button) => { - button.label = `${new Date().toLocaleString('default', { month: 'long' })} ${new Date().getFullYear()}`; - setupCursorHover(button); - } - }); - const addCalendarChildren = (box, calendarJson) => { - box.children = calendarJson.map((row, i) => Widget.Box({ - // homogeneous: true, - className: 'spacing-h-5', - children: row.map((day, i) => - CalendarDay(day.day, day.today) - ) - })) - } - function shiftCalendarXMonths(x) { - if (x == 0) - monthshift = 0; - else - monthshift += x; - var newDate = undefined; - if (monthshift == 0) - newDate = new Date(); - else - newDate = getDateInXMonthsTime(monthshift); - calendarJson = getCalendarLayout(newDate, monthshift == 0); - calendarMonthYear.label = `${monthshift == 0 ? '' : '• '}${newDate.toLocaleString('default', { month: 'long' })} ${newDate.getFullYear()}`; - addCalendarChildren(calendarDays, calendarJson); - } - const calendarHeader = Widget.Box({ - className: 'spacing-h-5 sidebar-calendar-header', - setup: (box) => { - box.pack_start(calendarMonthYear, false, false, 0); - box.pack_end(Widget.Box({ - className: 'spacing-h-5', - children: [ - Button({ - className: 'sidebar-calendar-monthshift-btn', - onClicked: () => shiftCalendarXMonths(-1), - child: MaterialIcon('chevron_left', 'norm'), - setup: (button) => setupCursorHover(button), - }), - Button({ - className: 'sidebar-calendar-monthshift-btn', - onClicked: () => shiftCalendarXMonths(1), - child: MaterialIcon('chevron_right', 'norm'), - setup: (button) => setupCursorHover(button), - }) - ] - }), false, false, 0); - } - }) - const calendarDays = Widget.Box({ - hexpand: true, - vertical: true, - className: 'spacing-v-5', - setup: (box) => { - addCalendarChildren(box, calendarJson); - } - }); - return Widget.EventBox({ - onScrollUp: () => shiftCalendarXMonths(-1), - onScrollDown: () => shiftCalendarXMonths(1), - child: Widget.Box({ - halign: 'center', - children: [ - Widget.Box({ - hexpand: true, - vertical: true, - className: 'spacing-v-5', - children: [ - calendarHeader, - Widget.Box({ - homogeneous: true, - className: 'spacing-h-5', - children: weekDays.map((day, i) => CalendarDay(day.day, day.today)) - }), - calendarDays, - ] - }) - ] - }) - }); -}; - -const defaultTodoSelected = 'undone'; - -const todoItems = (isDone) => Widget.Scrollable({ - child: Widget.Box({ - vertical: true, - connections: [[Todo, (self) => { - self.children = Todo.todo_json.map((task, i) => { - if (task.done != isDone) return null; - return Widget.Box({ - className: 'spacing-h-5', - children: [ - Widget.Label({ - className: 'txt txt-small', - label: '•', - }), - Widget.Label({ - hexpand: true, - xalign: 0, - wrap: true, - className: 'txt txt-small sidebar-todo-txt', - label: task.content, - }), - Widget.Button({ - valign: 'center', - className: 'txt sidebar-todo-item-action', - child: MaterialIcon(`${isDone ? 'remove_done' : 'check'}`, 'norm', { valign: 'center' }), - onClicked: () => { - if (isDone) - Todo.uncheck(i); - else - Todo.check(i); - }, - setup: (button) => setupCursorHover(button), - }), - Widget.Button({ - valign: 'center', - className: 'txt sidebar-todo-item-action', - child: MaterialIcon('delete_forever', 'norm', { valign: 'center' }), - onClicked: () => { - Todo.remove(i); - }, - setup: (button) => setupCursorHover(button), - }), - ] - }); - }) - if (self.children.length == 0) { - self.homogeneous = true; - self.children = [ - Widget.Box({ - hexpand: true, - vertical: true, - valign: 'center', - className: 'txt', - children: [ - MaterialIcon(`${isDone ? 'checklist' : 'check_circle'}`, 'badonkers'), - Label({ label: `${isDone ? 'Finished tasks will go here' : 'Nothing here!'}` }) - ] - }) - ] - } - else self.homogeneous = false; - }, 'updated']] - }) -}); - -const todoItemsBox = Widget.Stack({ - valign: 'fill', - transition: 'slide_left_right', - items: [ - ['undone', todoItems(false)], - ['done', todoItems(true)], - ], -}); - -const TodoWidget = () => { - const TodoTabButton = (isDone, navIndex) => Widget.Button({ - hexpand: true, - className: 'sidebar-todo-selector-tab', - onClicked: (button) => { - todoItemsBox.shown = `${isDone ? 'done' : 'undone'}`; - const kids = button.get_parent().get_children(); - for (let i = 0; i < kids.length; i++) { - if (kids[i] != button) kids[i].toggleClassName('sidebar-todo-selector-tab-active', false); - else button.toggleClassName('sidebar-todo-selector-tab-active', true); - } - // Fancy highlighter line width - const buttonWidth = button.get_allocated_width(); - const highlightWidth = button.get_children()[0].get_allocated_width(); - navIndicator.style = ` - font-size: ${navIndex}px; - padding: 0px ${(buttonWidth - highlightWidth) / 2}px; - `; - }, - child: Box({ - halign: 'center', - className: 'spacing-h-5', - children: [ - MaterialIcon(`${isDone ? 'task_alt' : 'format_list_bulleted'}`, 'larger'), - Label({ - className: 'txt txt-smallie', - label: `${isDone ? 'Done' : 'Unfinished'}`, - }) - ] - }), - setup: (button) => { - button.toggleClassName('sidebar-todo-selector-tab-active', defaultTodoSelected === `${isDone ? 'done' : 'undone'}`); - setupCursorHover(button); - }, - }); - const undoneButton = TodoTabButton(false, 0); - const doneButton = TodoTabButton(true, 1); - const navIndicator = NavigationIndicator(2, false, { - className: 'sidebar-todo-selector-highlight', - style: 'font-size: 0px;', - setup: (self) => { - // Fancy highlighter line width - const buttonWidth = undoneButton.get_allocated_width(); - const highlightWidth = undoneButton.get_children()[0].get_allocated_width(); - navIndicator.style = ` - font-size: ${navIndex}px; - padding: 0px ${(buttonWidth - highlightWidth) / 2}px; - `; - } - }) - return Widget.Box({ - hexpand: true, - vertical: true, - className: 'spacing-v-10', - setup: (box) => { - // undone/done selector rail - box.pack_start(Widget.Box({ - vertical: true, - children: [ - Widget.Box({ - className: 'sidebar-todo-selectors spacing-h-5', - homogeneous: true, - setup: (box) => { - box.pack_start(undoneButton, false, true, 0); - box.pack_start(doneButton, false, true, 0); - } - }), - Widget.Box({ - className: 'sidebar-todo-selector-highlight-offset', - homogeneous: true, - children: [navIndicator] - }) - ] - }), false, false, 0); - box.pack_end(todoItemsBox, true, true, 0); - } - }); -}; - -const defaultShown = 'calendar'; -const contentStack = Widget.Stack({ - hexpand: true, - items: [ - ['calendar', CalendarWidget()], - ['todo', TodoWidget()], - // ['stars', Widget.Label({ label: 'GitHub feed will be here' })], - ], - transition: 'slide_up_down', - transitionDuration: 180, - setup: (stack) => { - stack.shown = defaultShown; - } -}) - -const StackButton = (stackItemName, icon, name) => Widget.Button({ - className: 'button-minsize sidebar-navrail-btn sidebar-button-alone txt-small spacing-h-5', - onClicked: (button) => { - contentStack.shown = stackItemName; - const kids = button.get_parent().get_children(); - for (let i = 0; i < kids.length; i++) { - if (kids[i] != button) kids[i].toggleClassName('sidebar-navrail-btn-active', false); - else button.toggleClassName('sidebar-navrail-btn-active', true); - } - }, - child: Box({ - className: 'spacing-v-5', - vertical: true, - children: [ - Label({ - className: `txt icon-material txt-hugeass`, - label: icon, - }), - Label({ - label: name, - className: 'txt txt-smallie', - }), - ] - }), - setup: (button) => { - button.toggleClassName('sidebar-navrail-btn-active', defaultShown === stackItemName); - setupCursorHover(button); - } -}); - -export const ModuleCalendar = () => Box({ - className: 'sidebar-group spacing-h-5', - setup: (box) => { - box.pack_start(Box({ - valign: 'center', - homogeneous: true, - vertical: true, - className: 'sidebar-navrail spacing-v-10', - children: [ - StackButton('calendar', 'calendar_month', 'Calendar'), - StackButton('todo', 'checklist', 'To Do'), - // StackButton(box, 'stars', 'star', 'GitHub'), - ] - }), false, false, 0); - // ags.Widget({ // TDOO: replace this sad default calendar with a custom one - // type: imports.gi.Gtk.Calendar, - // }), - box.pack_end(contentStack, false, false, 0); - } -}) diff --git a/home/desktops/hyprland/ags/modules/keybinds.js b/home/desktops/hyprland/ags/modules/keybinds.js deleted file mode 100644 index 3bcfec8..0000000 --- a/home/desktops/hyprland/ags/modules/keybinds.js +++ /dev/null @@ -1,60 +0,0 @@ -import { Widget } from '../imports.js'; -import { keybindList } from "../data/keybinds.js"; - -export const Keybinds = () => Widget.Box({ - vertical: false, - className: "spacing-h-15", - homogeneous: true, - children: keybindList.map((group, i) => Widget.Box({ // Columns - vertical: true, - className: "spacing-v-15", - children: group.map((category, i) => Widget.Box({ // Categories - vertical: true, - className: "spacing-v-15", - children: [ - Widget.Box({ // Category header - vertical: false, - className: "spacing-h-10", - children: [ - Widget.Label({ - xalign: 0, - className: "icon-material txt txt-larger", - label: category.icon, - }), - Widget.Label({ - xalign: 0, - className: "cheatsheet-category-title txt", - label: category.name, - }), - ] - }), - Widget.Box({ - vertical: false, - className: "spacing-h-10", - children: [ - Widget.Box({ // Keys - vertical: true, - homogeneous: true, - children: category.binds.map((keybinds, i) => Widget.Box({ // Binds - vertical: false, - children: keybinds.keys.map((key, i) => Widget.Label({ // Specific keys - className: `${key == 'OR' || key == '+' ? 'cheatsheet-key-notkey' : 'cheatsheet-key'} txt-small`, - label: key, - })) - })) - }), - Widget.Box({ // Actions - vertical: true, - homogeneous: true, - children: category.binds.map((keybinds, i) => Widget.Label({ // Binds - xalign: 0, - label: keybinds.action, - className: "txt chearsheet-action txt-small", - })) - }) - ] - }) - ] - })) - })), -}); \ No newline at end of file diff --git a/home/desktops/hyprland/ags/modules/leftspace.js b/home/desktops/hyprland/ags/modules/leftspace.js deleted file mode 100644 index d1239a9..0000000 --- a/home/desktops/hyprland/ags/modules/leftspace.js +++ /dev/null @@ -1,101 +0,0 @@ -import { App, Service, Utils, Widget } from '../imports.js'; -import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; -const { CONFIG_DIR, exec, execAsync } = Utils; -import { deflisten } from '../scripts/scripts.js'; -import { setupCursorHover } from "./lib/cursorhover.js"; -import { RoundedCorner } from "./lib/roundedcorner.js"; -import Brightness from '../scripts/brightness.js'; -import Indicator from '../scripts/indicator.js'; - -// Removes everything after the last -// em dash, en dash, minus, vertical bar, or middle dot (note: maybe add open parenthesis?) -// For example: -// • Discord | #ricing-theming | r/unixporn — Mozilla Firefox --> • Discord | #ricing-theming -// GJS Error · Issue #112 · Aylur/ags — Mozilla Firefox --> GJS Error · Issue #112 -function truncateTitle(str) { - let lastDash = -1; - let found = -1; // 0: em dash, 1: en dash, 2: minus, 3: vertical bar, 4: middle dot - for (let i = str.length - 1; i >= 0; i--) { - if (str[i] === '—') { - found = 0; - lastDash = i; - } - else if (str[i] === '–' && found < 1) { - found = 1; - lastDash = i; - } - else if (str[i] === '-' && found < 2) { - found = 2; - lastDash = i; - } - else if (str[i] === '|' && found < 3) { - found = 3; - lastDash = i; - } - else if (str[i] === '·' && found < 4) { - found = 4; - lastDash = i; - } - } - if (lastDash === -1) return str; - return str.substring(0, lastDash); -} - -export const ModuleLeftSpace = () => Widget.EventBox({ - onScrollUp: () => { - Indicator.popup(1); // Since the brightness and speaker are both on the same window - Brightness.screen_value += 0.05; - }, - onScrollDown: () => { - Indicator.popup(1); // Since the brightness and speaker are both on the same window - Brightness.screen_value -= 0.05; - }, - child: Widget.Box({ - homogeneous: false, - children: [ - RoundedCorner('topleft', { className: 'corner-black' }), - Widget.Overlay({ - overlays: [ - Widget.Box({ hexpand: true }), - Widget.Box({ - className: 'bar-sidemodule', hexpand: true, - children: [Widget.Button({ - className: 'bar-space-button', - child: Widget.Box({ - vertical: true, - children: [ - Widget.Scrollable({ - hexpand: true, vexpand: true, - hscroll: 'automatic', vscroll: 'never', - child: Widget.Box({ - vertical: true, - children: [ - Widget.Label({ - xalign: 0, - className: 'txt txt-smaller bar-topdesc', - connections: [[Hyprland, label => { // Hyprland.active.client - label.label = Hyprland.active.client._class.length === 0 ? 'Desktop' : Hyprland.active.client._class; - }]], - }), - Widget.Label({ - xalign: 0, - className: 'txt txt-smallie', - connections: [ - [Hyprland, label => { // Hyprland.active.client - label.label = Hyprland.active.client._title.length === 0 ? `Workspace ${Hyprland.active.workspace.id}` : truncateTitle(Hyprland.active.client._title); - }] - ], - }) - ] - }) - }) - ] - }), - setup: (button) => setupCursorHover(button), - })] - }), - ] - }) - ] - }) -}); \ No newline at end of file diff --git a/home/desktops/hyprland/ags/modules/lib/actioncenter.js b/home/desktops/hyprland/ags/modules/lib/actioncenter.js deleted file mode 100644 index 9b8fb60..0000000 --- a/home/desktops/hyprland/ags/modules/lib/actioncenter.js +++ /dev/null @@ -1,245 +0,0 @@ -// Not yet used. For cool drag and drop stuff. Thanks DevAlien - -const Toggles = {}; -Toggles.Wifi = NetworkToggle; -Toggles.Bluetooth = BluetoothToggle; -Toggles.DND = DNDToggle; -Toggles.ThemeToggle = ThemeToggle; -Toggles.ProfileToggle = ProfileToggle; -// Toggles.Record = RecordToggle; -// Toggles.Airplane = AirplaneToggle; -// Toggles.DoNotDisturb = DoNotDisturbToggle; -const TARGET = [Gtk.TargetEntry.new("text/plain", Gtk.TargetFlags.SAME_APP, 0)]; - -export class ActionCenter extends Gtk.Box { - static { - GObject.registerClass({ - GTypeName: 'ActionCenter', - Properties: { - - }, - }, this); - } - - constructor({ className = "ActionCenter", toggles, ...rest }) { - super(rest); - this.toggles = Toggles - this.currentToggles = Settings.getSetting("toggles", []); - this.mainFlowBox = this._setupFlowBox(className + QSView.editing && className + "Editing"); - this.mainFlowBox.connect("drag_motion", this._dragMotionMain); - this.mainFlowBox.connect("drag_drop", this._dragDropMain); - this._dragged = {}; - this._draggedExtra = {}; - - this._dragged; - this._currentPosition = 0; - this._orderedState; - this._draggedName; - - this.updateList(toggles, this.mainFlowBox) - - this.set_orientation(Gtk.Orientation.VERTICAL); - this.add(this.mainFlowBox) - this.mainFlowBox.set_size_request(1, 30) - if (QSView.editing) { - this.extraFlowBox = this._setupFlowBox(className); - this.extraFlowBox.connect("drag_motion", this._dragMotionExtra); - this.extraFlowBox.connect("drag_drop", this._dragDropExtra); - this.updateList(this._getExtraToggles(), this.extraFlowBox) - this.add(Box({ - vertical: true, - children: [ - Label("Extra widgets"), - Label("Drop here to remove or drag from here to add"), - this.extraFlowBox - ] - })) - } - } - - _getExtraToggles() { - let toggles = { ...this.toggles } - this.currentToggles.map(t => { - if (toggles[t]) { - delete toggles[t]; - } - }); - return Object.keys(toggles); - } - - _setupFlowBox(className) { - const flowBox = new Gtk.FlowBox(); - flowBox.set_valign(Gtk.Align.FILL); - flowBox.set_min_children_per_line(2); - flowBox.set_max_children_per_line(2); - flowBox.set_selection_mode(Gtk.SelectionMode.NONE); - flowBox.get_style_context().add_class(className); - flowBox.set_homogeneous(true); - flowBox.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY); - - return flowBox; - } - - createWidget = (name, index, type) => { - const editSetup = (widget) => { - widget.drag_source_set( - Gdk.ModifierType.BUTTON1_MASK, - TARGET, - Gdk.DragAction.COPY - ); - - widget.connect("drag-begin", (w, context) => { - const widgetContainer = widget.get_parent(); - - Gtk.drag_set_icon_surface(context, createSurfaceFromWidget(widgetContainer)); - this._dragged = { - widget: widgetContainer.get_parent().get_parent(), - container: widgetContainer, - name: name, - currentPosition: type === "Main" ? index : null, - currentPositionExtra: type === "Extra" ? index : null, - from: type, - } - widgetContainer.get_style_context().add_class("hidden"); - if (type !== "Main") { - this.extraFlowBox.remove(this._dragged.widget); - } - - - return true; - }); - widget.connect("drag-failed", () => { - this.updateList(Settings.getSetting("toggles"), this.mainFlowBox) - this.updateList(this._getExtraToggles(), this.extraFlowBox) - }); - } - - let row = new Gtk.FlowBoxChild({ visible: true }); - row.add(Toggles[name]({ setup: QSView.editing && editSetup, QSView: QSView })); - row._index = index; - row._name = name; - return row; - } - - updateList(toggles, flowBox) { - let type = flowBox === this.mainFlowBox ? "Main" : "Extra" - var childrenBox = flowBox.get_children(); - childrenBox.forEach((element) => { - flowBox.remove(element); - element.destroy(); - }); - - if (!toggles) return; - - toggles.forEach((name, i) => { - if (Toggles[name]) - flowBox.add(this.createWidget(name, i, type)); - }); - flowBox.show_all(); - } - - - _dragMotionMain = (widget, context, x, y, time) => { - if (this._dragged.currentPositionExtra !== null) { - this._dragged.currentPositionExtra = null; - if (this._isChild(this.extraFlowBox, this._dragged.widget)) { - this.extraFlowBox.remove(this._dragged.widget); - } - } - const children = this.mainFlowBox.get_children(); - const sampleItem = children[0]; - const sampleWidth = sampleItem.get_allocation().width; - const sampleHeight = sampleItem.get_allocated_height(); - const perLine = Math.floor(this.mainFlowBox.get_allocation().width / sampleWidth); - const pos = Math.floor(y / sampleHeight) * perLine + Math.floor(x / sampleWidth); - if (pos >= children.length && pos !== 0) return false; - - if (this._dragged.currentPosition === null) { - this.mainFlowBox.insert(this._dragged.widget, pos); - - this._dragged.currentPosition = pos; - } else if (this._dragged.currentPosition !== pos) { - if (this._isChild(this.mainFlowBox, this._dragged.widget)) { - this.mainFlowBox.remove(this._dragged.widget); - } - - this.mainFlowBox.insert(this._dragged.widget, pos); - - this._dragged.currentPosition = pos; - } - - return true; - } - - _dragDropMain = () => { - if (this._dragged.from !== "Main") { - this.currentToggles.splice(this._dragged.currentPosition, 0, this._dragged.name); - } else { - const indexCurrentToggle = this.currentToggles.indexOf(this._dragged.name); - this.currentToggles.splice(indexCurrentToggle, 1); - this.currentToggles.splice(this._dragged.currentPosition, 0, this._dragged.name); - } - - Settings.setSetting("toggles", this.currentToggles); - this._dragged.container.get_style_context().remove_class("hidden"); - return true; - } - - _dragDropExtra = () => { - if (this._dragged.from === "Main") { - const indexCurrentToggle = this.currentToggles.indexOf(this._dragged.name); - this.currentToggles.splice(indexCurrentToggle, 1); - } - - Settings.setSetting("toggles", this.currentToggles); - this._dragged.container.get_style_context().remove_class("hidden"); - return true; - } - - _dragMotionExtra = (widget, context, x, y, time) => { - if (this._dragged.currentPosition !== null) { - this._dragged.currentPosition = null; - if (this._isChild(this.mainFlowBox, this._dragged.widget)) { - this.mainFlowBox.remove(this._dragged.widget); - } - } - - const children = this.extraFlowBox.get_children(); - const sampleItem = children[0]; - let pos = 0; - if (sampleItem) { - const sampleWidth = sampleItem.get_allocation().width; - const sampleHeight = sampleItem.get_allocated_height(); - const perLine = Math.floor(this.extraFlowBox.get_allocation().width / sampleWidth); - pos = Math.floor(y / sampleHeight) * perLine + Math.floor(x / sampleWidth); - } - - if (pos >= children.length && pos !== 0) return false; - - if (this._dragged.currentPositionExtra === null) { - this.extraFlowBox.insert(this._dragged.widget, pos); - - this._dragged.currentPositionExtra = pos; - } - - if (this._dragged.currentPositionExtra !== pos) { - if (this._isChild(this.extraFlowBox, this._dragged.widget)) { - this.extraFlowBox.remove(this._dragged.widget); - } - - this.extraFlowBox.insert(this._dragged.widget, pos); - - this._dragged.currentPositionExtra = pos; - } - - return true; - } - - _isChild(container, widget) { - let found = false; - container.get_children().forEach((c) => { - if (c === widget) found = true; - }) - return found; - } -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/modules/lib/animatedcircularprogress.js b/home/desktops/hyprland/ags/modules/lib/animatedcircularprogress.js deleted file mode 100644 index 9ea548f..0000000 --- a/home/desktops/hyprland/ags/modules/lib/animatedcircularprogress.js +++ /dev/null @@ -1,74 +0,0 @@ -const { Gdk, Gtk } = imports.gi; -const GObject = imports.gi.GObject; -const Lang = imports.lang; -import { Utils, Widget } from '../../imports.js'; - -// min-height for diameter -// min-width for trough stroke -// padding for space between trough and progress -// margin for space between widget and parent -// background-color for trough color -// color for progress color -// font size for progress value (0-100px) (hacky i know, but i want animations) -// TODO: border-radius for rounded ends maybe (unimportant) -export const AnimatedCircProg = (props) => Widget({ - ...props, - type: Gtk.DrawingArea, - setup: (area) => { - const styleContext = area.get_style_context(); - const width = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL); - const height = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL); - const padding = styleContext.get_padding(Gtk.StateFlags.NORMAL).left; - const marginLeft = styleContext.get_margin(Gtk.StateFlags.NORMAL).left; - const marginRight = styleContext.get_margin(Gtk.StateFlags.NORMAL).right; - const marginTop = styleContext.get_margin(Gtk.StateFlags.NORMAL).top; - const marginBottom = styleContext.get_margin(Gtk.StateFlags.NORMAL).bottom; - area.set_size_request(width + marginLeft + marginRight, height + marginTop + marginBottom); - area.connect('draw', Lang.bind(area, (area, cr) => { - const styleContext = area.get_style_context(); - const width = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL); - const height = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL); - const padding = styleContext.get_padding(Gtk.StateFlags.NORMAL).left; - const marginLeft = styleContext.get_margin(Gtk.StateFlags.NORMAL).left; - const marginRight = styleContext.get_margin(Gtk.StateFlags.NORMAL).right; - const marginTop = styleContext.get_margin(Gtk.StateFlags.NORMAL).top; - const marginBottom = styleContext.get_margin(Gtk.StateFlags.NORMAL).bottom; - area.set_size_request(width + marginLeft + marginRight, height + marginTop + marginBottom); - - const progressValue = styleContext.get_property('font-size', Gtk.StateFlags.NORMAL) / 100.0; - - const bg_stroke = styleContext.get_property('min-width', Gtk.StateFlags.NORMAL); - const fg_stroke = bg_stroke - padding; - const radius = Math.min(width, height) / 2.0 - Math.max(bg_stroke, fg_stroke) / 2.0; - const center_x = width / 2.0 + marginLeft; - const center_y = height / 2.0 + marginTop; - const start_angle = -Math.PI / 2.0; - const end_angle = start_angle + (2 * Math.PI * progressValue); - const start_x = center_x + Math.cos(start_angle) * radius; - const start_y = center_y + Math.sin(start_angle) * radius; - const end_x = center_x + Math.cos(end_angle) * radius; - const end_y = center_y + Math.sin(end_angle) * radius; - - // Draw background - const background_color = styleContext.get_property('background-color', Gtk.StateFlags.NORMAL); - cr.setSourceRGBA(background_color.red, background_color.green, background_color.blue, background_color.alpha); - cr.arc(center_x, center_y, radius, 0, 2 * Math.PI); - cr.setLineWidth(bg_stroke); - cr.stroke(); - - // Draw progress - const color = styleContext.get_property('color', Gtk.StateFlags.NORMAL); - cr.setSourceRGBA(color.red, color.green, color.blue, color.alpha); - cr.arc(center_x, center_y, radius, start_angle, end_angle); - cr.setLineWidth(fg_stroke); - cr.stroke(); - - // Draw rounded ends for progress arcs - cr.setLineWidth(0); - cr.arc(start_x, start_y, fg_stroke / 2, 0, 0 - 0.01); - cr.fill(); - cr.arc(end_x, end_y, fg_stroke / 2, 0, 0 - 0.01); - cr.fill(); - })) - }, -}) \ No newline at end of file diff --git a/home/desktops/hyprland/ags/modules/lib/contextmenuitem.js b/home/desktops/hyprland/ags/modules/lib/contextmenuitem.js deleted file mode 100644 index 8dca27c..0000000 --- a/home/desktops/hyprland/ags/modules/lib/contextmenuitem.js +++ /dev/null @@ -1,10 +0,0 @@ -const { Gdk, Gtk } = imports.gi; -import { Widget } from '../../imports.js'; - -export const ContextMenuItem = ({ label, onClick }) => Widget({ - type: Gtk.MenuItem, - label: `${label}`, - setup: menuItem => { - menuItem.connect("activate", onClick); - } -}) \ No newline at end of file diff --git a/home/desktops/hyprland/ags/modules/lib/cursorhover.js b/home/desktops/hyprland/ags/modules/lib/cursorhover.js deleted file mode 100644 index 89717df..0000000 --- a/home/desktops/hyprland/ags/modules/lib/cursorhover.js +++ /dev/null @@ -1,70 +0,0 @@ -const { Gdk, Gtk } = imports.gi; - -const CLICK_BRIGHTEN_AMOUNT = 0.13; - -export function setupCursorHover(button) { - var clicked = false; - var dummy = false; - var cursorX = 0; - var cursorY = 0; - const styleContext = button.get_style_context(); - var clickColor = styleContext.get_property('background-color', Gtk.StateFlags.HOVER); - clickColor.green += CLICK_BRIGHTEN_AMOUNT; - clickColor.blue += CLICK_BRIGHTEN_AMOUNT; - clickColor.red += CLICK_BRIGHTEN_AMOUNT; - clickColor = clickColor.to_string(); - - const display = Gdk.Display.get_default(); - button.connect('enter-notify-event', () => { - const cursor = Gdk.Cursor.new_from_name(display, 'pointer'); - button.get_window().set_cursor(cursor); - }); - - button.connect('leave-notify-event', () => { - const cursor = Gdk.Cursor.new_from_name(display, 'default'); - button.get_window().set_cursor(cursor); - }); - - // button.add_events(Gdk.EventMask.POINTER_MOTION_MASK); - // button.connect('motion-notify-event', (widget, event) => { - // [dummy, cursorX, cursorY] = event.get_coords(); // Get the mouse coordinates relative to the widget - // if(!clicked) widget.style = ` - // background-image: radial-gradient(circle at ${cursorX}px ${cursorY}px, rgba(0,0,0,0), rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%, ${clickColor} 0%, ${clickColor} 0%, ${clickColor} 0%, ${clickColor} 0%, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%); - // `; - // }); - - // button.connect('button-press-event', (widget, event) => { - // clicked = true; - // [dummy, cursorX, cursorY] = event.get_coords(); // Get the mouse coordinates relative to the widget - // cursorX = Math.round(cursorX); cursorY = Math.round(cursorY); - // widget.style = ` - // background-image: radial-gradient(circle at ${cursorX}px ${cursorY}px, rgba(0,0,0,0), rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%, ${clickColor} 0%, ${clickColor} 0%, ${clickColor} 0%, ${clickColor} 0%, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%); - // `; - // widget.toggleClassName('growingRadial', true); - // widget.style = ` - // background-image: radial-gradient(circle at ${cursorX}px ${cursorY}px, rgba(0,0,0,0), rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%, ${clickColor} 0%, ${clickColor} 0%, ${clickColor} 70%, ${clickColor} 70%, rgba(0,0,0,0) 70%, rgba(0,0,0,0) 70%); - // ` - // }); - // button.connect('button-release-event', (widget, event) => { - // widget.toggleClassName('growingRadial', false); - // widget.toggleClassName('fadingRadial', false); - // widget.style = ` - // background-image: radial-gradient(circle at ${cursorX}px ${cursorY}px, rgba(0,0,0,0), rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 70%, rgba(0,0,0,0) 70%, rgba(0,0,0,0) 70%, rgba(0,0,0,0) 70%); - // ` - // clicked = false; - // }); -} - -export function setupCursorHoverAim(button) { - button.connect('enter-notify-event', () => { - const display = Gdk.Display.get_default(); - const cursor = Gdk.Cursor.new_from_name(display, 'crosshair'); - button.get_window().set_cursor(cursor); - }); - - button.connect('leave-notify-event', () => { - const display = Gdk.Display.get_default(); - const cursor = Gdk.Cursor.new_from_name(display, 'default'); - button.get_window().set_cursor(cursor); - }); -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/modules/lib/materialicon.js b/home/desktops/hyprland/ags/modules/lib/materialicon.js deleted file mode 100644 index 6bcb6c6..0000000 --- a/home/desktops/hyprland/ags/modules/lib/materialicon.js +++ /dev/null @@ -1,7 +0,0 @@ -import { Widget } from '../../imports.js'; - -export const MaterialIcon = (icon, size, props = {}) => Widget.Label({ - className: `icon-material txt-${size}`, - label: icon, - ...props, -}) \ No newline at end of file diff --git a/home/desktops/hyprland/ags/modules/lib/navigationindicator.js b/home/desktops/hyprland/ags/modules/lib/navigationindicator.js deleted file mode 100644 index b0a6340..0000000 --- a/home/desktops/hyprland/ags/modules/lib/navigationindicator.js +++ /dev/null @@ -1,73 +0,0 @@ -const { Gdk, Gtk } = imports.gi; -const GObject = imports.gi.GObject; -const Lang = imports.lang; -import { Utils, Widget } from '../../imports.js'; - -// min-height/min-width for height/width -// background-color/color for background/indicator color -// padding for pad of indicator -// font-size for selected index (0-based) -export const NavigationIndicator = (count, vertical, props) => Widget({ - ...props, - type: Gtk.DrawingArea, - setup: (area) => { - const styleContext = area.get_style_context(); - const width = Math.max(styleContext.get_property('min-width', Gtk.StateFlags.NORMAL), area.get_allocated_width()); - const height = Math.max(styleContext.get_property('min-height', Gtk.StateFlags.NORMAL), area.get_allocated_height()); - area.set_size_request(width, height); - - area.connect('draw', Lang.bind(area, (area, cr) => { - const styleContext = area.get_style_context(); - const width = Math.max(styleContext.get_property('min-width', Gtk.StateFlags.NORMAL), area.get_allocated_width()); - const height = Math.max(styleContext.get_property('min-height', Gtk.StateFlags.NORMAL), area.get_allocated_height()); - // console.log('allocated width/height:', area.get_allocated_width(), '/', area.get_allocated_height()) - area.set_size_request(width, height); - const paddingLeft = styleContext.get_padding(Gtk.StateFlags.NORMAL).left; - const paddingRight = styleContext.get_padding(Gtk.StateFlags.NORMAL).right; - const paddingTop = styleContext.get_padding(Gtk.StateFlags.NORMAL).top; - const paddingBottom = styleContext.get_padding(Gtk.StateFlags.NORMAL).bottom; - - const selectedCell = styleContext.get_property('font-size', Gtk.StateFlags.NORMAL); - - let cellWidth = width; - let cellHeight = height; - if (vertical) cellHeight /= count; - else cellWidth /= count; - const indicatorWidth = cellWidth - paddingLeft - paddingRight; - const indicatorHeight = cellHeight - paddingTop - paddingBottom; - - const background_color = styleContext.get_property('background-color', Gtk.StateFlags.NORMAL); - const color = styleContext.get_property('color', Gtk.StateFlags.NORMAL); - cr.setLineWidth(2); - // Background - cr.setSourceRGBA(background_color.red, background_color.green, background_color.blue, background_color.alpha); - cr.rectangle(0, 0, width, height); - cr.fill(); - - // The indicator line - cr.setSourceRGBA(color.red, color.green, color.blue, color.alpha); - if (vertical) { - cr.rectangle(paddingLeft, paddingTop + cellHeight * selectedCell + indicatorWidth / 2, indicatorWidth, indicatorHeight - indicatorWidth); - cr.stroke(); - cr.rectangle(paddingLeft, paddingTop + cellHeight * selectedCell + indicatorWidth / 2, indicatorWidth, indicatorHeight - indicatorWidth); - cr.fill(); - cr.arc(paddingLeft + indicatorWidth / 2, paddingTop + cellHeight * selectedCell + indicatorWidth / 2, indicatorWidth / 2, Math.PI, 2 * Math.PI); - cr.fill(); - cr.arc(paddingLeft + indicatorWidth / 2, paddingTop + cellHeight * selectedCell + indicatorHeight - indicatorWidth / 2, indicatorWidth / 2, 0, Math.PI); - cr.fill(); - } - else { - cr.rectangle(paddingLeft + cellWidth * selectedCell + indicatorHeight / 2, paddingTop, indicatorWidth - indicatorHeight, indicatorHeight); - cr.stroke(); - cr.rectangle(paddingLeft + cellWidth * selectedCell + indicatorHeight / 2, paddingTop, indicatorWidth - indicatorHeight, indicatorHeight); - cr.fill(); - cr.arc(paddingLeft + cellWidth * selectedCell + indicatorHeight / 2, paddingTop + indicatorHeight / 2, indicatorHeight / 2, 0.5 * Math.PI, 1.5 * Math.PI); - cr.fill(); - cr.arc(paddingLeft + cellWidth * selectedCell + indicatorWidth - indicatorHeight / 2, paddingTop + indicatorHeight / 2, indicatorHeight / 2, -0.5 * Math.PI, 0.5 * Math.PI); - cr.fill(); - } - })) - }, -}) - - diff --git a/home/desktops/hyprland/ags/modules/lib/notification.js b/home/desktops/hyprland/ags/modules/lib/notification.js deleted file mode 100644 index 6ae5a56..0000000 --- a/home/desktops/hyprland/ags/modules/lib/notification.js +++ /dev/null @@ -1,298 +0,0 @@ -// This file is for the actual widget for each single notification - -const { GLib, Gdk, Gtk } = imports.gi; -import { Utils, Widget } from '../../imports.js'; -const { lookUpIcon, timeout } = Utils; -const { Box, EventBox, Icon, Scrollable, Label, Button, Revealer } = Widget; -import { MaterialIcon } from "./materialicon.js"; -import { setupCursorHover } from "./cursorhover.js"; - -const NotificationIcon = (notifObject) => { - // { appEntry, appIcon, image }, urgency = 'normal' - if (notifObject.image) { - return Box({ - valign: 'center', - hexpand: false, - className: 'notif-icon', - style: ` - background-image: url("${notifObject.image}"); - background-size: auto 100%; - background-repeat: no-repeat; - background-position: center; - `, - }); - } - - let icon = 'NO_ICON'; - if (lookUpIcon(notifObject.appIcon)) - icon = notifObject.appIcon; - if (lookUpIcon(notifObject.appEntry)) - icon = notifObject.appEntry; - - return Box({ - valign: 'center', - hexpand: false, - className: 'notif-icon', - setup: box => { - if (icon != 'NO_ICON') box.pack_start(Icon({ - icon, size: 30, - halign: 'center', hexpand: true, - valign: 'center', - setup: () => { - box.toggleClassName(`notif-icon-material-${notifObject.urgency}`, true); - }, - }), false, true, 0); - else box.pack_start(MaterialIcon(`${notifObject.urgency == 'critical' ? 'release_alert' : 'chat'}`, 'hugeass', { - hexpand: true, - setup: () => box.toggleClassName(`notif-icon-material-${notifObject.urgency}`, true), - }), false, true, 0) - } - }); -}; - -export default ({ - notifObject, - isPopup = false, - props = {}, -} = {}) => { - const command = (isPopup ? - () => notifObject.dismiss() : - () => notifObject.close() - ) - const destroyWithAnims = () => { - widget.sensitive = false; - notificationBox.setStyle(rightAnim1); - Utils.timeout(200, () => { - wholeThing.revealChild = false; - }); - Utils.timeout(400, () => { - command(); - wholeThing.destroy(); - }); - } - const widget = EventBox({ - onHover: (self) => { - self.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grab')); - if (!wholeThing._hovered) - wholeThing._hovered = true; - }, - onHoverLost: (self) => { - self.window.set_cursor(null); - if (wholeThing._hovered) - wholeThing._hovered = false; - if(isPopup) { - command(); - } - }, - onMiddleClick: (self) => { - destroyWithAnims(); - } - }); - const wholeThing = Revealer({ - properties: [ - ['id', notifObject.id], - ['close', undefined], - ['hovered', false], - ['dragging', false], - ['destroyWithAnims', () => destroyWithAnims] - ], - revealChild: false, - transition: 'slide_down', - transitionDuration: 200, - child: Box({ // Box to make sure css-based spacing works - homogeneous: true, - }) - }); - - const display = Gdk.Display.get_default(); - const notificationContent = Box({ - ...props, - className: `${isPopup ? 'popup-' : ''}notif-${notifObject.urgency} spacing-h-10`, - children: [ - NotificationIcon(notifObject), - Box({ - valign: 'center', - vertical: true, - hexpand: true, - children: [ - Box({ - children: [ - Label({ - xalign: 0, - className: 'txt-small txt-semibold titlefont', - justify: Gtk.Justification.LEFT, - hexpand: true, - maxWidthChars: 24, - ellipsize: 3, - wrap: true, - useMarkup: notifObject.summary.startsWith('<'), - label: notifObject.summary, - }), - ] - }), - Label({ - xalign: 0, - className: 'txt-smallie notif-body-${urgency}', - useMarkup: true, - xalign: 0, - justify: Gtk.Justification.LEFT, - wrap: true, - label: notifObject.body, - }), - ] - }), - Box({ - className: 'spacing-h-5', - children: [ - Label({ - valign: 'center', - className: 'txt-smaller txt-semibold', - justify: Gtk.Justification.RIGHT, - setup: (label) => { - const messageTime = GLib.DateTime.new_from_unix_local(notifObject.time); - if (messageTime.get_day_of_year() == GLib.DateTime.new_now_local().get_day_of_year()) { - label.label = messageTime.format('%H:%M'); - } - else if (messageTime.get_day_of_year() == GLib.DateTime.new_now_local().get_day_of_year() - 1) { - label.label = messageTime.format('%H:%M\nYesterday'); - } - else { - label.label = messageTime.format('%H:%M\n%d/%m'); - } - } - }), - Button({ - className: 'notif-close-btn', - onClicked: () => { - destroyWithAnims() - }, - child: MaterialIcon('close', 'large', { - valign: 'center', - }), - setup: (button) => setupCursorHover(button), - }), - ] - }), - - // what is this? i think it should be at the bottom not on the right - // Box({ - // className: 'actions', - // children: actions.map(action => Button({ - // className: 'action-button', - // onClicked: () => Notifications.invoke(id, action.id), - // hexpand: true, - // child: Label(action.label), - // })), - // }), - ] - }) - - // Gesture stuff - - const gesture = Gtk.GestureDrag.new(widget); - var initialDir = 0; - // in px - const startMargin = 0; - const dragThreshold = 100; - // in rem - const maxOffset = 10.227; - const endMargin = 20.455; - const disappearHeight = 6.818; - const leftAnim1 = `transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); - margin-left: -${Number(maxOffset + endMargin)}rem; - margin-right: ${Number(maxOffset + endMargin)}rem; - opacity: 0;`; - - const rightAnim1 = `transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); - margin-left: ${Number(maxOffset + endMargin)}rem; - margin-right: -${Number(maxOffset + endMargin)}rem; - opacity: 0;`; - - const notificationBox = Box({ - properties: [ - ['leftAnim1', leftAnim1], - ['rightAnim1', rightAnim1], - ['ready', false], - ], - homogeneous: true, - children: [notificationContent], - connections: [ - [gesture, self => { - var offset = gesture.get_offset()[1]; - if (initialDir == 0 && offset != 0) - initialDir = (offset > 0 ? 1 : -1) - - if (offset > 0) { - if (initialDir < 0) - self.setStyle(`margin-left: 0px; margin-right: 0px;`); - else - self.setStyle(` - margin-left: ${Number(offset + startMargin)}px; - margin-right: -${Number(offset + startMargin)}px; - `); - } - else if (offset < 0) { - if (initialDir > 0) - self.setStyle(`margin-left: 0px; margin-right: 0px;`); - else { - offset = Math.abs(offset); - self.setStyle(` - margin-right: ${Number(offset + startMargin)}px; - margin-left: -${Number(offset + startMargin)}px; - `); - } - } - - wholeThing._dragging = Math.abs(offset) > 10; - - if (widget.window) - widget.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grabbing')); - }, 'drag-update'], - - [gesture, self => { - if (!self._ready) { - wholeThing.revealChild = true; - self._ready = true; - return; - } - - const offset = gesture.get_offset()[1]; - - if (Math.abs(offset) > dragThreshold && offset * initialDir > 0) { - if (offset > 0) { - self.setStyle(rightAnim1); - widget.sensitive = false; - } - else { - self.setStyle(leftAnim1); - widget.sensitive = false; - } - Utils.timeout(200, () => { - wholeThing.revealChild = false - }); - Utils.timeout(400, () => { - command(); - wholeThing.destroy(); - }); - } - else { - self.setStyle(`transition: margin 200ms cubic-bezier(0.05, 0.7, 0.1, 1), opacity 200ms cubic-bezier(0.05, 0.7, 0.1, 1); - margin-left: ${startMargin}px; - margin-right: ${startMargin}px; - margin-bottom: unset; margin-top: unset; - opacity: 1;`); - if (widget.window) - widget.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grab')); - - wholeThing._dragging = false; - } - initialDir = 0; - }, 'drag-end'], - - ], - }) - widget.add(notificationBox); - wholeThing.child.children = [widget]; - - return wholeThing; -} diff --git a/home/desktops/hyprland/ags/modules/lib/roundedcorner.js b/home/desktops/hyprland/ags/modules/lib/roundedcorner.js deleted file mode 100644 index bef91ca..0000000 --- a/home/desktops/hyprland/ags/modules/lib/roundedcorner.js +++ /dev/null @@ -1,51 +0,0 @@ -import { Widget } from '../../imports.js'; -const { Gtk } = imports.gi; -const Lang = imports.lang; - -export const RoundedCorner = (place, props) => Widget({ - ...props, - type: Gtk.DrawingArea, - halign: place.includes('left') ? 'start' : 'end', - valign: place.includes('top') ? 'start' : 'end', - setup: widget => { - const c = widget.get_style_context().get_property('background-color', Gtk.StateFlags.NORMAL); - const r = widget.get_style_context().get_property('border-radius', Gtk.StateFlags.NORMAL); - widget.set_size_request(r, r); - widget.connect('draw', Lang.bind(widget, (widget, cr) => { - const c = widget.get_style_context().get_property('background-color', Gtk.StateFlags.NORMAL); - const r = widget.get_style_context().get_property('border-radius', Gtk.StateFlags.NORMAL); - // const borderColor = widget.get_style_context().get_property('color', Gtk.StateFlags.NORMAL); - // const borderWidth = widget.get_style_context().get_border(Gtk.StateFlags.NORMAL).left; // ur going to write border-width: something anyway - widget.set_size_request(r, r); - - switch (place) { - case 'topleft': - cr.arc(r, r, r, Math.PI, 3 * Math.PI / 2); - cr.lineTo(0, 0); - break; - - case 'topright': - cr.arc(0, r, r, 3 * Math.PI / 2, 2 * Math.PI); - cr.lineTo(r, 0); - break; - - case 'bottomleft': - cr.arc(r, 0, r, Math.PI / 2, Math.PI); - cr.lineTo(0, r); - break; - - case 'bottomright': - cr.arc(0, 0, r, 0, Math.PI / 2); - cr.lineTo(r, r); - break; - } - - cr.closePath(); - cr.setSourceRGBA(c.red, c.green, c.blue, c.alpha); - cr.fill(); - // cr.setLineWidth(borderWidth); - // cr.setSourceRGBA(borderColor.red, borderColor.green, borderColor.blue, borderColor.alpha); - // cr.stroke(); - })); - }, -}); \ No newline at end of file diff --git a/home/desktops/hyprland/ags/modules/lib/searchitem.js b/home/desktops/hyprland/ags/modules/lib/searchitem.js deleted file mode 100644 index 38f79d0..0000000 --- a/home/desktops/hyprland/ags/modules/lib/searchitem.js +++ /dev/null @@ -1,69 +0,0 @@ -const { Gdk, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../../imports.js'; -const { execAsync, exec } = Utils; -import { setupCursorHover, setupCursorHoverAim } from "./cursorhover.js"; -import { MaterialIcon } from './materialicon.js'; - -export const searchItem = ({ materialIconName, name, actionName, content, onActivate }) => { - const actionText = Widget.Revealer({ - revealChild: false, - transition: "crossfade", - transitionDuration: 200, - child: Widget.Label({ - className: 'overview-search-results-txt txt txt-small txt-action', - label: `${actionName}`, - }) - }); - const actionTextRevealer = Widget.Revealer({ - revealChild: false, - transition: "slide_left", - transitionDuration: 300, - child: actionText, - }) - return Widget.Button({ - className: 'overview-search-result-btn', - onClicked: onActivate, - child: Widget.Box({ - children: [ - Widget.Box({ - vertical: false, - children: [ - Widget.Label({ - className: `icon-material overview-search-results-icon`, - label: `${materialIconName}`, - }), - Widget.Box({ - vertical: true, - children: [ - Widget.Label({ - halign: 'start', - className: 'overview-search-results-txt txt txt-smallie txt-subtext', - label: `${name}`, - truncate: "end", - }), - Widget.Label({ - halign: 'start', - className: 'overview-search-results-txt txt txt-norm', - label: `${content}`, - truncate: "end", - }), - ] - }), - Widget.Box({ hexpand: true }), - actionTextRevealer, - ], - }) - ] - }), - connections: [ - ['focus-in-event', (button) => { - actionText.revealChild = true; - actionTextRevealer.revealChild = true; - }], - ['focus-out-event', (button) => { - actionText.revealChild = false; - actionTextRevealer.revealChild = false; - }], - ] - }); -} diff --git a/home/desktops/hyprland/ags/modules/lib/separator.js b/home/desktops/hyprland/ags/modules/lib/separator.js deleted file mode 100644 index 4eaa02c..0000000 --- a/home/desktops/hyprland/ags/modules/lib/separator.js +++ /dev/null @@ -1,9 +0,0 @@ -const { Gdk, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../../imports.js'; -const { execAsync, exec } = Utils; -import { setupCursorHover, setupCursorHoverAim } from "./cursorhover.js"; -import { MaterialIcon } from './materialicon.js'; - -export const separatorLine = Widget.Box({ - className: 'separator-line', -}) \ No newline at end of file diff --git a/home/desktops/hyprland/ags/modules/misctoggles.js b/home/desktops/hyprland/ags/modules/misctoggles.js deleted file mode 100644 index 0031fca..0000000 --- a/home/desktops/hyprland/ags/modules/misctoggles.js +++ /dev/null @@ -1,111 +0,0 @@ -import { App, Utils, Widget } from '../imports.js'; -const { execAsync, exec } = Utils; -import { MaterialIcon } from "./lib/materialicon.js"; -import { setupCursorHover } from "./lib/cursorhover.js"; - -const RECORD_SCRIPT_DIR = `${App.configDir}/scripts/record-script.sh`; -const RECORDER_PROCESS = 'record-script.sh'; -const CLOSE_ANIM_TIME = 150; - -async function toggleSystemdService(serviceName, button) { - const serviceState = exec(`systemctl is-enabled ${serviceName}`) == 'enabled'; - // console.log(`pkexec bash -c "systemctl ${serviceState ? 'disable' : 'enable'} ${serviceName}"`) - exec(`pkexec bash -c "systemctl ${serviceState ? 'disable' : 'enable'} ${serviceName}"`); - const newServiceState = exec(`systemctl is-enabled ${serviceName}`) == 'enabled'; - button.toggleClassName('sidebar-button-active', newServiceState); - serviceState.toggleClassName('invisible', newServiceState); -} - -const ModuleRecord = (props = {}) => Widget.Button({ - ...props, - className: 'button-minsize sidebar-button-nopad sidebar-button-alone-normal txt-small', - onClicked: () => { - execAsync(['bash', '-c', RECORD_SCRIPT_DIR]).catch(print); - setTimeout(() => { - button.toggleClassName('sidebar-button-active', exec(`pidof ${RECORDER_PROCESS} >/dev/null && echo 1 || echo`) == '1'); - }, CLOSE_ANIM_TIME); - }, - child: MaterialIcon('screen_record', 'larger'), - setup: button => { - button.toggleClassName('sidebar-button-active', exec(`pidof ${RECORDER_PROCESS} >/dev/null && echo 1 || echo`)); - setupCursorHover(button); - } -}) - -const SystemdService = (serviceName) => { - const serviceState = Widget.Label({ - className: `icon-material txt-larger`, - label: 'check', - setup: label => { - // label.toggleClassName('invisible', exec(`bash -c "systemctl is-enabled ${serviceName} >/dev/null && echo ON || echo OFF"`) == 'OFF'); - } - }); - return Widget.Button({ - className: 'button-minsize sidebar-button sidebar-button-alone-normal txt-small', - onClicked: (button) => { - toggleSystemdService(serviceName, button); - }, - setup: button => { - button.toggleClassName('sidebar-button-active', exec(`systemctl is-enabled ${serviceName}`) == 'enabled'); - setupCursorHover(button); - }, - child: Widget.Box({ - setup: box => { - box.pack_start(Widget.Label({ - xalign: 0, - label: serviceName, - }), true, true, 0); - // box.pack_end(serviceState, false, false, 0); - } - }) - }); -} - -export const ModuleMiscToggles = () => { - const PowerSavers = Widget.Revealer({ - revealChild: false, - transition: 'slide_left', - transitionDuration: 100, - child: Widget.Box({ - className: 'spacing-v-5 margin-right-10', - vertical: true, - children: [ - SystemdService('tlp'), - SystemdService('auto-cpufreq'), - ] - }) - }) - const ModulePowerSavers = Widget.Button({ - className: 'button-minsize sidebar-button-nopad sidebar-button-alone-normal txt-small', - child: MaterialIcon('keyboard_arrow_leftenergy_savings_leaf', 'larger', { - xalign: 0.2, - }), - onClicked: (button) => { - const revealed = PowerSavers.revealChild; - PowerSavers.revealChild = !revealed; - button.toggleClassName('sidebar-button-active', !revealed); - button.child.label = revealed ? 'keyboard_arrow_leftenergy_savings_leaf' : 'keyboard_arrow_rightenergy_savings_leaf'; - }, - setup: (button) => setupCursorHover(button), - }) - return Widget.Box({ - className: 'sidebar-group spacing-h-10', - children: [ - PowerSavers, - Widget.Box({ - vertical: true, - className: 'spacing-v-5', - children: [ - ModulePowerSavers, - Widget.Box({ - className: 'spacing-h-5', - children: [ - ModuleNightLight(), - ModuleRecord(), - ] - }) - ] - }) - ] - }); -} diff --git a/home/desktops/hyprland/ags/modules/music.js b/home/desktops/hyprland/ags/modules/music.js deleted file mode 100644 index 667f4d9..0000000 --- a/home/desktops/hyprland/ags/modules/music.js +++ /dev/null @@ -1,78 +0,0 @@ -import { Service, Utils, Widget } from '../imports.js'; -import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js'; -import Audio from 'resource:///com/github/Aylur/ags/service/audio.js'; -const { execAsync, exec } = Utils; -import { AnimatedCircProg } from "./lib/animatedcircularprogress.js"; - -const TrackProgress = () => { - const _updateProgress = (circprog) => { - const mpris = Mpris.getPlayer(''); - if (!mpris) return; - // Set circular progress (font size cuz that's how this hacky circprog works) - circprog.style = `font-size: ${mpris.position / mpris.length * 100}px;` - } - return AnimatedCircProg({ - className: 'bar-music-circprog', - valign: 'center', - connections: [ // Update on change/once every 3 seconds - [Mpris, _updateProgress], - [3000, _updateProgress] - ] - }) -} - -export const ModuleMusic = () => Widget.EventBox({ - onScrollUp: () => execAsync('hyprctl dispatch workspace -1'), - onScrollDown: () => execAsync('hyprctl dispatch workspace +1'), - onSecondaryClick: () => Mpris.getPlayer('')?.next(), - onMiddleClick: () => Mpris.getPlayer('')?.playPause(), - child: Widget.Box({ - className: 'bar-group-margin bar-sides', - children: [ - Widget.Box({ - className: 'bar-group bar-group-standalone bar-group-pad-music spacing-h-10', - children: [ - Widget.Box({ // Wrap a box cuz overlay can't have margins itself - homogeneous: true, - children: [Widget.Overlay({ - child: Widget.Box({ - valign: 'center', - className: 'bar-music-playstate', - children: [Widget.Label({ - valign: 'center', - className: 'bar-music-playstate-txt', - connections: [[Mpris, label => { - const mpris = Mpris.getPlayer(''); - label.label = `${mpris !== null && mpris.playBackStatus == 'Playing' ? '' : ''}`; - }]], - })], - connections: [[Mpris, label => { - const mpris = Mpris.getPlayer(''); - if (!mpris) return; - label.toggleClassName('bar-music-playstate-playing', mpris !== null && mpris.playBackStatus == 'Playing'); - label.toggleClassName('bar-music-playstate', mpris !== null || mpris.playBackStatus == 'Paused'); - }]], - }), - overlays: [ - TrackProgress(), - ] - })] - }), - Widget.Scrollable({ - hexpand: true, - child: Widget.Label({ - className: 'txt txt-smallie', - connections: [[Mpris, label => { - const mpris = Mpris.getPlayer(''); - if (mpris) - label.label = `${mpris.trackTitle} • ${mpris.trackArtists.join(', ')}`; - else - label.label = 'No mewwsic'; - }]], - }) - }) - ] - }) - ] - }) -}); \ No newline at end of file diff --git a/home/desktops/hyprland/ags/modules/musiccontrols.js b/home/desktops/hyprland/ags/modules/musiccontrols.js deleted file mode 100644 index 3712718..0000000 --- a/home/desktops/hyprland/ags/modules/musiccontrols.js +++ /dev/null @@ -1,9 +0,0 @@ -import { Service, Utils, Widget } from '../imports.js'; -const { Box, CenterBox, Label } = Widget; -const { Mpris } = Service; -const { timeout } = Utils; -import { BluetoothIndicator, NetworkIndicator } from "./statusicons.js"; - -export const ModuleMusicControls = () => Box({ - -}) \ No newline at end of file diff --git a/home/desktops/hyprland/ags/modules/notificationlist.js b/home/desktops/hyprland/ags/modules/notificationlist.js deleted file mode 100644 index 6478e00..0000000 --- a/home/desktops/hyprland/ags/modules/notificationlist.js +++ /dev/null @@ -1,123 +0,0 @@ -// This file is for the notification widget on the sidebar -// For the popup notifications, see onscreendisplay.js -// The actual widget for each single notification is in lib/notification.js - -const { GLib, Gtk } = imports.gi; -import { Service, Utils, Widget } from '../imports.js'; -import Notifications from 'resource:///com/github/Aylur/ags/service/notifications.js'; -const { lookUpIcon, timeout } = Utils; -const { Box, Icon, Scrollable, Label, Button, Revealer } = Widget; -import { MaterialIcon } from "./lib/materialicon.js"; -import { setupCursorHover } from "./lib/cursorhover.js"; -import Notification from "./lib/notification.js"; - -const NotificationList = Box({ - vertical: true, - valign: 'start', - className: 'spacing-v-5-revealer', - connections: [ - [Notifications, (box, id) => { - if (box.children.length == 0) { - Notifications.notifications - .forEach(n => { - box.pack_end(Notification({ - notifObject: n, - isPopup: false, - }), false, false, 0) - }); - box.show_all(); - } - else if (id) { - const notif = Notifications.getNotification(id); - - const NewNotif = Notification({ - notifObject: notif, - isPopup: false, - }); - - if (NewNotif) { - box.pack_end(NewNotif, false, false, 0); - box.show_all(); - } - } - }, 'notified'], - - [Notifications, (box, id) => { - if (!id) return; - for (const ch of box.children) { - if (ch._id === id) { - ch._destroyWithAnims(); - } - } - }, 'closed'], - - [Notifications, box => box.visible = Notifications.notifications.length > 0], - ], -}); - -export default (props) => { - const listTitle = Revealer({ - revealChild: false, - connections: [[Notifications, (revealer) => { - revealer.revealChild = (Notifications.notifications.length > 0); - }]], - child: Box({ - valign: 'start', - className: 'sidebar-group-invisible txt', - children: [ - Label({ - hexpand: true, - xalign: 0, - className: 'txt-title-small', - label: 'Notifications', - }), - Button({ - className: 'notif-closeall-btn', - onClicked: () => { - Notifications.clear(); - }, - child: Box({ - className: 'spacing-h-5', - children: [ - MaterialIcon('clear_all', 'norm'), - Label({ - className: 'txt-small', - label: 'Clear', - }) - ] - }), - setup: button => { - setupCursorHover(button); - }, - }) - ] - }) - }); - const listContents = Scrollable({ - hexpand: true, - hscroll: 'never', - vscroll: 'automatic', - child: Widget({ - type: Gtk.Viewport, - className: 'sidebar-viewport', - setup: (viewport) => { - viewport.add(Box({ - vexpand: true, - children: [NotificationList], - })); - } - }) - }); - listContents.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); - const vScrollbar = listContents.get_vscrollbar(); - vScrollbar.get_style_context().add_class('sidebar-scrollbar'); - return Box({ - ...props, - className: 'sidebar-group-invisible spacing-v-5', - vertical: true, - children: [ - listTitle, - listContents, - ] - }); -} diff --git a/home/desktops/hyprland/ags/modules/onscreendisplay.js b/home/desktops/hyprland/ags/modules/onscreendisplay.js deleted file mode 100644 index 217f6e6..0000000 --- a/home/desktops/hyprland/ags/modules/onscreendisplay.js +++ /dev/null @@ -1,192 +0,0 @@ -// This file is for brightness/volume indicator and popup notifications -// For the notification widget on the sidebar, see notificationlist.js -// The actual widget for each single notification is in lib/notification.js - -const { GLib, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../imports.js'; -import Audio from 'resource:///com/github/Aylur/ags/service/audio.js'; -import Notifications from 'resource:///com/github/Aylur/ags/service/notifications.js'; -const { Box, EventBox, Icon, Scrollable, Label, Button, Revealer } = Widget; -import Brightness from '../scripts/brightness.js'; -import Indicator from '../scripts/indicator.js'; -import Notification from './lib/notification.js'; - -const OsdValue = (name, labelConnections, progressConnections, props = {}) => Widget.Box({ // Volume - ...props, - vertical: true, - className: 'osd-bg osd-value', - hexpand: true, - children: [ - Widget.Box({ - vexpand: true, - children: [ - Widget.Label({ - xalign: 0, yalign: 0, hexpand: true, - className: 'osd-label', - label: `${name}`, - }), - Widget.Label({ - hexpand: false, className: 'osd-value-txt', - label: '100', - connections: labelConnections, - }), - ] - }), - Widget.ProgressBar({ - className: 'osd-progress', - hexpand: true, - vertical: false, - connections: progressConnections, - }) - ], -}); - -const brightnessIndicator = OsdValue('Brightness', - [[Brightness, self => { - self.label = `${Math.round(Brightness.screen_value * 100)}`; - }, 'notify::screen-value']], - [[Brightness, (progress) => { - const updateValue = Brightness.screen_value; - progress.value = updateValue; - }, 'notify::screen-value']], -) - -const volumeIndicator = OsdValue('Volume', - [[Audio, (label) => { - label.label = `${Math.round(Audio.speaker?.volume * 100)}`; - }]], - [[Audio, (progress) => { - const updateValue = Audio.speaker?.volume; - if (!isNaN(updateValue)) progress.value = updateValue; - }]], -); - -const indicatorValues = Widget.Revealer({ - transition: 'slide_down', - connections: [ - [Indicator, (revealer, value) => { - revealer.revealChild = (value > -1); - }, 'popup'], - ], - child: Widget.Box({ - halign: 'center', - vertical: false, - children: [ - brightnessIndicator, - volumeIndicator, - ] - }) -}); - -const PopupNotification = (notifObject) => Widget.Box({ - homogeneous: true, - children: [ - Widget.EventBox({ - onHoverLost: () => { - notifObject.dismiss(); - }, - child: Widget.Revealer({ - revealChild: true, - child: Widget.Box({ - children: [Notification({ - notifObject: notifObject, - isPopup: true, - props: { halign: 'fill' }, - })], - }), - }) - }) - ] -}) - -const naiveNotifPopupList = Widget.Box({ - vertical: true, - className: 'spacing-v-5', - connections: [ - [Notifications, (box) => { - box.children = Notifications.popups.reverse() - .map(notifItem => PopupNotification(notifItem)); - }], - ], -}) - -const notifPopupList = Box({ - vertical: true, - className: 'spacing-v-5-revealer', - properties: [ - ['map', new Map()], - - ['dismiss', (box, id, force = false) => { - if (!id || !box._map.has(id) || box._map.get(id)._hovered && !force) - return; - - const notif = box._map.get(id); - // console.log(notif); - notif.revealChild = false; - Utils.timeout(200, () => { - notif._destroyWithAnims(); - }) - }], - - ['notify', (box, id) => { - if (!id || Notifications.dnd) - return; - - if (!Notifications.getNotification(id)) - return; - - box._map.delete(id); - - const notif = Notifications.getNotification(id); - box._map.set(id, Notification({ - notifObject: notif, - isPopup: true, - })); - - box.children = Array.from(box._map.values()).reverse(); - - Utils.timeout(10, () => { - box.get_parent().revealChild = true; - }); - - box._map.get(id).interval = Utils.interval(4500, () => { - const notif = box._map.get(id); - if (!notif._hovered) { - if (notif.interval) { - Utils.timeout(500, () => notif.destroy()); - GLib.source_remove(notif.interval); - notif.interval = undefined; - } - } - }); - }], - ], - connections: [ - [Notifications, (box, id) => box._notify(box, id), 'notified'], - [Notifications, (box, id) => box._dismiss(box, id), 'dismissed'], - [Notifications, (box, id) => box._dismiss(box, id, true), 'closed'], - ], -}); - -const notificationPopups = Widget.Revealer({ - className: 'osd-notifs', - transition: 'slide_down', - connections: [[Notifications, (self) => { - self.revealChild = Notifications.popups.length > 0; - }]], - child: notifPopupList, -}) - -export default () => Widget.EventBox({ - onHover: () => { //make the widget hide when hovering - Indicator.popup(-1); - }, - child: Widget.Box({ - vertical: true, - style: 'padding: 1px;', - children: [ - indicatorValues, - notificationPopups, - ] - }) -}); \ No newline at end of file diff --git a/home/desktops/hyprland/ags/modules/onscreenkeyboard.js b/home/desktops/hyprland/ags/modules/onscreenkeyboard.js deleted file mode 100644 index 5d44d27..0000000 --- a/home/desktops/hyprland/ags/modules/onscreenkeyboard.js +++ /dev/null @@ -1,114 +0,0 @@ -const { Gdk, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../imports.js'; -const { Box, EventBox, Button, Revealer } = Widget; -const { execAsync, exec } = Utils; -import { setupCursorHover, setupCursorHoverAim } from "./lib/cursorhover.js"; -import { MaterialIcon } from './lib/materialicon.js'; -import { separatorLine } from './lib/separator.js'; -import { defaultOskLayout, oskLayouts } from '../data/keyboardlayouts.js'; - -const keyboardLayout = defaultOskLayout; -const keyboardJson = oskLayouts[keyboardLayout]; -execAsync(`ydotoold`).catch(print); // Start ydotool daemon - -function releaseAllKeys() { - const keycodes = Array.from(Array(249).keys()); - execAsync([`ydotool`, `key`, ...keycodes.map(keycode => `${keycode}:0`)]) - .then(console.log('Released all keys')) - .catch(print); -} -var modsPressed = false; - -const keyboardControlButton = (icon, text, runFunction) => Button({ - className: 'osk-control-button spacing-h-10', - onClicked: () => runFunction(), - child: Widget.Box({ - children: [ - MaterialIcon(icon, 'norm'), - Widget.Label({ - label: `${text}`, - }), - ] - }) -}) - -const keyboardControls = Box({ - vertical: true, - className: 'spacing-v-5', - children: [ - Button({ - className: 'osk-control-button txt-norm icon-material', - onClicked: () => { - releaseAllKeys(); - App.toggleWindow('osk'); - }, - label: 'keyboard_hide', - }), - Button({ - className: 'osk-control-button txt-norm', - label: `${keyboardJson['name_short']}`, - }), - Button({ - className: 'osk-control-button txt-norm icon-material', - onClicked: () => { // TODO: Proper clipboard widget, since fuzzel doesn't receive mouse inputs - execAsync([`bash`, `-c`, "pkill fuzzel || cliphist list | fuzzel --no-fuzzy --dmenu | cliphist decode | wl-copy"]).catch(print); - }, - label: 'assignment', - }), - ] -}) - -const keyboardItself = (kbJson) => { - return Box({ - vertical: true, - className: 'spacing-v-5', - children: kbJson.keys.map(row => Box({ - vertical: false, - className: 'spacing-h-5', - children: row.map(key => { - return Button({ - className: `osk-key osk-key-${key.shape}`, - hexpand: (key.shape == "space" || key.shape == "expand"), - label: key.label, - setup: (button) => { - let pressed = false; - if (key.keytype == "normal") { - button.connect('pressed', () => { // mouse down - execAsync(`ydotool key ${key.keycode}:1`); - }); - button.connect('clicked', () => { // release - execAsync(`ydotool key ${key.keycode}:0`); - }); - } - else if (key.keytype == "modkey") { - button.connect('pressed', () => { // release - if (pressed) { - execAsync(`ydotool key ${key.keycode}:0`); - button.toggleClassName('osk-key-active', false); - pressed = false; - } - else { - execAsync(`ydotool key ${key.keycode}:1`); - button.toggleClassName('osk-key-active', true); - pressed = true; - modsPressed = true; - } - }); - } - } - }) - }) - })) - }) -} - -export default () => Box({ - vexpand: true, - hexpand: true, - className: 'osk-window spacing-h-10', - children: [ - keyboardControls, - separatorLine, - keyboardItself(keyboardJson), - ], -}); diff --git a/home/desktops/hyprland/ags/modules/overview.js b/home/desktops/hyprland/ags/modules/overview.js deleted file mode 100644 index f5e7425..0000000 --- a/home/desktops/hyprland/ags/modules/overview.js +++ /dev/null @@ -1,580 +0,0 @@ -const { Gdk, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../imports.js'; -import Applications from 'resource:///com/github/Aylur/ags/service/applications.js'; -import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; -const { execAsync, exec } = Utils; -import { setupCursorHover, setupCursorHoverAim } from "./lib/cursorhover.js"; -import { MaterialIcon } from './lib/materialicon.js'; -import { searchItem } from './lib/searchitem.js'; -import { ContextMenuItem } from './lib/contextmenuitem.js'; -import Todo from "../scripts/todo.js"; - -var searching = false; -// Add math funcs -const { abs, sin, cos, tan, cot, asin, acos, atan, acot } = Math; -const pi = Math.PI; -// trigonometric funcs for deg -const sind = x => sin(x * pi / 180); -const cosd = x => cos(x * pi / 180); -const tand = x => tan(x * pi / 180); -const cotd = x => cot(x * pi / 180); -const asind = x => asin(x) * 180 / pi; -const acosd = x => acos(x) * 180 / pi; -const atand = x => atan(x) * 180 / pi; -const acotd = x => acot(x) * 180 / pi; - -const MAX_RESULTS = 10; -const OVERVIEW_SCALE = 0.18; // = overview workspace box / screen size -const TARGET = [Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags.SAME_APP, 0)]; -const searchPromptTexts = [ - 'Try "Kolourpaint"', - 'Try "6*cos(pi)"', - 'Try "sudo pacman -Syu"', - 'Try "How to basic"', - 'Drag n\' drop to move windows', - 'Type to search', -] - -function launchCustomCommand(command) { - App.closeWindow('overview'); - const args = command.split(' '); - if (args[0] == '>raw') { // Mouse raw input - execAsync([`bash`, `-c`, `hyprctl keyword input:force_no_accel $(( 1 - $(hyprctl getoption input:force_no_accel -j | gojq ".int") ))`, `&`]).catch(print); - } - else if (args[0] == '>img') { // Change wallpaper - execAsync([`bash`, `-c`, `${App.configDir}/scripts/color_generation/switchwall.sh`, `&`]).catch(print); - } - else if (args[0] == '>light') { // Light mode - execAsync([`bash`, `-c`, `mkdir -p ~/.cache/ags/user && echo "-l" > ~/.cache/ags/user/colormode.txt`, `&`]).catch(print); - } - else if (args[0] == '>dark') { // Dark mode - execAsync([`bash`, `-c`, `mkdir -p ~/.cache/ags/user && echo "" > ~/.cache/ags/user/colormode.txt`, `&`]).catch(print); - } - else if (args[0] == '>material') { // Light mode - execAsync([`bash`, `-c`, `mkdir -p ~/.cache/ags/user && echo "material" > ~/.cache/ags/user/colorbackend.txt`, `&`]).catch(print); - } - else if (args[0] == '>pywal') { // Dark mode - execAsync([`bash`, `-c`, `mkdir -p ~/.cache/ags/user && echo "pywal" > ~/.cache/ags/user/colorbackend.txt`, `&`]).catch(print); - } - else if (args[0] == '>todo') { // Todo - Todo.add(args.slice(1).join(' ')); - } - else if (args[0] == '>shutdown') { // Shut down - execAsync([`bash`, `-c`, `systemctl poweroff`]).catch(print); - } - else if (args[0] == '>reboot') { // Reboot - execAsync([`bash`, `-c`, `systemctl reboot`]).catch(print); - } - else if (args[0] == '>sleep') { // Sleep - execAsync([`bash`, `-c`, `systemctl suspend`]).catch(print); - } - else if (args[0] == '>logout') { // Log out - execAsync([`bash`, `-c`, `loginctl terminate-user $USER`]).catch(print); - } -} - -function execAndClose(command, terminal) { - App.closeWindow('overview'); - if (terminal) { - execAsync([`bash`, `-c`, `foot fish -C "${command}"`, `&`]).catch(print); - } - else - execAsync(command).catch(print); -} - -function startsWithNumber(str) { - var pattern = /^\d/; - return pattern.test(str); -} - -function substitute(str) { - const subs = [ - { from: 'code-url-handler', to: 'visual-studio-code' }, - { from: 'Code', to: 'visual-studio-code' }, - { from: 'GitHub Desktop', to: 'github-desktop' }, - { from: 'wpsoffice', to: 'wps-office2019-kprometheus' }, - { from: 'gnome-tweaks', to: 'org.gnome.tweaks' }, - { from: 'Minecraft* 1.20.1', to: 'minecraft' }, - { from: '', to: 'image-missing' }, - ]; - - for (const { from, to } of subs) { - if (from === str) - return to; - } - - return str; -} - -function destroyContextMenu(menu) { - if (menu !== null) { - menu.remove_all(); - menu.destroy(); - menu = null; - } -} -const CalculationResultButton = ({ result, text }) => searchItem({ - materialIconName: 'calculate', - name: `Math result`, - actionName: "Copy", - content: `${result}`, - onActivate: () => { - App.closeWindow('overview'); - console.log(result); - execAsync(['bash', '-c', `wl-copy '${result}'`, `&`]).catch(print); - }, -}); - -const DesktopEntryButton = (app) => { - const actionText = Widget.Revealer({ - revealChild: false, - transition: "crossfade", - transitionDuration: 200, - child: Widget.Label({ - className: 'overview-search-results-txt txt txt-small txt-action', - label: 'Launch', - }) - }); - const actionTextRevealer = Widget.Revealer({ - revealChild: false, - transition: "slide_left", - transitionDuration: 300, - child: actionText, - }); - return Widget.Button({ - className: 'overview-search-result-btn', - onClicked: () => { - App.closeWindow('overview'); - app.launch(); - }, - child: Widget.Box({ - children: [ - Widget.Box({ - vertical: false, - children: [ - Widget.Icon({ - className: 'overview-search-results-icon', - icon: app.iconName, - size: 35, // TODO: Make this follow font size. made for 11pt. - }), - Widget.Label({ - className: 'overview-search-results-txt txt txt-norm', - label: app.name, - }), - Widget.Box({ hexpand: true }), - actionTextRevealer, - ] - }) - ] - }), - connections: [ - ['focus-in-event', (button) => { - actionText.revealChild = true; - actionTextRevealer.revealChild = true; - }], - ['focus-out-event', (button) => { - actionText.revealChild = false; - actionTextRevealer.revealChild = false; - }], - ] - }) -} - -const ExecuteCommandButton = ({ command, terminal = false }) => searchItem({ - materialIconName: `${terminal ? 'terminal' : 'settings_b_roll'}`, - name: `Run command`, - actionName: `Execute ${terminal ? 'in terminal' : ''}`, - content: `${command}`, - onActivate: () => execAndClose(command, terminal), -}) - -const CustomCommandButton = ({ text = '' }) => searchItem({ - materialIconName: 'settings_suggest', - name: 'Action', - actionName: 'Run', - content: `${text}`, - onActivate: () => { - App.closeWindow('overview'); - launchCustomCommand(text); - }, -}); - -const SearchButton = ({ text = '' }) => searchItem({ - materialIconName: 'travel_explore', - name: 'Search Google', - actionName: 'Go', - content: `${text}`, - onActivate: () => { - App.closeWindow('overview'); - execAsync(['xdg-open', `https://www.google.com/search?q=${text}`]).catch(print); - }, -}); - -const ContextWorkspaceArray = ({ label, onClickBinary, thisWorkspace }) => Widget({ - type: Gtk.MenuItem, - label: `${label}`, - setup: menuItem => { - let submenu = new Gtk.Menu(); - submenu.className = 'menu'; - for (let i = 1; i <= 10; i++) { - let button = new Gtk.MenuItem({ label: `${i}` }); - button.connect("activate", () => { - execAsync([`${onClickBinary}`, `${thisWorkspace}`, `${i}`]).catch(print); - }); - submenu.append(button); - } - menuItem.set_reserve_indicator(true); - menuItem.set_submenu(submenu); - } -}) - -const client = ({ address, size: [w, h], workspace: { id, name }, class: c, title }) => Widget.Button({ - className: 'overview-tasks-window', - halign: 'center', - valign: 'center', - onClicked: () => { - execAsync([`bash`, `-c`, `hyprctl dispatch focuswindow address:${address}`, `&`]).catch(print); - App.closeWindow('overview'); - }, - onMiddleClick: () => execAsync([`bash`, `-c`, `hyprctl dispatch closewindow address:${address}`, `&`]).catch(print), - onSecondaryClick: (button) => { - button.toggleClassName('overview-tasks-window-selected', true); - const menu = Widget({ - type: Gtk.Menu, - className: 'menu', - setup: menu => { - menu.append(ContextMenuItem({ label: "Close (Middle-click)", onClick: () => { execAsync([`bash`, `-c`, `hyprctl dispatch closewindow address:${address}`, `&`]).catch(print); destroyContextMenu(menu); } })); - menu.append(ContextWorkspaceArray({ label: "Dump windows to workspace", onClickBinary: `${App.configDir}/scripts/dumptows`, thisWorkspace: Number(id) })); - menu.append(ContextWorkspaceArray({ label: "Swap windows with workspace", onClickBinary: `${App.configDir}/scripts/dumptows`, thisWorkspace: Number(id) })); - menu.show_all(); - } - }); - menu.connect("deactivate", () => { - button.toggleClassName('overview-tasks-window-selected', false); - }) - menu.connect("selection-done", () => { - button.toggleClassName('overview-tasks-window-selected', false); - }) - menu.popup_at_pointer(null); // Show the menu at the pointer's position - }, - child: Widget.Box({ - vertical: true, - children: [ - Widget.Icon({ - style: ` - min-width: ${w * OVERVIEW_SCALE - 4}px; - min-height: ${h * OVERVIEW_SCALE - 4}px; - `, - size: Math.min(w, h) * OVERVIEW_SCALE / 2.5, - icon: substitute(c), - }), - Widget.Scrollable({ - hexpand: true, - vexpand: true, - child: Widget.Label({ - style: ` - font-size: ${Math.min(w, h) * OVERVIEW_SCALE / 20}px; - `, - label: title, - }) - }) - ] - }), - tooltipText: `${c}: ${title}`, - setup: (button) => { - setupCursorHoverAim(button); - - button.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, TARGET, Gdk.DragAction.MOVE); - button.drag_source_set_icon_name(substitute(c)); - // button.drag_source_set_icon_gicon(icon); - - button.connect('drag-begin', (button) => { // On drag start, add the dragging class - button.toggleClassName('overview-tasks-window-dragging', true); - }); - button.connect('drag-data-get', (_w, _c, data) => { // On drag finish, give address - data.set_text(address, address.length); - button.toggleClassName('overview-tasks-window-dragging', false); - }); - - // button.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, TARGET, Gdk.DragAction.COPY); - // button.connect('drag-data-get', (_w, _c, data) => data.set_text(address, address.length)); - // button.connect('drag-begin', (_, context) => { - // Gtk.drag_set_icon_surface(context, createSurfaceFromWidget(button)); - // button.toggleClassName('hidden', true); - // }); - // button.connect('drag-end', () => button.toggleClassName('hidden', false)); - - }, -}); - -const workspace = index => { - const fixed = Gtk.Fixed.new(); - const widget = Widget.Box({ - className: 'overview-tasks-workspace', - valign: 'center', - style: ` - min-width: ${SCREEN_WIDTH * OVERVIEW_SCALE}px; - min-height: ${SCREEN_HEIGHT * OVERVIEW_SCALE}px; - `, - connections: [[Hyprland, box => { - box.toggleClassName('active', Hyprland.active.workspace.id === index); - }]], - children: [Widget.EventBox({ - hexpand: true, - vexpand: true, - onPrimaryClickRelease: () => { - execAsync([`bash`, `-c`, `hyprctl dispatch workspace ${index}`, `&`]).catch(print); - App.closeWindow('overview'); - }, - // onSecondaryClick: (eventbox) => { - // const menu = Widget({ - // type: Gtk.Menu, - // setup: menu => { - // menu.append(ContextWorkspaceArray({ label: "Dump windows to workspace", onClickBinary: `${App.configDir}/scripts/dumptows`, thisWorkspace: Number(index) })); - // menu.append(ContextWorkspaceArray({ label: "Swap windows with workspace", onClickBinary: `${App.configDir}/scripts/dumptows`, thisWorkspace: Number(index) })); - // menu.show_all(); - // } - // }); - // menu.popup_at_pointer(null); // Show the menu at the pointer's position - // }, - setup: eventbox => { - eventbox.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY); - eventbox.connect('drag-data-received', (_w, _c, _x, _y, data) => { - execAsync([`bash`, `-c`, `hyprctl dispatch movetoworkspacesilent ${index},address:${data.get_text()}`, `&`]).catch(print); - }); - }, - child: fixed, - })], - }); - widget.update = clients => { - clients = clients.filter(({ workspace: { id } }) => id === index); - - // this is for my monitor layout - // shifts clients back by SCREEN_WIDTHpx if necessary - clients = clients.map(client => { - // console.log(client); - const [x, y] = client.at; - if (x > SCREEN_WIDTH) - client.at = [x - SCREEN_WIDTH, y]; - return client; - }); - - fixed.get_children().forEach(ch => ch.destroy()); - clients.forEach(c => c.mapped && fixed.put(client(c), c.at[0] * OVERVIEW_SCALE, c.at[1] * OVERVIEW_SCALE)); - fixed.show_all(); - }; - return widget; -}; - -const arr = (s, n) => { - const array = []; - for (let i = 0; i < n; i++) - array.push(s + i); - - return array; -}; - -const OverviewRow = ({ startWorkspace = 1, workspaces = 5, windowName = 'overview' }) => Widget.Box({ - children: arr(startWorkspace, workspaces).map(workspace), - properties: [['update', box => { - execAsync('hyprctl -j clients').then(clients => { - const json = JSON.parse(clients); - box.get_children().forEach(ch => ch.update(json)); - }).catch(print); - }]], - setup: box => box._update(box), - connections: [[Hyprland, box => { - if (!App.getWindow(windowName).visible) - return; - - box._update(box); - }]], -}); - - -export const SearchAndWindows = () => { - var _appSearchResults = []; - - const clickOutsideToClose = Widget.EventBox({ - onPrimaryClick: () => App.closeWindow('overview'), - onSecondaryClick: () => App.closeWindow('overview'), - onMiddleClick: () => App.closeWindow('overview'), - }); - const resultsBox = Widget.Box({ - className: 'spacing-v-15 overview-search-results', - vertical: true, - vexpand: true, - }); - const resultsRevealer = Widget.Revealer({ - transitionDuration: 200, - revealChild: false, - transition: 'slide_down', - // duration: 200, - halign: 'center', - child: resultsBox, - }); - const overviewRevealer = Widget.Revealer({ - revealChild: true, - transition: 'slide_down', - transitionDuration: 200, - child: Widget.Box({ - vertical: true, - className: 'overview-tasks', - children: [ - OverviewRow({ startWorkspace: 1, workspaces: 5 }), - OverviewRow({ startWorkspace: 6, workspaces: 5 }), - ] - }), - }); - const entryPromptRevealer = Widget.Revealer({ - transition: 'crossfade', - transitionDuration: 150, - revealChild: true, - halign: 'center', - child: Widget.Label({ - className: 'overview-search-prompt txt-small txt', - label: searchPromptTexts[Math.floor(Math.random() * searchPromptTexts.length)], - }) - }); - - const entryIconRevealer = Widget.Revealer({ - transition: 'crossfade', - transitionDuration: 150, - revealChild: false, - halign: 'end', - child: Widget.Label({ - className: 'txt txt-large icon-material overview-search-icon', - label: 'search', - }), - }); - - const entryIcon = Widget.Box({ - className: 'overview-search-prompt-box', - setup: box => box.pack_start(entryIconRevealer, true, true, 0), - }); - - const entry = Widget.Entry({ - className: 'overview-search-box txt-small txt', - halign: 'center', - onAccept: ({ text }) => { // This is when you press Enter - const isAction = text.startsWith('>'); - if (startsWithNumber(text)) { // Eval on typing is dangerous, this is a workaround - try { - const fullResult = eval(text); - // copy - execAsync(['bash', '-c', `wl-copy '${fullResult}'`, `&`]).catch(print); - App.closeWindow('overview'); - return; - } catch (e) { - // console.log(e); - } - } - if (_appSearchResults.length > 0) { - App.closeWindow('overview'); - _appSearchResults[0].launch(); - return; - } - else if (text[0] == '>') { // Custom commands - launchCustomCommand(text); - return; - } - // Fallback: Execute command - if (!isAction && exec(`bash -c "command -v ${text.split(' ')[0]}"`) != '') { - if (text.startsWith('sudo')) - execAndClose(text, true); - else - execAndClose(text, false); - } - - else { - App.closeWindow('overview'); - execAsync(['xdg-open', `https://www.google.com/search?q=${text}`]).catch(print); - } - }, - // Actually onChange but this is ta workaround for a bug - connections: [ - ['notify::text', (entry) => { // This is when you type - const isAction = entry.text.startsWith('>'); - resultsBox.get_children().forEach(ch => ch.destroy()); - //check empty if so then dont do stuff - if (entry.text == '') { - resultsRevealer.set_reveal_child(false); - overviewRevealer.set_reveal_child(true); - entryPromptRevealer.set_reveal_child(true); - entryIconRevealer.set_reveal_child(false); - entry.toggleClassName('overview-search-box-extended', false); - searching = false; - } - else { - const text = entry.text; - resultsRevealer.set_reveal_child(true); - overviewRevealer.set_reveal_child(false); - entryPromptRevealer.set_reveal_child(false); - entryIconRevealer.set_reveal_child(true); - entry.toggleClassName('overview-search-box-extended', true); - _appSearchResults = Applications.query(text); - - // Calculate - if (startsWithNumber(text)) { // Eval on typing is dangerous, this is a workaround. - try { - const fullResult = eval(text); - resultsBox.add(CalculationResultButton({ result: fullResult, text: text })); - } catch (e) { - // console.log(e); - } - } - if (isAction) { // Eval on typing is dangerous, this is a workaround. - resultsBox.add(CustomCommandButton({ text: entry.text })); - } - // Add application entries - let appsToAdd = MAX_RESULTS; - _appSearchResults.forEach(app => { - if (appsToAdd == 0) return; - resultsBox.add(DesktopEntryButton(app)); - appsToAdd--; - }); - - // Fallbacks - // if the first word is an actual command - if (!isAction && exec(`bash -c "command -v ${text.split(' ')[0]}"`) != '') { - resultsBox.add(ExecuteCommandButton({ command: entry.text, terminal: entry.text.startsWith('sudo') })); - } - - // Add fallback: search - resultsBox.add(SearchButton({ text: entry.text })); - resultsBox.show_all(); - searching = true; - } - }] - ], - }); - - return Widget.Box({ - vertical: true, - children: [ - clickOutsideToClose, - Widget.Box({ - halign: 'center', - children: [ - entry, - Widget.Box({ - className: 'overview-search-icon-box', - setup: box => box.pack_start(entryPromptRevealer, true, true, 0), - }), - entryIcon, - ] - }), - overviewRevealer, - resultsRevealer, - ], - connections: [ - [App, (_b, name, visible) => { - if (name == 'overview' && !visible) { - entryPromptRevealer.child.label = searchPromptTexts[Math.floor(Math.random() * searchPromptTexts.length)]; - resultsBox.children = []; - entry.set_text(''); - } - }], - ], - }); -}; diff --git a/home/desktops/hyprland/ags/modules/quicktoggles.js b/home/desktops/hyprland/ags/modules/quicktoggles.js deleted file mode 100644 index 057d5bf..0000000 --- a/home/desktops/hyprland/ags/modules/quicktoggles.js +++ /dev/null @@ -1,148 +0,0 @@ -import { Widget, Utils, Service } from '../imports.js'; -import Bluetooth from 'resource:///com/github/Aylur/ags/service/bluetooth.js'; -import Network from 'resource:///com/github/Aylur/ags/service/network.js'; -const { execAsync, exec } = Utils; -import { BluetoothIndicator, NetworkIndicator } from "./statusicons.js"; -import { setupCursorHover } from "./lib/cursorhover.js"; -import { MaterialIcon } from './lib/materialicon.js'; - -export const ToggleIconWifi = (props = {}) => Widget.Button({ - className: 'txt-small sidebar-iconbutton', - tooltipText: 'Wifi | Right-click to configure', - onClicked: Network.toggleWifi, - onSecondaryClickRelease: () => { - execAsync(['bash', '-c', 'XDG_CURRENT_DESKTOP="gnome" gnome-control-center wifi', '&']); - }, - child: NetworkIndicator(), - connections: [ - [Network, button => { - button.toggleClassName('sidebar-button-active', Network.wifi?.internet == 'connected' || Network.wired?.internet == 'connected') - }], - [Network, button => { - button.tooltipText = (`${Network.wifi?.ssid} | Right-click to configure` || 'Unknown'); - }], - ], - setup: (button) => setupCursorHover(button), - ...props, -}); - -export const ToggleIconBluetooth = (props = {}) => Widget.Button({ - className: 'txt-small sidebar-iconbutton', - tooltipText: 'Bluetooth | Right-click to configure', - onClicked: () => { // Provided service doesn't work hmmm - const status = Bluetooth?.enabled; - if (status) { - exec('rfkill block bluetooth'); - } - else { - exec('rfkill unblock bluetooth'); - } - }, - onSecondaryClickRelease: () => { - execAsync(['bash', '-c', 'XDG_CURRENT_DESKTOP="gnome" gnome-control-center bluetooth', '&']); - }, - child: BluetoothIndicator(), - connections: [ - [Bluetooth, button => { - button.toggleClassName('sidebar-button-active', Bluetooth?.enabled) - }], - ], - setup: (button) => setupCursorHover(button), - ...props, -}); - -export const HyprToggleIcon = (icon, name, hyprlandConfigValue, props = {}) => Widget.Button({ - className: 'txt-small sidebar-iconbutton', - tooltipText: `${name}`, - onClicked: (button) => { - // Set the value to 1 - value - Utils.execAsync(`hyprctl -j getoption ${hyprlandConfigValue}`).then((result) => { - const currentOption = JSON.parse(result).int; - execAsync(['bash', '-c', `hyprctl keyword ${hyprlandConfigValue} ${1 - currentOption} &`]).catch(print); - button.toggleClassName('sidebar-button-active', currentOption == 0); - }).catch(print); - }, - child: MaterialIcon(icon, 'norm', { halign: 'center' }), - setup: button => { - button.toggleClassName('sidebar-button-active', JSON.parse(Utils.exec(`hyprctl -j getoption ${hyprlandConfigValue}`)).int == 1); - setupCursorHover(button); - }, - ...props, -}) - -export const ModuleNightLight = (props = {}) => Widget.Button({ - className: 'txt-small sidebar-iconbutton', - tooltipText: 'Night Light', - onClicked: (button) => { - // Set the value to 1 - value - const shaderPath = JSON.parse(exec('hyprctl -j getoption decoration:screen_shader')).str; - if (shaderPath != "[[EMPTY]]" && shaderPath != "") { - execAsync(['bash', '-c', `hyprctl keyword decoration:screen_shader ''`]).catch(print); - button.toggleClassName('sidebar-button-active', false); - } - else { - execAsync(['bash', '-c', `hyprctl keyword decoration:screen_shader ~/.config/hypr/shaders/extradark.frag`]).catch(print); - button.toggleClassName('sidebar-button-active', true); - } - }, - child: MaterialIcon('nightlight', 'norm'), - setup: (button) => setupCursorHover(button), - ...props, -}) - -export const ModuleEditIcon = (props = {}) => Widget.Button({ // TODO: Make this work - ...props, - className: 'txt-small sidebar-iconbutton', - onClicked: () => { - execAsync(['bash', '-c', 'XDG_CURRENT_DESKTOP="gnome" gnome-control-center', '&']); - App.toggleWindow('sideright'); - }, - child: MaterialIcon('edit', 'norm'), - setup: button => { - setupCursorHover(button); - } -}) - -export const ModuleReloadIcon = (props = {}) => Widget.Button({ - ...props, - className: 'txt-small sidebar-iconbutton', - tooltipText: 'Reload Hyprland', - onClicked: () => { - execAsync(['bash', '-c', 'hyprctl reload &']); - App.toggleWindow('sideright'); - }, - child: MaterialIcon('refresh', 'norm'), - setup: button => { - setupCursorHover(button); - } -}) - -export const ModuleSettingsIcon = (props = {}) => Widget.Button({ - ...props, - className: 'txt-small sidebar-iconbutton', - tooltipText: 'Open Settings', - onClicked: () => { - execAsync(['bash', '-c', 'XDG_CURRENT_DESKTOP="gnome" gnome-control-center', '&']); - App.toggleWindow('sideright'); - }, - child: MaterialIcon('settings', 'norm'), - setup: button => { - setupCursorHover(button); - } -}) - -export const ModulePowerIcon = (props = {}) => Widget.Button({ - ...props, - className: 'txt-small sidebar-iconbutton', - tooltipText: 'Session', - onClicked: () => { - App.toggleWindow('session'); - }, - child: MaterialIcon('power_settings_new', 'norm'), - setup: button => { - setupCursorHover(button); - } -}) - - - diff --git a/home/desktops/hyprland/ags/modules/rightspace.js b/home/desktops/hyprland/ags/modules/rightspace.js deleted file mode 100644 index 2ecc867..0000000 --- a/home/desktops/hyprland/ags/modules/rightspace.js +++ /dev/null @@ -1,44 +0,0 @@ -import { App, Service, Utils, Widget } from '../imports.js'; -import Audio from 'resource:///com/github/Aylur/ags/service/audio.js'; -import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js'; -const { exec, execAsync, CONFIG_DIR } = Utils; -import Indicator from '../scripts/indicator.js'; -import { StatusIcons } from "./statusicons.js"; -import { RoundedCorner } from "./lib/roundedcorner.js"; -import { Tray } from "./tray.js"; - -export const ModuleRightSpace = () => Widget.EventBox({ - onScrollUp: () => { - if (Audio.speaker == null) return; - Audio.speaker.volume += 0.03; - Indicator.popup(1); - }, - onScrollDown: () => { - if (Audio.speaker == null) return; - Audio.speaker.volume -= 0.03; - Indicator.popup(1); - }, - onPrimaryClick: () => App.toggleWindow('sideright'), - onSecondaryClick: () => Mpris.getPlayer('')?.next(), - onMiddleClick: () => Mpris.getPlayer('')?.playPause(), - child: Widget.Box({ - homogeneous: false, - children: [ - Widget.Box({ - hexpand: true, - className: 'spacing-h-5 txt', - children: [ - Widget.Box({ - hexpand: true, - className: 'spacing-h-15 txt', - setup: box => { - box.pack_end(StatusIcons(), false, false, 0); - box.pack_end(Tray(), false, false, 0); - } - }), - ] - }), - RoundedCorner('topright', { className: 'corner-black' }) - ] - }) -}); diff --git a/home/desktops/hyprland/ags/modules/sessionscreen.js b/home/desktops/hyprland/ags/modules/sessionscreen.js deleted file mode 100644 index f99d651..0000000 --- a/home/desktops/hyprland/ags/modules/sessionscreen.js +++ /dev/null @@ -1,144 +0,0 @@ -// This is for the cool memory indicator on the sidebar -// For the right pill of the bar, see system.js -const { Gdk, Gtk } = imports.gi; -const GObject = imports.gi.GObject; -const Lang = imports.lang; -import { App, Service, Utils, Widget } from '../imports.js'; -const { exec, execAsync } = Utils; - -const SessionButton = (name, icon, command, props = {}) => { - const buttonDescription = Widget.Revealer({ - valign: 'end', - transitionDuration: 200, - transition: 'slide_down', - revealChild: false, - child: Widget.Label({ - className: 'txt-smaller session-button-desc', - label: name, - }), - }); - return Widget.Button({ - onClicked: command, - className: 'session-button', - child: Widget.Overlay({ - className: 'session-button-box', - child: Widget.Label({ - vexpand: true, - className: 'icon-material', - label: icon, - }), - overlays: [ - buttonDescription, - ] - }), - onHover: (button) => { - const display = Gdk.Display.get_default(); - const cursor = Gdk.Cursor.new_from_name(display, 'pointer'); - button.get_window().set_cursor(cursor); - buttonDescription.revealChild = true; - }, - onHoverLost: (button) => { - const display = Gdk.Display.get_default(); - const cursor = Gdk.Cursor.new_from_name(display, 'default'); - button.get_window().set_cursor(cursor); - buttonDescription.revealChild = false; - }, - connections: [ - ['focus-in-event', (self) => { - buttonDescription.revealChild = true; - self.toggleClassName('session-button-focused', true); - }], - ['focus-out-event', (self) => { - buttonDescription.revealChild = false; - self.toggleClassName('session-button-focused', false); - }], - ], - ...props, - }); -} - -export default () => { - // lock, logout, sleep - const lockButton = SessionButton('Lock', 'lock', () => { App.closeWindow('session'); execAsync('gtklock') }); - const logoutButton = SessionButton('Logout', 'logout', () => { App.closeWindow('session'); execAsync(['bash', '-c', 'loginctl terminate-user $USER']) }); - const sleepButton = SessionButton('Sleep', 'sleep', () => { App.closeWindow('session'); execAsync('systemctl suspend') }); - // hibernate, shutdown, reboot - const hibernateButton = SessionButton('Hibernate', 'downloading', () => { App.closeWindow('session'); execAsync('systemctl hibernate') }); - const shutdownButton = SessionButton('Shutdown', 'power_settings_new', () => { App.closeWindow('session'); execAsync('systemctl poweroff') }); - const rebootButton = SessionButton('Reboot', 'restart_alt', () => { App.closeWindow('session'); execAsync('systemctl reboot') }); - const cancelButton = SessionButton('Cancel', 'close', () => App.closeWindow('session'), { className: 'session-button-cancel' }); - return Widget.Box({ - className: 'session-bg', - style: ` - min-width: ${SCREEN_WIDTH * 2}px; - min-height: ${SCREEN_HEIGHT * 2}px; - `, // Hack to draw over reserved bar space - vertical: true, - children: [ - Widget.EventBox({ - onPrimaryClick: () => App.closeWindow('session'), - onSecondaryClick: () => App.closeWindow('session'), - onMiddleClick: () => App.closeWindow('session'), - }), - Widget.Box({ - halign: 'center', - vexpand: true, - vertical: true, - children: [ - Widget.Box({ - valign: 'center', - vertical: true, - className: 'spacing-v-15', - children: [ - Widget.Box({ - vertical: true, - style: 'margin-bottom: 0.682rem;', - children: [ - Widget.Label({ - className: 'txt-title txt', - label: 'Session', - }), - Widget.Label({ - justify: Gtk.Justification.CENTER, - className: 'txt-small txt', - label: 'Use arrow keys to navigate.\nEnter to select, Esc to cancel.' - }), - ] - }), - Widget.Box({ - halign: 'center', - className: 'spacing-h-15', - children: [ // lock, logout, sleep - lockButton, - logoutButton, - sleepButton, - ] - }), - Widget.Box({ - halign: 'center', - className: 'spacing-h-15', - children: [ // hibernate, shutdown, reboot - hibernateButton, - shutdownButton, - rebootButton, - ] - }), - Widget.Box({ - halign: 'center', - className: 'spacing-h-15', - children: [ // hibernate, shutdown, reboot - cancelButton, - ] - }), - ] - }) - ] - }) - ], - connections: [ - [App, (_b, name, visible) => { - if (visible) lockButton.grab_focus(); // Lock is the default option - }], - ], - }); -} diff --git a/home/desktops/hyprland/ags/modules/sideleft.js b/home/desktops/hyprland/ags/modules/sideleft.js deleted file mode 100644 index 7fb347c..0000000 --- a/home/desktops/hyprland/ags/modules/sideleft.js +++ /dev/null @@ -1,75 +0,0 @@ -const { Gdk, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../imports.js'; -import Applications from 'resource:///com/github/Aylur/ags/service/applications.js'; -import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; -const { execAsync, exec } = Utils; -const { Box, EventBox, Button, Label, Scrollable } = Widget; - -const CLIPBOARD_SHOWN_ENTRIES = 20; - -const ClipboardItems = () => { - return Box({ - vertical: true, - className: 'spacing-v-5', - connections: [ - [App, (box, name, visible) => { - if (name != 'sideleft') - return; - - let clipboardContents = exec('cliphist list'); // Output is lines like this: 1000 copied text - clipboardContents = clipboardContents.split('\n'); - - // console.log(clipboardContents); - // console.log(`bash -c 'echo "${clipboardContents[0]}" | sed "s/ /\\t/" | cliphist decode'`); - // console.log(exec(`bash -c 'echo "${clipboardContents[0]}" | sed "s/ /\\t/" | cliphist decode'`)); - - box.children = clipboardContents.map((text, i) => { - if (i >= CLIPBOARD_SHOWN_ENTRIES) return; - return Button({ - onClicked: () => { - print(`bash` + `-c` + `echo "${clipboardContents[i]}" | sed "s/ /\\\t/" | cliphist decode | wl-copy`); - execAsync(`bash`, `-c`, `echo "${clipboardContents[i]}" | sed "s/ /\\\t/" | cliphist decode | wl-copy`).catch(print); - App.closeWindow('sideleft'); - }, - className: 'sidebar-clipboard-item', - child: Box({ - children: [ - Label({ - label: text, - className: 'txt-small', - truncate: 'end', - }) - ] - }) - }) - }); - }] - ] - }); -} - -export default () => Box({ - vertical: true, - children: [ - EventBox({ - onPrimaryClick: () => App.closeWindow('sideleft'), - onSecondaryClick: () => App.closeWindow('sideleft'), - onMiddleClick: () => App.closeWindow('sideleft'), - }), - ClipboardItems(), - // Box({ - // vertical: true, - // vexpand: true, - // className: 'sidebar-left', - // children: [ - // Widget.Box({ - // className: 'spacing-v-5', - // children: [ - // ClipboardItems(), - // ] - // }) - // ], - // }), - ] -}); - diff --git a/home/desktops/hyprland/ags/modules/sideright.js b/home/desktops/hyprland/ags/modules/sideright.js deleted file mode 100644 index d900578..0000000 --- a/home/desktops/hyprland/ags/modules/sideright.js +++ /dev/null @@ -1,109 +0,0 @@ -const { Gdk, Gtk } = imports.gi; -import { Utils, Widget } from '../imports.js'; -const { execAsync, exec } = Utils; -const { Box, EventBox } = Widget; -import { - ToggleIconBluetooth, ToggleIconWifi, HyprToggleIcon, ModuleNightLight, - ModuleEditIcon, ModuleReloadIcon, ModuleSettingsIcon, ModulePowerIcon -} from "./quicktoggles.js"; -import ModuleNotificationList from "./notificationlist.js"; -import { ModuleMusicControls } from "./musiccontrols.js"; -import { ModuleCalendar } from "./calendar.js"; - -const NUM_OF_TOGGLES_PER_LINE = 5; - -const togglesFlowBox = Widget({ - type: Gtk.FlowBox, - className: 'sidebar-group spacing-h-10', - setup: (self) => { - self.set_max_children_per_line(NUM_OF_TOGGLES_PER_LINE); - self.add(ToggleIconWifi({ hexpand: 'true' })); - self.add(ToggleIconBluetooth({ hexpand: 'true' })); - self.add(HyprToggleIcon('mouse', 'Raw input', 'input:force_no_accel', { hexpand: 'true' })); - self.add(HyprToggleIcon('front_hand', 'No touchpad while typing', 'input:touchpad:disable_while_typing', { hexpand: 'true' })); - self.add(ModuleNightLight({ hexpand: 'true' })); - // Setup flowbox rearrange - self.connect('child-activated', (self, child) => { - if (child.get_index() === 0) { - self.reorder_child(child, self.get_children().length - 1); - } else { - self.reorder_child(child, 0); - } - }); - } -}) - -const togglesBox = Widget.Box({ - className: 'sidebar-group spacing-h-10', - children: [ - ToggleIconWifi({ hexpand: 'true' }), - ToggleIconBluetooth({ hexpand: 'true' }), - HyprToggleIcon('mouse', 'Raw input', 'input:force_no_accel', { hexpand: 'true' }), - HyprToggleIcon('front_hand', 'No touchpad while typing', 'input:touchpad:disable_while_typing', { hexpand: 'true' }), - ModuleNightLight({ hexpand: 'true' }), - ] -}) - -export default () => Box({ - // vertical: true, - vexpand: true, - hexpand: true, - children: [ - EventBox({ - onPrimaryClick: () => App.closeWindow('sideright'), - onSecondaryClick: () => App.closeWindow('sideright'), - onMiddleClick: () => App.closeWindow('sideright'), - }), - Box({ - vertical: true, - vexpand: true, - className: 'sidebar-right', - children: [ - Box({ - vertical: true, - vexpand: true, - className: 'spacing-v-15', - children: [ - Box({ - vertical: true, - className: 'spacing-v-5', - children: [ - Box({ // Header - className: 'spacing-h-5 sidebar-group-invisible-morehorizpad', - children: [ - Widget.Label({ - className: 'txt-title txt', - connections: [[5000, label => { - execAsync([`date`, "+%H:%M"]).then(timeString => { - label.label = timeString; - }).catch(print); - }]], - }), - Widget.Label({ - halign: 'center', - className: 'txt-small txt', - connections: [[5000, label => { - execAsync(['bash', '-c', `uptime -p | sed -e 's/up //;s/ hours,/h/;s/ minutes/m/'`]).then(upTimeString => { - label.label = `• uptime ${upTimeString}`; - }).catch(print); - }]], - }), - Widget.Box({ hexpand: true }), - // ModuleEditIcon({ halign: 'end' }), // TODO: Make this work - ModuleReloadIcon({ halign: 'end' }), - ModuleSettingsIcon({ halign: 'end' }), - ModulePowerIcon({ halign: 'end' }), - ] - }), - // togglesFlowBox, - togglesBox, - ] - }), - ModuleNotificationList({ vexpand: true, }), - ModuleCalendar(), - ] - }), - ], - }), - ] -}); diff --git a/home/desktops/hyprland/ags/modules/statusicons.js b/home/desktops/hyprland/ags/modules/statusicons.js deleted file mode 100644 index 0d642de..0000000 --- a/home/desktops/hyprland/ags/modules/statusicons.js +++ /dev/null @@ -1,93 +0,0 @@ -import { Service, Utils, Widget } from '../imports.js'; -const { exec, execAsync } = Utils; -import Audio from 'resource:///com/github/Aylur/ags/service/audio.js'; -import Battery from 'resource:///com/github/Aylur/ags/service/battery.js'; -import Bluetooth from 'resource:///com/github/Aylur/ags/service/bluetooth.js'; -import Network from 'resource:///com/github/Aylur/ags/service/network.js'; - -export const BluetoothIndicator = () => Widget.Stack({ - transition: 'slide_up_down', - items: [ - ['true', Widget.Label({ className: 'txt-norm icon-material', label: 'bluetooth' })], - ['false', Widget.Label({ className: 'txt-norm icon-material', label: 'bluetooth_disabled' })], - ], - connections: [[Bluetooth, stack => { stack.shown = String(Bluetooth.enabled); }]], -}); - - -const NetworkWiredIndicator = () => Widget.Stack({ - transition: 'slide_up_down', - items: [ - ['unknown', Widget.Label({ className: 'txt-norm icon-material', label: 'wifi_off' })], - ['disconnected', Widget.Label({ className: 'txt-norm icon-material', label: 'signal_wifi_off' })], - ['disabled', Widget.Label({ className: 'txt-norm icon-material', label: 'signal_wifi_statusbar_not_connected' })], - ['connected', Widget.Label({ className: 'txt-norm icon-material', label: 'lan' })], - ['connecting', Widget.Label({ className: 'txt-norm icon-material', label: 'signal_wifi_0_bar' })], - ], - connections: [[Network, stack => { - if (!Network.wired) - return; - - const { internet } = Network.wired; - if (internet === 'connected' || internet === 'connecting') - stack.shown = internet; - - if (Network.connectivity !== 'full') - stack.shown = 'disconnected'; - - stack.shown = 'disabled'; - }]], -}); - -const NetworkWifiIndicator = () => Widget.Stack({ - transition: 'slide_up_down', - items: [ - ['disabled', Widget.Label({ className: 'txt-norm icon-material', label: 'wifi_off' })], - ['disconnected', Widget.Label({ className: 'txt-norm icon-material', label: 'signal_wifi_off' })], - ['connecting', Widget.Label({ className: 'txt-norm icon-material', label: 'signal_wifi_statusbar_not_connected' })], - ['4', Widget.Label({ className: 'txt-norm icon-material', label: 'signal_wifi_4_bar' })], - ['3', Widget.Label({ className: 'txt-norm icon-material', label: 'network_wifi_3_bar' })], - ['2', Widget.Label({ className: 'txt-norm icon-material', label: 'network_wifi_2_bar' })], - ['1', Widget.Label({ className: 'txt-norm icon-material', label: 'network_wifi_1_bar' })], - ['0', Widget.Label({ className: 'txt-norm icon-material', label: 'signal_wifi_0_bar' })], - ], - connections: [[Network, - stack => { - if (!Network.wifi) - return; - const { internet, enabled, strength } = Network.wifi; - - if (internet == 'connected') { - stack.shown = String(Math.ceil(strength / 25)); - } - else { - stack.shown = 'disconnected' - } - } - ]], -}); - -export const NetworkIndicator = () => Widget.Stack({ - transition: 'slide_up_down', - items: [ - ['wifi', NetworkWifiIndicator()], - ['wired', NetworkWiredIndicator()], - ], - connections: [[Network, stack => { - const primary = Network.primary || 'wired'; - stack.shown = primary; - }]], -}); - -export const StatusIcons = (props = {}) => Widget.Box({ - ...props, - children: [Widget.EventBox({ - child: Widget.Box({ - className: 'spacing-h-15', - children: [ - BluetoothIndicator(), - NetworkIndicator(), - ] - }) - })] -}); diff --git a/home/desktops/hyprland/ags/modules/sysinfo.js b/home/desktops/hyprland/ags/modules/sysinfo.js deleted file mode 100644 index d5cc797..0000000 --- a/home/desktops/hyprland/ags/modules/sysinfo.js +++ /dev/null @@ -1,108 +0,0 @@ -// This is for the cool memory indicator on the sidebar -// For the right pill of the bar, see system.js -const { Gdk, Gtk } = imports.gi; -const GObject = imports.gi.GObject; -const Lang = imports.lang; -import { App, Service, Utils, Widget } from '../imports.js'; -import Bluetooth from 'resource:///com/github/Aylur/ags/service/bluetooth.js'; -import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; -import Network from 'resource:///com/github/Aylur/ags/service/network.js'; -const { execAsync, exec } = Utils; -import { CircularProgress } from "./lib/circularprogress.js"; -import { MaterialIcon } from "./lib/materialicon.js"; - -let cpuUsageQueue = []; -const CPU_HISTORY_LENGTH = 10; - -export const ModuleSysInfo = (props = {}) => { - const swapCircle = Widget({ - type: CircularProgress, - className: 'sidebar-memory-swap-circprog', - valign: 'center', - }); - const ramCircle = Widget({ - type: CircularProgress, - className: 'sidebar-memory-ram-circprog margin-right-10', // margin right 10 here cuz overlay can't have margins itself - valign: 'center', - }); - const cpuCircle = Widget.Box({ - children: [Widget({ - type: CircularProgress, - className: 'sidebar-cpu-circprog margin-right-10', // margin right 10 here cuz overlay can't have margins itself - valign: 'center', - })] - }); - const memoryCircles = Widget.Box({ - homogeneous: true, - children: [Widget.Overlay({ - child: ramCircle, - overlays: [ - swapCircle, - ] - })] - }); - const ramText = Widget.Label({ - halign: 'start', xalign: 0, - className: 'txt txt-small', - }); - const swapText = Widget.Label({ - halign: 'start', xalign: 0, - className: 'txt txt-small', - }); - const memoryText = Widget.Box({ - vertical: true, - valign: 'center', - className: 'spacing-v--5', - children: [ - Widget.Box({ - className: 'spacing-h-5', - children: [ - MaterialIcon('memory', 'large', { setup: icon => icon.toggleClassName('txt', true) }), - ramText - ] - }), - Widget.Box({ - className: 'spacing-h-5', - children: [ - MaterialIcon('swap_horiz', 'large', { setup: icon => icon.toggleClassName('txt', true) }), - swapText - ] - }), - ] - }); - return Widget.Box({ - ...props, - className: 'sidebar-group-nopad', - children: [Widget.Scrollable({ - hexpand: true, - vscroll: 'never', - hscroll: 'automatic', - child: Widget.Box({ - className: 'sidebar-sysinfo-grouppad spacing-h--5', - children: [ - memoryCircles, - memoryText, - // cpuCircle, - // maybe make cpu a graph? - ], - connections: [ - [3000, () => { - // Get memory info - const ramString = exec(`bash -c 'free -h --si | rg "Mem:"'`); - const [ramTotal, ramUsed] = ramString.split(/\s+/).slice(1, 3); - const ramPerc = Number(exec(`bash -c "printf '%.1f' \\\"$(free -m | rg Mem | awk '{print ($3/$2)*100}')\\\""`)); - const swapString = exec(`bash -c 'free -h --si | rg "Swap:"'`); - const [swapTotal, swapUsed] = swapString.split(/\s+/).slice(1, 3); - const swapPerc = Number(exec(`bash -c "printf '%.1f' \\\"$(free -m | rg Swap | awk '{print ($3/$2)*100}')\\\""`)); - // const cpuPerc = parseFloat(exec(`bash -c "top -bn1 | grep 'Cpu(s)' | awk '{print $2 + $4}'"`)); - // Set circular progress (font size cuz hack for anims) - ramCircle.style = `font-size: ${ramPerc}px;` - swapCircle.style = `font-size: ${swapPerc}px;` - ramText.label = `${ramUsed} / ${ramTotal}`; - swapText.label = `${swapUsed} / ${swapTotal}`; - }] - ] - }) - })] - }); -}; diff --git a/home/desktops/hyprland/ags/modules/system.js b/home/desktops/hyprland/ags/modules/system.js deleted file mode 100644 index 8ca7dd4..0000000 --- a/home/desktops/hyprland/ags/modules/system.js +++ /dev/null @@ -1,89 +0,0 @@ -// This is for the right pill of the bar. -// For the cool memory indicator on the sidebar, see sysinfo.js -import { Service, Utils, Widget } from '../imports.js'; -const { exec, execAsync } = Utils; -import Battery from 'resource:///com/github/Aylur/ags/service/battery.js'; - -export const ModuleSystem = () => Widget.EventBox({ - onScrollUp: () => execAsync('hyprctl dispatch workspace -1'), - onScrollDown: () => execAsync('hyprctl dispatch workspace +1'), - child: Widget.Box({ - className: 'bar-group-margin bar-sides', - children: [ - Widget.Box({ - className: 'bar-group bar-group-standalone bar-group-pad-system spacing-h-15', - children: [ - Widget.Box({ // Clock - valign: 'center', - className: 'spacing-h-5', - children: [ - Widget.Label({ - className: 'bar-clock', - connections: [[5000, label => { - execAsync([`date`, "+%H:%M"]).then(timeString => { - label.label = timeString; - }).catch(print); - }]], - }), - Widget.Label({ - className: 'txt-norm txt', - label: '•', - }), - Widget.Label({ - className: 'txt-smallie txt', - connections: [[5000, label => { - execAsync([`date`, "+%A, %d/%m"]).then(dateString => { - label.label = dateString; - }).catch(print); - }]], - }), - ], - }), - /*Widget.Box({ // Battery - valign: 'center', - hexpand: true, - className: 'spacing-h-5 bar-batt', - connections: [[Battery, box => { - box.toggleClassName('bar-batt-low', Battery.percent <= 20); - box.toggleClassName('bar-batt-full', Battery.charged); - }]], - children: [ - Widget.Label({ - className: 'bar-batt-percentage', - connections: [[Battery, label => { - label.label = `${Battery.percent}`; - }]], - }), - Widget.ProgressBar({ - valign: 'center', - hexpand: true, - className: 'bar-prog-batt', - connections: [[Battery, progress => { - progress.value = Math.abs(Battery.percent / 100); // battery could be initially negative wtf - progress.toggleClassName('bar-prog-batt-low', Battery.percent <= 20); - progress.toggleClassName('bar-prog-batt-full', Battery.charged); - }]], - }), - Widget.Revealer({ - transitionDuration: 150, - revealChild: false, - transition: 'slide_left', - child: Widget.Box({ - valign: 'center', - className: 'bar-batt-chargestate-charging', - connections: [[Battery, box => { - box.toggleClassName('bar-batt-chargestate-low', Battery.percent <= 20); - box.toggleClassName('bar-batt-chargestate-full', Battery.charged); - }]], - }), - connections: [[Battery, revealer => { - revealer.revealChild = Battery.charging; - }]], - }), - ], - }),]*/ - ], - }), - ] - }) -}); diff --git a/home/desktops/hyprland/ags/modules/tray.js b/home/desktops/hyprland/ags/modules/tray.js deleted file mode 100644 index 1871a59..0000000 --- a/home/desktops/hyprland/ags/modules/tray.js +++ /dev/null @@ -1,71 +0,0 @@ -import { Service, Widget } from '../imports.js'; -import SystemTray from 'resource:///com/github/Aylur/ags/service/systemtray.js'; -const { Box, Icon, Button, Revealer } = Widget; -const { Gravity } = imports.gi.Gdk; - -const revealerDuration = 200; - -const SysTrayItem = item => Button({ - className: 'bar-systray-item', - child: Icon({ - halign: 'center', - size: 16, - binds: [['icon', item, 'icon']] - }), - binds: [['tooltipMarkup', item, 'tooltipMarkup']], - // setup: btn => { - // const id = item.menu.connect('popped-up', menu => { - // menu.disconnect(id); - // }); - // }, - onClicked: btn => item.menu.popup_at_widget(btn, Gravity.SOUTH, Gravity.NORTH, null), - onSecondaryClick: btn => item.menu.popup_at_widget(btn, Gravity.SOUTH, Gravity.NORTH, null), -}); - -export const Tray = (props = {}) => { - const trayContent = Box({ - valign: 'center', - className: 'bar-systray bar-group', - properties: [ - ['items', new Map()], - ['onAdded', (box, id) => { - const item = SystemTray.getItem(id); - if (!item) return; - item.menu.className = 'menu'; - if (box._items.has(id) || !item) - return; - const widget = SysTrayItem(item); - box._items.set(id, widget); - box.pack_start(widget, false, false, 0); - box.show_all(); - if (box._items.size === 1) - trayRevealer.revealChild = true; - }], - ['onRemoved', (box, id) => { - if (!box._items.has(id)) - return; - - box._items.get(id).destroy(); - box._items.delete(id); - if (box._items.size === 0) - trayRevealer.revealChild = false; - }], - ], - connections: [ - [SystemTray, (box, id) => box._onAdded(box, id), 'added'], - [SystemTray, (box, id) => box._onRemoved(box, id), 'removed'], - ], - }); - const trayRevealer = Widget.Revealer({ - revealChild: false, - transition: 'slide_left', - transitionDuration: revealerDuration, - child: trayContent, - }); - return Box({ - ...props, - children: [ - trayRevealer, - ] - }); -} diff --git a/home/desktops/hyprland/ags/modules/workspaces.js b/home/desktops/hyprland/ags/modules/workspaces.js deleted file mode 100644 index 98977ed..0000000 --- a/home/desktops/hyprland/ags/modules/workspaces.js +++ /dev/null @@ -1,76 +0,0 @@ -import {App, Service, Utils, Widget} from '../imports.js'; -import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; -import {deflisten} from '../scripts/scripts.js'; - -const WORKSPACE_SIDE_PAD = 0.546; // rem -const NUM_OF_WORKSPACES = 9; -let lastWorkspace = 0; - -const activeWorkspaceIndicator = Widget.Box({ - valign: 'center', - halign: 'start', - className: 'bar-ws-active-box', - connections: [ - [Hyprland.active.workspace, (box) => { - const ws = Hyprland.active.workspace.id; - box.setStyle(` - margin-left: -${1.772 * (NUM_OF_WORKSPACES - ws + 1) + WORKSPACE_SIDE_PAD / 2 + 0.4}rem; - `); - lastWorkspace = ws; - }], - ], - children: [ - Widget.Label({ - valign: 'center', - className: 'bar-ws-active', - label: `•`, - }) - ] -}); - -export const ModuleWorkspaces = () => Widget.EventBox({ - onScrollUp: () => Utils.execAsync(['bash', '-c', 'hyprctl dispatch workspace -1 &']), - onScrollDown: () => Utils.execAsync(['bash', '-c', 'hyprctl dispatch workspace +1 &']), - onPrimaryClickRelease: () => App.toggleWindow('overview'), - onMiddleClickRelease: () => App.toggleWindow('osk'), - child: Widget.Box({ - homogeneous: true, - className: 'bar-group-center', - children: [ - Widget.Box({ - style: `padding: 0rem ${WORKSPACE_SIDE_PAD}rem;`, - children: [ - Widget.Box({ - halign: 'center', - children: Array.from({length: NUM_OF_WORKSPACES}, (_, i) => i + 1).map(i => Widget.Button({ - onSecondaryClick: () => Utils.execAsync(['bash', '-c', `hyprctl dispatch workspace ${i} &`]).catch(print), - child: Widget.Label({ - valign: 'center', - label: `${i}`, - className: 'bar-ws txt', - }), - })), - connections: [ - [Hyprland, (box) => { // TODO: connect to the right signal so that it doesn't update too much - const kids = box.children; - kids.forEach((child, i) => { - child.child.toggleClassName('bar-ws-occupied', false); - child.child.toggleClassName('bar-ws-occupied-left', false); - child.child.toggleClassName('bar-ws-occupied-right', false); - child.child.toggleClassName('bar-ws-occupied-left-right', false); - }); - const occupied = Array.from({length: NUM_OF_WORKSPACES}, (_, i) => Hyprland.getWorkspace(i + 1)?.windows > 0); - for (let i = 0; i < occupied.length; i++) { - if (!occupied[i]) continue; - const child = kids[i]; - child.child.toggleClassName(`bar-ws-occupied${!occupied[i - 1] ? '-left' : ''}${!occupied[i + 1] ? '-right' : ''}`, true); - } - }], - ], - }), - activeWorkspaceIndicator, - ] - }) - ] - }) -}); diff --git a/home/desktops/hyprland/ags/package.json b/home/desktops/hyprland/ags/package.json new file mode 100644 index 0000000..6f6c8a9 --- /dev/null +++ b/home/desktops/hyprland/ags/package.json @@ -0,0 +1,31 @@ +{ + "name": "ags-dotfiles", + "version": "1.6.3", + "description": "My config files for AGS", + "main": "config.js", + "scripts": { + "lint": "eslint . --fix", + "stylelint": "stylelint ./scss --fix" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Aylur/dotfiles.git" + }, + "author": "Aylur", + "bugs": { + "url": "https://github.com/Aylur/dotfiles/issues" + }, + "homepage": "https://github.com/Aylur/dotfiles#readme", + "kofi": "https://ko-fi.com/aylur", + "devDependencies": { + "@girs/dbusmenugtk3-0.4": "^0.4.0-3.2.0", + "@girs/gobject-2.0": "^2.76.1-3.2.3", + "@girs/gtk-3.0": "^3.24.39-3.2.2", + "@girs/gvc-1.0": "^1.0.0-3.1.0", + "@girs/nm-1.0": "^1.43.1-3.1.0", + "stylelint-config-standard-scss": "^10.0.0", + "@typescript-eslint/eslint-plugin": "^5.33.0", + "@typescript-eslint/parser": "^5.33.0", + "eslint": "^8.44.0" + } +} diff --git a/home/desktops/hyprland/ags/scripts/README.md b/home/desktops/hyprland/ags/scripts/README.md deleted file mode 100755 index 1292e1c..0000000 --- a/home/desktops/hyprland/ags/scripts/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# scripts folder -- For ARM devices, you have to compile C++ files yourself. \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scripts/brightness.js b/home/desktops/hyprland/ags/scripts/brightness.js deleted file mode 100644 index b86558c..0000000 --- a/home/desktops/hyprland/ags/scripts/brightness.js +++ /dev/null @@ -1,58 +0,0 @@ -import { Service, Utils } from '../imports.js'; -const { exec, execAsync } = Utils; - -const clamp = (num, min, max) => Math.min(Math.max(num, min), max); - -class BrightnessService extends Service { - static { - Service.register( - this, - { 'screen-changed': ['float'], }, - { 'screen-value': ['float', 'rw'], }, - ); - } - - _screenValue = 0; - - // the getter has to be in snake_case - get screen_value() { return this._screenValue; } - - // the setter has to be in snake_case too - set screen_value(percent) { - percent = clamp(percent, 0, 1); - this._screenValue = percent; - - Utils.execAsync(`brightnessctl s ${percent * 100}% -q`) - .then(() => { - // signals has to be explicity emitted - this.emit('screen-changed', percent); - this.notify('screen-value'); - - // or use Service.changed(propName: string) which does the above two - // this.changed('screen'); - }) - .catch(print); - } - - constructor() { - super(); - const current = Number(exec('brightnessctl g')); - const max = Number(exec('brightnessctl m')); - this._screenValue = current / max; - } - - // overwriting connectWidget method, let's you - // change the default event that widgets connect to - connectWidget(widget, callback, event = 'screen-changed') { - super.connectWidget(widget, callback, event); - } -} - -// the singleton instance -const service = new BrightnessService(); - -// make it global for easy use with cli -globalThis.brightness = service; - -// export to use in other modules -export default service; \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scripts/calendarlayout.js b/home/desktops/hyprland/ags/scripts/calendarlayout.js deleted file mode 100644 index 691ee5e..0000000 --- a/home/desktops/hyprland/ags/scripts/calendarlayout.js +++ /dev/null @@ -1,101 +0,0 @@ -export function getCalendarLayout(d, highlight) { - if (!d) d = new Date(); - var calendar = [...Array(6)].map(() => Array(7)); - var today = [...Array(6)].map(() => Array(7)); - const year = d.getFullYear(); - const month = d.getMonth() + 1; - const day = d.getDate(); - const weekdayOfMonthFirst = new Date(`${year}-${month}-01`).getDay(); - const leapYear = (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)); - const daysInMonth = (((month <= 7 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) ? 31 : ((month == 2 && leapYear) ? 29 : ((month == 2 && !leapYear) ? 28 : 30))); - const daysInNextMonth = ((month == 1 && leapYear) ? 29 : ((month == 1 && !leapYear) ? 28 : ((month == 7 || month == 12) ? 31 : (((month <= 6 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) ? 30 : 31)))); - const daysInLastMonth = ((month == 3 && leapYear) ? 29 : ((month == 3 && !leapYear) ? 28 : ((month == 1 || month == 8) ? 31 : ((month <= 7 && month % 2 == 1) || (month >= 9 && month % 2 == 0)) ? 30 : 31))); - var monthDiff = (weekdayOfMonthFirst == 0 ? 0 : -1); - var dim = daysInLastMonth; - var toFill = (weekdayOfMonthFirst == 0 ? 1 : (daysInLastMonth + 1 - weekdayOfMonthFirst)); - var i = 0, j = 0; - while (i < 6 && j < 7) { - calendar[i][j] = toFill; - if (toFill == day && monthDiff == 0 && highlight) today[i][j] = 1; - else if (monthDiff == 0) today[i][j] = 0; - else today[i][j] = -1; - toFill++; - if (toFill > dim) { - monthDiff++; - if (monthDiff == 0) dim = daysInMonth; - else if (monthDiff == 1) dim = daysInNextMonth; - toFill = 1; - } - j++; - if (j == 7) { - j = 0; - i++; - } - } - var cal = []; - for (var i = 0; i < 6; i++) { - var arr = []; - for (var j = 0; j < 7; j++) { - arr.push({ - day: calendar[i][j], - today: today[i][j] - }); - } - cal.push(arr); - } - - return cal; -} - -export default getCalendarLayout; - -// export function getCalendarLayout(d, highlight) { -// if (!d) d = new Date(); -// var calendar = [...Array(6)].map(() => Array(7)); -// var today = [...Array(6)].map(() => Array(7)); -// const year = d.getFullYear(); -// const month = d.getMonth() + 1; -// const day = d.getDate(); -// const weekdayOfMonthFirst = new Date(`${year}-${month}-01`).getDay(); -// const leapYear = (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)); -// const daysInMonth = (((month <= 7 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) ? 31 : ((month == 2 && leapYear) ? 29 : ((month == 2 && !leapYear) ? 28 : 30))); -// const daysInNextMonth = ((month == 1 && leapYear) ? 29 : ((month == 1 && !leapYear) ? 28 : ((month == 7 || month == 12) ? 31 : (((month <= 6 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) ? 30 : 31)))); -// const daysInLastMonth = ((month == 3 && leapYear) ? 29 : ((month == 3 && !leapYear) ? 28 : ((month == 1 || month == 8) ? 31 : ((month <= 7 && month % 2 == 1) || (month >= 9 && month % 2 == 0)) ? 30 : 31))); -// var monthDiff = (weekdayOfMonthFirst == 1 ? 0 : -1); -// var dim = daysInLastMonth; -// var toFill = (weekdayOfMonthFirst == 1 ? 1 : (weekdayOfMonthFirst == 0 ? (daysInLastMonth - 5) : (daysInLastMonth + 2 - weekdayOfMonthFirst))); -// var i = 0, j = 0; -// while (i < 6 && j < 7) { -// calendar[i][j] = toFill; -// if (toFill == day && monthDiff == 0 && highlight) today[i][j] = 1; -// else if (monthDiff == 0) today[i][j] = 0; -// else today[i][j] = -1; -// toFill++; -// if (toFill > dim) { -// monthDiff++; -// if (monthDiff == 0) dim = daysInMonth; -// else if (monthDiff == 1) dim = daysInNextMonth; -// toFill = 1; -// } -// j++; -// if (j == 7) { -// j = 0; -// i++; -// } -// } -// var cal = []; -// for (var i = 0; i < 6; i++) { -// var arr = []; -// for (var j = 0; j < 7; j++) { -// arr.push({ -// day: calendar[i][j], -// today: today[i][j] -// }); -// } -// cal.push(arr); -// } - -// return cal; -// } - -// export default getCalendarLayout; \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scripts/color_generation/applycolor.sh b/home/desktops/hyprland/ags/scripts/color_generation/applycolor.sh deleted file mode 100755 index 4e301f3..0000000 --- a/home/desktops/hyprland/ags/scripts/color_generation/applycolor.sh +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/env bash - -cd "$HOME/.config/ags" || exit - -# filelist=$(ls 'images/svg/template/' | grep -v /) - -# cat scss/_material.scss -colornames=$(cat scss/_material.scss | cut -d: -f1) -colorstrings=$(cat scss/_material.scss | cut -d: -f2 | cut -d ' ' -f2 | cut -d ";" -f1) -IFS=$'\n' -# filearr=( $filelist ) # Get colors -colorlist=( $colornames ) # Array of color names -colorvalues=( $colorstrings ) # Array of color values - -transparentize() { - local hex="$1" - local alpha="$2" - local red green blue - - red=$((16#${hex:1:2})) - green=$((16#${hex:3:2})) - blue=$((16#${hex:5:2})) - - printf 'rgba(%d, %d, %d, %.2f)\n' "$red" "$green" "$blue" "$alpha" -} - -get_light_dark() { - lightdark="" - if [ ! -f ~/.cache/ags/user/colormode.txt ]; then - echo "" > ~/.cache/ags/user/colormode.txt - else - lightdark=$(cat ~/.cache/ags/user/colormode.txt) # either "" or "-l" - fi - echo "$lightdark" -} - -# apply_svgs() { -# for i in "${!filearr[@]}"; do # Loop through folders -# colorvalue=$(echo "$colorscss" | grep "${filearr[$i]}" | awk '{print $2}' | cut -d ";" -f1) -# for file in images/svg/template/"${filearr[$i]}"/*; do # Loop through files -# cp "$file" images/svg/ -# sed -i "s/black/$colorvalue/g" images/svg/"${file##*/}" -# done -# done -# } - -apply_gtklock() { - # Check if scripts/templates/gtklock/main.scss exists - if [ ! -f "scripts/templates/gtklock/main.scss" ]; then - echo "SCSS not found. Fallback to CSS." - else - sassc ~/.config/ags/scripts/templates/gtklock/main.scss ~/.config/gtklock/style.css - return - fi - - # Check if scripts/templates/gtklock/style.css exists - if [ ! -f "scripts/templates/gtklock/style.css" ]; then - echo "Template file not found for Gtklock. Skipping that." - return - fi - # Copy template - cp "scripts/templates/gtklock/style.css" "$HOME/.config/gtklock/style.css" - # Apply colors - for i in "${!colorlist[@]}"; do - sed -i "s/${colorlist[$i]};/${colorvalues[$i]};/g" "$HOME/.config/gtklock/style.css" - done -} - -apply_fuzzel() { - # Check if scripts/templates/fuzzel/fuzzel.ini exists - if [ ! -f "scripts/templates/fuzzel/fuzzel.ini" ]; then - echo "Template file not found for Fuzzel. Skipping that." - return - fi - # Copy template - cp "scripts/templates/fuzzel/fuzzel.ini" "$HOME/.config/fuzzel/fuzzel.ini" - # Apply colors - for i in "${!colorlist[@]}"; do - sed -i "s/${colorlist[$i]}ff/${colorvalues[$i]#\#}ff/g" "$HOME/.config/fuzzel/fuzzel.ini" - sed -i "s/${colorlist[$i]}cc/${colorvalues[$i]#\#}cc/g" "$HOME/.config/fuzzel/fuzzel.ini" - done -} - -apply_foot() { - # Check if scripts/templates/foot/foot.ini exists - if [ ! -f "scripts/templates/foot/foot.ini" ]; then - echo "Template file not found for Foot. Skipping that." - return - fi - # Copy template - cp "scripts/templates/foot/foot.ini" "$HOME/.config/foot/foot.ini" - # Apply colors - for i in "${!colorlist[@]}"; do - sed -i "s/${colorlist[$i]} #/${colorvalues[$i]#\#}/g" "$HOME/.config/foot/foot.ini" # note: ff because theyre opaque - done -} - -apply_hyprland() { - # Check if scripts/templates/hypr/colors.conf exists - if [ ! -f "scripts/templates/hypr/colors.conf" ]; then - echo "Template file not found for Hyprland colors. Skipping that." - return - fi - # Copy template - cp "scripts/templates/hypr/colors.conf" "$HOME/.config/hypr/colors.conf" - # Apply colors - for i in "${!colorlist[@]}"; do - sed -i "s/(${colorlist[$i]}/(${colorvalues[$i]#\#}/g" "$HOME/.config/hypr/colors.conf" - done -} - -apply_gtk() { # Using gradience-cli - lightdark=$(get_light_dark) - - background=$(cat scss/_material.scss | grep "background" | awk '{print $2}' | cut -d ";" -f1) - secondaryContainer=$(cat scss/_material.scss | grep "secondaryContainer" | awk '{print $2}' | cut -d ";" -f1) - window_bg_color=$(transparentize "$background" 0.9) - card_bg_color=$(transparentize "$background" 0.2) - headerbar_border_color=$(transparentize "$secondaryContainer" 0.12) - - # Copy template - cp "scripts/templates/gradience/preset_template.json" "scripts/templates/gradience/preset.json" - - # Apply colors - for i in "${!colorlist[@]}"; do - sed -i "s/\"${colorlist[$i]}\"/\"${colorvalues[$i]}\"/g" "scripts/templates/gradience/preset.json" - done - sed -i "s|\"\$windowBgColor\"|\"$window_bg_color\"|g" "scripts/templates/gradience/preset.json" - sed -i "s|\"\$cardBgColor\"|\"$card_bg_color\"|g" "scripts/templates/gradience/preset.json" - sed -i "s|\"\$headerbarBorderColor\"|\"$headerbar_border_color\"|g" "scripts/templates/gradience/preset.json" - - gradience-cli apply -p scripts/templates/gradience/preset.json --gtk both - - # Set light/dark preference - # And set GTK theme manually as Gradience defaults to light adw-gtk3 - # (which is unreadable when broken when you use dark mode) - if [ "$lightdark" = "-l" ]; then - gsettings set org.gnome.desktop.interface color-scheme 'prefer-light' - gsettings set org.gnome.desktop.interface gtk-application-prefer-dark-theme false - gsettings set org.gnome.desktop.interface gtk-theme adw-gtk3 - else - gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark' - gsettings set org.gnome.desktop.interface gtk-application-prefer-dark-theme true - gsettings set org.gnome.desktop.interface gtk-theme adw-gtk3-dark - fi -} - -# apply_svgs -apply_gtklock -apply_fuzzel -apply_foot -apply_hyprland -apply_gtk diff --git a/home/desktops/hyprland/ags/scripts/color_generation/colorgen.sh b/home/desktops/hyprland/ags/scripts/color_generation/colorgen.sh deleted file mode 100755 index 4da2eb4..0000000 --- a/home/desktops/hyprland/ags/scripts/color_generation/colorgen.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/bash - -# check if no arguments -if [ $# -eq 0 ]; then - echo "Usage: colorgen.sh /path/to/image (--apply)" - exit 1 -fi - -# check if the file ~/.cache/ags/user/colormode.txt exists. if not, create it. else, read it to $lightdark -lightdark="" -if [ ! -f "$HOME/.cache/ags/user/colormode.txt" ]; then - echo "" > "$HOME/.cache/ags/user/colormode.txt" -else - lightdark=$(cat "$HOME/.cache/ags/user/colormode.txt") # either "" or "-l" -fi -# check if the file ~/.cache/ags/user/colorbackend.txt exists. if not, create it. else, read it to $lightdark -backend="material" -if [ ! -f "$HOME/.cache/ags/user/colorbackend.txt" ]; then - echo "material" > "$HOME/.cache/ags/user/colorbackend.txt" -else - backend=$(cat "$HOME/.cache/ags/user/colorbackend.txt") # either "" or "-l" -fi - -cd "$HOME/.config/ags/scripts/" || exit -if [ "$backend" = "material" ]; then - color_generation/generate_colors_material.py --path "$1" "$lightdark" > $HOME/.cache/ags/user/generated_colors.txt - if [ "$2" = "--apply" ]; then - cp $HOME/.cache/ags/user/generated_colors.txt "$HOME/.config/ags/scss/_material.scss" - color_generation/applycolor.sh - fi -elif [ "$backend" = "pywal" ]; then - # clear and generate - wal -c - echo wal -i "$1" -n -t -s -e "$lightdark" -q - wal -i "$1" -n -t -s -e $lightdark -q - # copy scss - cp "$HOME/.cache/wal/colors.scss" $HOME/.cache/ags/user/generated_colors.txt - - cat color_generation/pywal_to_material.scss >> $HOME/.cache/ags/user/generated_colors.txt - if [ "$2" = "--apply" ]; then - sassc $HOME/.cache/ags/user/generated_colors.txt $HOME/.cache/ags/user/generated_colors_classes.scss --style compact - sed -i "s/ { color//g" $HOME/.cache/ags/user/generated_colors_classes.scss - sed -i "s/\./$/g" $HOME/.cache/ags/user/generated_colors_classes.scss - sed -i "s/}//g" $HOME/.cache/ags/user/generated_colors_classes.scss - if [ "$lightdark" = "-l" ]; then - printf "\n"'$darkmode: false;'"\n" >> $HOME/.cache/ags/user/generated_colors_classes.scss - else - printf "\n"'$darkmode: true;'"\n" >> $HOME/.cache/ags/user/generated_colors_classes.scss - fi - - cp $HOME/.cache/ags/user/generated_colors_classes.scss "$HOME/.config/ags/scss/_material.scss" - - color_generation/applycolor.sh - fi -fi diff --git a/home/desktops/hyprland/ags/scripts/color_generation/generate_colors_material.py b/home/desktops/hyprland/ags/scripts/color_generation/generate_colors_material.py deleted file mode 100755 index d26ecf8..0000000 --- a/home/desktops/hyprland/ags/scripts/color_generation/generate_colors_material.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/python3 -from material_color_utilities_python import * -from pathlib import Path -import sys -import subprocess - -img = 0 -newtheme=0 -if len(sys.argv) > 1 and sys.argv[1] == '--path': - img = Image.open(sys.argv[2]) - basewidth = 64 - wpercent = (basewidth/float(img.size[0])) - hsize = int((float(img.size[1])*float(wpercent))) - img = img.resize((basewidth,hsize),Image.Resampling.LANCZOS) - newtheme = themeFromImage(img) -elif len(sys.argv) > 1 and sys.argv[1] == '--color': - colorstr = sys.argv[2] - newtheme = themeFromSourceColor(argbFromHex(colorstr)) -else: - imagePath = subprocess.check_output("swww query | awk -F 'image: ' '{print $2}'", shell=True) - imagePath = imagePath[:-1].decode("utf-8") - img = Image.open(imagePath) - basewidth = 64 - wpercent = (basewidth/float(img.size[0])) - hsize = int((float(img.size[1])*float(wpercent))) - img = img.resize((basewidth,hsize),Image.Resampling.LANCZOS) - newtheme = themeFromImage(img) - -colorscheme=0 -if("-l" in sys.argv): - colorscheme = newtheme.get('schemes').get('light') - print('$darkmode: false;') -else: - colorscheme = newtheme.get('schemes').get('dark') - print('$darkmode: true;') - -primary = colorscheme.get_primary() -onPrimary = colorscheme.get_onPrimary() -primaryContainer = colorscheme.get_primaryContainer() -onPrimaryContainer = colorscheme.get_onPrimaryContainer() -secondary = colorscheme.get_secondary() -onSecondary = colorscheme.get_onSecondary() -secondaryContainer = colorscheme.get_secondaryContainer() -onSecondaryContainer = colorscheme.get_onSecondaryContainer() -tertiary = colorscheme.get_tertiary() -onTertiary = colorscheme.get_onTertiary() -tertiaryContainer = colorscheme.get_tertiaryContainer() -onTertiaryContainer = colorscheme.get_onTertiaryContainer() -error = colorscheme.get_error() -onError = colorscheme.get_onError() -errorContainer = colorscheme.get_errorContainer() -onErrorContainer = colorscheme.get_onErrorContainer() -background = colorscheme.get_background() -onBackground = colorscheme.get_onBackground() -surface = colorscheme.get_surface() -onSurface = colorscheme.get_onSurface() -surfaceVariant = colorscheme.get_surfaceVariant() -onSurfaceVariant = colorscheme.get_onSurfaceVariant() -outline = colorscheme.get_outline() -shadow = colorscheme.get_shadow() -inverseSurface = colorscheme.get_inverseSurface() -inverseOnSurface = colorscheme.get_inverseOnSurface() -inversePrimary = colorscheme.get_inversePrimary() - - -print('$primary: ' + hexFromArgb(primary) + ';') -print('$onPrimary: ' + hexFromArgb(onPrimary) + ';') -print('$primaryContainer: ' + hexFromArgb(primaryContainer) + ';') -print('$onPrimaryContainer: ' + hexFromArgb(onPrimaryContainer) + ';') -print('$secondary: ' + hexFromArgb(secondary) + ';') -print('$onSecondary: ' + hexFromArgb(onSecondary) + ';') -print('$secondaryContainer: ' + hexFromArgb(secondaryContainer) + ';') -print('$onSecondaryContainer: ' + hexFromArgb(onSecondaryContainer) + ';') -print('$tertiary: ' + hexFromArgb(tertiary) + ';') -print('$onTertiary: ' + hexFromArgb(onTertiary) + ';') -print('$tertiaryContainer: ' + hexFromArgb(tertiaryContainer) + ';') -print('$onTertiaryContainer: ' + hexFromArgb(onTertiaryContainer) + ';') -print('$error: ' + hexFromArgb(error) + ';') -print('$onError: ' + hexFromArgb(onError) + ';') -print('$errorContainer: ' + hexFromArgb(errorContainer) + ';') -print('$onErrorContainer: ' + hexFromArgb(onErrorContainer) + ';') -print('$colorbarbg: ' + hexFromArgb(background) + ';') -print('$background: ' + hexFromArgb(background) + ';') -print('$onBackground: ' + hexFromArgb(onBackground) + ';') -print('$surface: ' + hexFromArgb(surface) + ';') -print('$onSurface: ' + hexFromArgb(onSurface) + ';') -print('$surfaceVariant: ' + hexFromArgb(surfaceVariant) + ';') -print('$onSurfaceVariant: ' + hexFromArgb(onSurfaceVariant) + ';') -print('$outline: ' + hexFromArgb(outline) + ';') -print('$shadow: ' + hexFromArgb(shadow) + ';') -print('$inverseSurface: ' + hexFromArgb(inverseSurface) + ';') -print('$inverseOnSurface: ' + hexFromArgb(inverseOnSurface) + ';') -print('$inversePrimary: ' + hexFromArgb(inversePrimary) + ';') \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scripts/color_generation/pywal_to_material.scss b/home/desktops/hyprland/ags/scripts/color_generation/pywal_to_material.scss deleted file mode 100755 index ff049b2..0000000 --- a/home/desktops/hyprland/ags/scripts/color_generation/pywal_to_material.scss +++ /dev/null @@ -1,57 +0,0 @@ -$primary: lighten($color4, 20%); -$onPrimary: darken($color2, 20%); -$primaryContainer: darken($color2, 10%); -$onPrimaryContainer: lighten($color4, 10%); -$secondary: desaturate(lighten($color5, 20%), 20%); -$onSecondary: desaturate(darken($color3, 20%), 20%); -$secondaryContainer: desaturate(darken($color3, 20%), 20%); -$onSecondaryContainer: desaturate(lighten($color5, 20%), 20%); -$tertiary: adjust-hue(lighten($color4, 20%), 30deg); -$onTertiary: adjust-hue(darken($color2, 20%), 30deg); -$tertiaryContainer: adjust-hue(darken($color2, 10%), 30deg); -$tertiaryContainer: adjust-hue(lighten($color4, 10%), 30deg); -$error: #ffb4a9; -$onError: #680003; -$errorContainer: #930006; -$onErrorContainer: #ffb4a9; -$colorbarbg: $color0; -$background: $color0; -$onBackground: $color7; -$surface: $color0; -$onSurface: $color7; -$surfaceVariant: $color1; -$onSurfaceVariant: $color7; -$outline: $color7; -$shadow: #000000; -$inverseSurface: invert($surface); -$inverseOnSurface: invert($onSurface); -$inversePrimary: invert($primary); - -.primary { color: $primary; } -.onPrimary { color: $onPrimary; } -.primaryContainer { color: $primaryContainer; } -.onPrimaryContainer { color: $onPrimaryContainer; } -.secondary { color: $secondary; } -.onSecondary { color: $onSecondary; } -.secondaryContainer { color: $secondaryContainer; } -.onSecondaryContainer { color: $onSecondaryContainer; } -.tertiary { color: $tertiary; } -.onTertiary { color: $onTertiary; } -.tertiaryContainer { color: $tertiaryContainer; } -.onTertiaryContainer { color: $tertiaryContainer; } -.error { color: $error; } -.onError { color: $onError; } -.errorContainer { color: $errorContainer; } -.onErrorContainer { color: $onErrorContainer; } -.colorbarbg { color: $colorbarbg; } -.background { color: $background; } -.onBackground { color: $onBackground; } -.surface { color: $surface; } -.onSurface { color: $onSurface; } -.surfaceVariant { color: $surfaceVariant; } -.onSurfaceVariant { color: $onSurfaceVariant; } -.outline { color: $outline; } -.shadow { color: $shadow; } -.inverseSurface { color: $inverseSurface; } -.inverseOnSurface { color: $inverseOnSurface; } -.inversePrimary { color: $inversePrimary; } diff --git a/home/desktops/hyprland/ags/scripts/color_generation/switchwall.sh b/home/desktops/hyprland/ags/scripts/color_generation/switchwall.sh deleted file mode 100755 index 4590974..0000000 --- a/home/desktops/hyprland/ags/scripts/color_generation/switchwall.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/bash -# Switches sww wallpaper -# Requires: coreutils, xrandr, hyprland - -# Select and set image (hyprland) -cd "$HOME/Pictures" -imgpath=$(yad --width 1200 --height 800 --file --title='Choose wallpaper') -screensizey=$(xrandr --current | grep '*' | uniq | awk '{print $1}' | cut -d 'x' -f2 | head -1) -cursorposx=$(hyprctl cursorpos -j | gojq '.x') -cursorposy=$(hyprctl cursorpos -j | gojq '.y') -cursorposy_inverted=$(( screensizey - cursorposy )) - -if [ "$imgpath" == '' ]; then - echo 'Aborted' - exit 0 -fi - -echo Sending "$imgpath" to swww. Cursor pos: ["$cursorposx, $cursorposy_inverted"] & -# Change swww wallpaper -swww img "$imgpath" --transition-step 100 --transition-fps 60 \ ---transition-type grow --transition-angle 30 --transition-duration 1 \ ---transition-pos "$cursorposx, $cursorposy_inverted" & - -# Generate colors for ags n stuff -"$HOME"/.config/ags/scripts/color_generation/colorgen.sh "${imgpath}" --apply -sassc "$HOME"/.config/ags/scss/main.scss "$HOME"/.config/ags/style.css -ags run-js "App.resetCss(); App.applyCss('${HOME}/.config/ags/style.css');" & diff --git a/home/desktops/hyprland/ags/scripts/dumptows b/home/desktops/hyprland/ags/scripts/dumptows deleted file mode 100755 index 273e968..0000000 Binary files a/home/desktops/hyprland/ags/scripts/dumptows and /dev/null differ diff --git a/home/desktops/hyprland/ags/scripts/dumptows.cpp b/home/desktops/hyprland/ags/scripts/dumptows.cpp deleted file mode 100755 index 6548af7..0000000 --- a/home/desktops/hyprland/ags/scripts/dumptows.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nlohmann/json.hpp" -using namespace std; -using json = nlohmann::json; - -int workspace_a, workspace_b; -string clients; -json clientjson; -vector windows_a, windows_b; -bool output = false; - -string exec(const char* cmd) { - array buffer; - string result; - unique_ptr pipe(popen(cmd, "r"), pclose); - if (!pipe) { - throw runtime_error("popen() failed!"); - } - while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { - result += buffer.data(); - } - return result; -} - -void tryAddApp(const json& client) { - if (int(client["workspace"]["id"]) == workspace_a) - windows_a.push_back(client["address"]); - else if (int(client["workspace"]["id"]) == workspace_b) - windows_b.push_back(client["address"]); -} - -void getApps() { - // Get clients - clients = exec("hyprctl clients -j | gojq -c -M"); - clientjson = json::parse(clients); - - // Access the values - for (json client : clientjson) { - tryAddApp(client); - } -} - -void dumptoWorkspace() { - for (string address : windows_a) { - string cmd = "hyprctl dispatch movetoworkspacesilent " + - to_string(workspace_b) + ",address:" + address; - if (output) cout << cmd << '\n'; - exec(&cmd[0]); - } -} - -int main(int argc, char* argv[]) { - ios::sync_with_stdio(false); - - if (argc < 3) { - cout << "Usage: dumptows [WORKSPACE_NUMBER_1] [WORKSPACE_NUMBER_2]" - << endl; - return 0; - } - if (argc == 4 && string(argv[3]) == "--output") output = true; - - workspace_a = stoi(string(argv[1])); - workspace_b = stoi(string(argv[2])); - if (workspace_a <= 0 || workspace_b <= 0 || workspace_a == workspace_b) { - cout << "Nahhh that's stupid" << endl; - return 0; - } - - getApps(); - dumptoWorkspace(); -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scripts/indicator.js b/home/desktops/hyprland/ags/scripts/indicator.js deleted file mode 100644 index fcb8948..0000000 --- a/home/desktops/hyprland/ags/scripts/indicator.js +++ /dev/null @@ -1,40 +0,0 @@ -import { Service, Utils } from '../imports.js'; -const { exec, execAsync } = Utils; - -const clamp = (num, min, max) => Math.min(Math.max(num, min), max); - -class IndicatorService extends Service { - static { - Service.register( - this, - { 'popup': ['double'], }, - ); - } - - _delay = 1500; - _count = 0; - - popup(value) { - this.emit('popup', value); - this._count++; - Utils.timeout(this._delay, () => { - this._count--; - - if (this._count === 0) - this.emit('popup', -1); - }); - } - - connectWidget(widget, callback) { - connect(this, widget, callback, 'popup'); - } -} - -// the singleton instance -const service = new IndicatorService(); - -// make it global for easy use with cli -globalThis['indicator'] = service; - -// export to use in other modules -export default service; \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scripts/record-script.sh b/home/desktops/hyprland/ags/scripts/record-script.sh deleted file mode 100755 index 57f4508..0000000 --- a/home/desktops/hyprland/ags/scripts/record-script.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/bash - -cd ~/Videos || exit -if [[ "$(pidof wf-recorder)" == "" ]]; then - notify-send "Starting recording" './recording_'"$(date '+%Y_%m_%_d..%H.%M.%S')"'.mp4' -a 'record-script.sh' - if [[ "$1" == "--sound" ]]; then - wf-recorder -t -f './recording_'"$(date '+%Y_%m_%_d..%H.%M.%S')"'.mp4' --geometry "$(slurp)" --audio=alsa_output.pci-0000_08_00.6.analog-stereo.monitor - else - wf-recorder -t -f './recording_'"$(date '+%Y_%m_%_d..%H.%M.%S')"'.mp4' --geometry "$(slurp)" - fi -else - /usr/bin/kill --signal SIGINT wf-recorder - notify-send "Recording Stopped" "Stopped" -a 'record-script.sh' -fi diff --git a/home/desktops/hyprland/ags/scripts/scripts.js b/home/desktops/hyprland/ags/scripts/scripts.js deleted file mode 100644 index a5449ae..0000000 --- a/home/desktops/hyprland/ags/scripts/scripts.js +++ /dev/null @@ -1,107 +0,0 @@ -import { App, Service, Utils, Widget } from '../imports.js'; -const { exec, execAsync, CONFIG_DIR } = Utils; - -export const deflisten = function (name, command, transformer = (a) => a) { - const { Service } = ags; - const GObject = imports.gi.GObject; - - const v = GObject.registerClass( - { - GTypeName: name, - Properties: { - state: GObject.ParamSpec.string( - "state", - "State", - "Read-Write string state.", - GObject.ParamFlags.READWRITE, - "" - ), - }, - Signals: { - [`${name}-changed`]: {}, - }, - }, - class Subclass extends Service { - get state() { - return this._state || ""; - } - - set state(value) { - this._state = value; - this.emit("changed"); - } - - get proc() { - return this._proc || null; - } - - set proc(value) { - this._proc = value; - } - - start = () => { - this.proc = Utils.subprocess(command, (line) => { - this.state = transformer(line); - }); - } - - stop = () => { - this.proc.force_exit(); - this.proc = null; - } - - constructor() { - super(); - this.proc = Utils.subprocess(command, (line) => { - this.state = transformer(line); - }); - } - } - ); - - class State { - static { - globalThis[name] = this; - } - - static instance = new v(); - - static get state() { - return State.instance.state; - } - - static set state(value) { - State.instance.state = value; - } - - static start() { - State.instance.start(); - } - static stop() { - State.instance.stop(); - } - } - - return State; -} - -export async function switchWall() { - try { - path = exec(`bash -c 'cd ~/Pictures && yad --width 1200 --height 800 --file --title="Choose wallpaper"'`); - screensizey = JSON.parse(exec(`hyprctl monitors -j`))[0]['height']; - cursorposx = exec(`bash -c 'hyprctl cursorpos -j | gojq ".x"'`); - cursorposy = exec(`bash -c 'hyprctl cursorpos -j | gojq ".y"'`); - cursorposy_inverted = screensizey - cursorposy; - // print all those - if (path == '') { - print('Switch wallpaper: Aborted'); - return; - } - print(`Sending ${path} to swww. Cursor pos: [${cursorposx}, ${cursorposy_inverted}]`); - exec(`swww img ${path} --transition-step 230 --transition-fps 60 --transition-type grow --transition-angle 30 --transition-duration 1 --transition-pos "${cursorposx}, ${cursorposy_inverted}"`); - exec(CONFIG_DIR + `/scripts/colorgen.sh ${path} --apply`); - imports.scss.scss.setupScss(); - } catch (error) { - print(error); - } -} diff --git a/home/desktops/hyprland/ags/scripts/swapws b/home/desktops/hyprland/ags/scripts/swapws deleted file mode 100755 index b0dc8d3..0000000 Binary files a/home/desktops/hyprland/ags/scripts/swapws and /dev/null differ diff --git a/home/desktops/hyprland/ags/scripts/swapws.cpp b/home/desktops/hyprland/ags/scripts/swapws.cpp deleted file mode 100755 index ead7b34..0000000 --- a/home/desktops/hyprland/ags/scripts/swapws.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nlohmann/json.hpp" -using namespace std; -using json = nlohmann::json; - -int workspace_a, workspace_b; -string clients; -json clientjson; -vector windows_a, windows_b; -bool output = false; - -string exec(const char* cmd) { - array buffer; - string result; - unique_ptr pipe(popen(cmd, "r"), pclose); - if (!pipe) { - throw runtime_error("popen() failed!"); - } - while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { - result += buffer.data(); - } - return result; -} - -void tryAddApp(const json& client) { - if (int(client["workspace"]["id"]) == workspace_a) - windows_a.push_back(client["address"]); - else if (int(client["workspace"]["id"]) == workspace_b) - windows_b.push_back(client["address"]); -} - -void getApps() { - // Get clients - clients = exec("hyprctl clients -j | gojq -c -M"); - clientjson = json::parse(clients); - - // Access the values - for (json client : clientjson) { - tryAddApp(client); - } -} - -void swapWorkspaces() { - for (string address : windows_a) { - string cmd = "hyprctl dispatch movetoworkspacesilent " + - to_string(workspace_b) + ",address:" + address; - if (output) cout << cmd << '\n'; - exec(&cmd[0]); - } - for (string address : windows_b) { - string cmd = "hyprctl dispatch movetoworkspacesilent " + - to_string(workspace_a) + ",address:" + address; - if (output) cout << cmd << '\n'; - exec(&cmd[0]); - } -} - -int main(int argc, char* argv[]) { - ios::sync_with_stdio(false); - - if (argc < 3) { - cout << "Usage: swapws [WORKSPACE_NUMBER_1] [WORKSPACE_NUMBER_2]" - << endl; - return 0; - } - if (argc == 4 && string(argv[3]) == "--output") output = true; - - workspace_a = stoi(string(argv[1])); - workspace_b = stoi(string(argv[2])); - if (workspace_a <= 0 || workspace_b <= 0 || workspace_a == workspace_b) { - cout << "Nahhh that's stupid" << endl; - return 0; - } - - getApps(); - swapWorkspaces(); -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scripts/templates/foot/foot.ini b/home/desktops/hyprland/ags/scripts/templates/foot/foot.ini deleted file mode 100755 index fa4e2a8..0000000 --- a/home/desktops/hyprland/ags/scripts/templates/foot/foot.ini +++ /dev/null @@ -1,156 +0,0 @@ -# -*- conf -*- - -shell=fish -# term=foot (or xterm-256color if built with -Dterminfo=disabled) -term=xterm-256color -# login-shell=no - -# app-id=foot -title=foot -# locked-title=no - -font=JetBrainsMono Nerd Font:size=12 -# font-bold= -# font-italic= -# font-bold-italic= -# line-height= -letter-spacing=0 -# horizontal-letter-offset=0 -# vertical-letter-offset=0 -# underline-offset= -# box-drawings-uses-font-glyphs=no -dpi-aware=no - -# initial-window-size-pixels=700x500 # Or, -# initial-window-size-chars= -# initial-window-mode=windowed -pad=25x25 # optionally append 'center' -# resize-delay-ms=100 - -# notify=notify-send -a ${app-id} -i ${app-id} ${title} ${body} - -bold-text-in-bright=no -# word-delimiters=,│`|:"'()[]{}<> -# selection-target=primary -# workers= - -[bell] -# urgent=no -# notify=no -# command= -# command-focused=no - -[scrollback] -lines=10000 -# multiplier=3.0 -# indicator-position=relative -# indicator-format= - -[url] -# launch=xdg-open ${url} -# label-letters=sadfjklewcmpgh -# osc8-underline=url-mode -# protocols=http, https, ftp, ftps, file, gemini, gopher -# uri-characters=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.,~:;/?#@!$&%*+="' - -[cursor] -style=beam -# color=111111 dcdccc -color=$background # $onBackground # -# blink=no -beam-thickness=1.5 -# underline-thickness= - -[mouse] -# hide-when-typing=no -# alternate-scroll-mode=yes - -[colors] -alpha=1 -background=$background # -foreground=$onBackground # -regular0=$background # -regular1=$error # -regular2=$inversePrimary # -regular3=$onPrimaryContainer # -regular4=$onPrimaryContainer # -regular5=$onSecondaryContainer # -regular6=$primary # -regular7=$onSurfaceVariant # -bright0=$background # -bright1=$error # -bright2=$inversePrimary # -bright3=$onPrimaryContainer # -bright4=$onPrimaryContainer # -bright5=$onSecondaryContainer # -bright6=$primary # -bright7=$onSurfaceVariant # - -[csd] -# preferred=server -# size=26 -# font= -# color= -# button-width=26 -# button-color= -# button-minimize-color= -# button-maximize-color= -# button-close-color= - -[key-bindings] -scrollback-up-page=Page_Up -# scrollback-up-half-page=none -# scrollback-up-line=none -scrollback-down-page=Page_Down -# scrollback-down-half-page=none -# scrollback-down-line=none -clipboard-copy=Control+c -clipboard-paste=Control+v -# primary-paste=Shift+Insert -search-start=Control+f -# font-increase=Control+plus Control+equal Control+KP_Add -# font-decrease=Control+minus Control+KP_Subtract -# font-reset=Control+0 Control+KP_0 -# spawn-terminal=Control+Shift+n -# minimize=none -# maximize=none -# fullscreen=none -# pipe-visible=[sh -c "xurls | fuzzel | xargs -r firefox"] none -# pipe-scrollback=[sh -c "xurls | fuzzel | xargs -r firefox"] none -# pipe-selected=[xargs -r firefox] none -# show-urls-launch=Control+Shift+u -# show-urls-copy=none - -[search-bindings] -# cancel=Control+g Control+c Escape -# commit=Return -# find-prev=Control+r -# find-next=Control+s -# cursor-left=Left Control+b -# cursor-left-word=Control+Left Mod1+b -# cursor-right=Right Control+f -# cursor-right-word=Control+Right Mod1+f -# cursor-home=Home Control+a -# cursor-end=End Control+e -# delete-prev=BackSpace -# delete-prev-word=Control+BackSpace -# delete-next=Delete -# delete-next-word=Mod1+d Control+Delete -# extend-to-word-boundary=Control+w -# extend-to-next-whitespace=Control+Shift+w -# clipboard-paste=Control+v Control+y -# primary-paste=Shift+Insert - -[url-bindings] -# cancel=Control+g Control+c Control+d Escape -# toggle-url-visible=t - -[mouse-bindings] -# primary-paste=BTN_MIDDLE -# select-begin=BTN_LEFT -# select-begin-block=Control+BTN_LEFT -# select-extend=BTN_RIGHT -# select-extend-character-wise=Control+BTN_RIGHT -# select-word=BTN_LEFT-2 -# select-word-whitespace=Control+BTN_LEFT-2 -# select-row=BTN_LEFT-3 diff --git a/home/desktops/hyprland/ags/scripts/templates/fuzzel/fuzzel.ini b/home/desktops/hyprland/ags/scripts/templates/fuzzel/fuzzel.ini deleted file mode 100755 index 9edf143..0000000 --- a/home/desktops/hyprland/ags/scripts/templates/fuzzel/fuzzel.ini +++ /dev/null @@ -1,21 +0,0 @@ -font=Lexend -terminal=foot -e -prompt=">> " -layer=overlay - -[colors] -background=$backgroundcc -text=$onBackgroundff -selection=$surfaceVariantff -selection-text=$onSurfaceVariantff -border=$surfaceVariantff -match=$primaryff -selection-match=$primaryff - - -[border] -radius=17 -width=2 - -[dmenu] -exit-immediately-if-empty=yes diff --git a/home/desktops/hyprland/ags/scripts/templates/gradience/preset.json b/home/desktops/hyprland/ags/scripts/templates/gradience/preset.json deleted file mode 100644 index c24826a..0000000 --- a/home/desktops/hyprland/ags/scripts/templates/gradience/preset.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "name": "Material-blue-light", - "variables": { - "theme_fg_color": "#AEE5FA", - "theme_text_color": "#AEE5FA", - "theme_bg_color": "#1a1b26", - "theme_base_color": "#1a1b26", - "theme_selected_bg_color": "#AEE5FA", - "theme_selected_fg_color": "rgba(0, 0, 0, 0.87)", - "insensitive_bg_color": "#1a1b26", - "insensitive_fg_color": "rgba(192, 202, 245, 0.5)", - "insensitive_base_color": "#24283b", - "theme_unfocused_fg_color": "#AEE5FA", - "theme_unfocused_text_color": "#c0caf5", - "theme_unfocused_bg_color": "#1a1b26", - "theme_unfocused_base_color": "#1a1b26", - "theme_unfocused_selected_bg_color": "#a9b1d6", - "theme_unfocused_selected_fg_color": "rgba(0, 0, 0, 0.87)", - "unfocused_insensitive_color": "rgba(192, 202, 245, 0.5)", - "borders": "rgba(192, 202, 245, 0.12)", - "unfocused_borders": "rgba(192, 202, 245, 0.12)", - "warning_color": "#FDD633", - "error_color": "#BA1B1B", - "success_color": "#81C995", - "wm_title": "#AEE5FA", - "wm_unfocused_title": "rgba(192, 202, 245, 0.7)", - "wm_highlight": "rgba(192, 202, 245, 0.1)", - "wm_bg": "#1a1b26", - "wm_unfocused_bg": "#1a1b26", - "wm_button_close_icon": "#1a1b26", - "wm_button_close_hover_bg": "#a9b1d6", - "wm_button_close_active_bg": "#c7c7c7", - "content_view_bg": "#1a1b26", - "placeholder_text_color": "silver", - "text_view_bg": "#1d1d1d", - "budgie_tasklist_indicator_color": "#90D1F6", - "budgie_tasklist_indicator_color_active": "#90D1F6", - "budgie_tasklist_indicator_color_active_window": "#999999", - "budgie_tasklist_indicator_color_attention": "#FDD633", - "STRAWBERRY_100": "#FF9262", - "STRAWBERRY_300": "#FF793E", - "STRAWBERRY_500": "#F15D22", - "STRAWBERRY_700": "#CF3B00", - "STRAWBERRY_900": "#AC1800", - "ORANGE_100": "#FFDB91", - "ORANGE_300": "#FFCA40", - "ORANGE_500": "#FAA41A", - "ORANGE_700": "#DE8800", - "ORANGE_900": "#C26C00", - "BANANA_100": "#FFFFA8", - "BANANA_300": "#FFFA7D", - "BANANA_500": "#FFCE51", - "BANANA_700": "#D1A023", - "BANANA_900": "#A27100", - "LIME_100": "#A2F3BE", - "LIME_300": "#8ADBA6", - "LIME_500": "#73C48F", - "LIME_700": "#479863", - "LIME_900": "#1C6D38", - "BLUEBERRY_100": "#94A6FF", - "BLUEBERRY_300": "#6A7CE0", - "BLUEBERRY_500": "#3F51B5", - "BLUEBERRY_700": "#213397", - "BLUEBERRY_900": "#031579", - "GRAPE_100": "#D25DE6", - "GRAPE_300": "#B84ACB", - "GRAPE_500": "#9C27B0", - "GRAPE_700": "#830E97", - "GRAPE_900": "#6A007E", - "COCOA_100": "#9F9792", - "COCOA_300": "#7B736E", - "COCOA_500": "#574F4A", - "COCOA_700": "#463E39", - "COCOA_900": "#342C27", - "SILVER_100": "#EEE", - "SILVER_300": "#CCC", - "SILVER_500": "#AAA", - "SILVER_700": "#888", - "SILVER_900": "#666", - "SLATE_100": "#888", - "SLATE_300": "#666", - "SLATE_500": "#444", - "SLATE_700": "#222", - "SLATE_900": "#111", - "BLACK_100": "#474341", - "BLACK_300": "#403C3A", - "BLACK_500": "#393634", - "BLACK_700": "#33302F", - "BLACK_900": "#2B2928", - "accent_bg_color": "#006874", - "accent_fg_color": "#ffffff", - "accent_color": "#006874", - "destructive_bg_color": "#ba1b1b", - "destructive_fg_color": "#ffffff", - "destructive_color": "#ba1b1b", - "success_bg_color": "#81C995", - "success_fg_color": "rgba(0, 0, 0, 0.87)", - "warning_bg_color": "#FDD633", - "warning_fg_color": "rgba(0, 0, 0, 0.87)", - "error_bg_color": "#ba1b1b", - "error_fg_color": "#ffffff", - "window_bg_color": "rgba(251, 253, 253, 0.90)", - "window_fg_color": "#191c1d", - "view_bg_color": "#fbfdfd", - "view_fg_color": "#191c1d", - "headerbar_bg_color": "mix(@dialog_bg_color, @window_bg_color, 0.5)", - "headerbar_fg_color": "#051f23", - "headerbar_border_color": "rgba(205, 231, 236, 0.12)", - "headerbar_backdrop_color": "@headerbar_bg_color", - "headerbar_shade_color": "rgba(0, 0, 0, 0.09)", - "card_bg_color": "rgba(251, 253, 253, 0.20)", - "card_fg_color": "#051f23", - "card_shade_color": "rgba(0, 0, 0, 0.09)", - "dialog_bg_color": "#cde7ec", - "dialog_fg_color": "#051f23", - "popover_bg_color": "#cde7ec", - "popover_fg_color": "#051f23", - "thumbnail_bg_color": "#1a1b26", - "thumbnail_fg_color": "#AEE5FA", - "shade_color": "rgba(0, 0, 0, 0.36)", - "scrollbar_outline_color": "rgba(0, 0, 0, 0.5)" - }, - "palette": { - "blue_": {}, - "green_": {}, - "yellow_": {}, - "orange_": {}, - "red_": {}, - "purple_": {}, - "brown_": {}, - "light_": {}, - "dark_": {} - }, - "custom_css": { - "gtk4": "", - "gtk3": "" - }, - "plugins": {} -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scripts/templates/gradience/preset_template.json b/home/desktops/hyprland/ags/scripts/templates/gradience/preset_template.json deleted file mode 100644 index 8e2bf9c..0000000 --- a/home/desktops/hyprland/ags/scripts/templates/gradience/preset_template.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "name": "Material-blue-light", - "variables": { - "theme_fg_color": "#AEE5FA", - "theme_text_color": "#AEE5FA", - "theme_bg_color": "#1a1b26", - "theme_base_color": "#1a1b26", - "theme_selected_bg_color": "#AEE5FA", - "theme_selected_fg_color": "rgba(0, 0, 0, 0.87)", - "insensitive_bg_color": "#1a1b26", - "insensitive_fg_color": "rgba(192, 202, 245, 0.5)", - "insensitive_base_color": "#24283b", - "theme_unfocused_fg_color": "#AEE5FA", - "theme_unfocused_text_color": "#c0caf5", - "theme_unfocused_bg_color": "#1a1b26", - "theme_unfocused_base_color": "#1a1b26", - "theme_unfocused_selected_bg_color": "#a9b1d6", - "theme_unfocused_selected_fg_color": "rgba(0, 0, 0, 0.87)", - "unfocused_insensitive_color": "rgba(192, 202, 245, 0.5)", - "borders": "rgba(192, 202, 245, 0.12)", - "unfocused_borders": "rgba(192, 202, 245, 0.12)", - "warning_color": "#FDD633", - "error_color": "#BA1B1B", - "success_color": "#81C995", - "wm_title": "#AEE5FA", - "wm_unfocused_title": "rgba(192, 202, 245, 0.7)", - "wm_highlight": "rgba(192, 202, 245, 0.1)", - "wm_bg": "#1a1b26", - "wm_unfocused_bg": "#1a1b26", - "wm_button_close_icon": "#1a1b26", - "wm_button_close_hover_bg": "#a9b1d6", - "wm_button_close_active_bg": "#c7c7c7", - "content_view_bg": "#1a1b26", - "placeholder_text_color": "silver", - "text_view_bg": "#1d1d1d", - "budgie_tasklist_indicator_color": "#90D1F6", - "budgie_tasklist_indicator_color_active": "#90D1F6", - "budgie_tasklist_indicator_color_active_window": "#999999", - "budgie_tasklist_indicator_color_attention": "#FDD633", - "STRAWBERRY_100": "#FF9262", - "STRAWBERRY_300": "#FF793E", - "STRAWBERRY_500": "#F15D22", - "STRAWBERRY_700": "#CF3B00", - "STRAWBERRY_900": "#AC1800", - "ORANGE_100": "#FFDB91", - "ORANGE_300": "#FFCA40", - "ORANGE_500": "#FAA41A", - "ORANGE_700": "#DE8800", - "ORANGE_900": "#C26C00", - "BANANA_100": "#FFFFA8", - "BANANA_300": "#FFFA7D", - "BANANA_500": "#FFCE51", - "BANANA_700": "#D1A023", - "BANANA_900": "#A27100", - "LIME_100": "#A2F3BE", - "LIME_300": "#8ADBA6", - "LIME_500": "#73C48F", - "LIME_700": "#479863", - "LIME_900": "#1C6D38", - "BLUEBERRY_100": "#94A6FF", - "BLUEBERRY_300": "#6A7CE0", - "BLUEBERRY_500": "#3F51B5", - "BLUEBERRY_700": "#213397", - "BLUEBERRY_900": "#031579", - "GRAPE_100": "#D25DE6", - "GRAPE_300": "#B84ACB", - "GRAPE_500": "#9C27B0", - "GRAPE_700": "#830E97", - "GRAPE_900": "#6A007E", - "COCOA_100": "#9F9792", - "COCOA_300": "#7B736E", - "COCOA_500": "#574F4A", - "COCOA_700": "#463E39", - "COCOA_900": "#342C27", - "SILVER_100": "#EEE", - "SILVER_300": "#CCC", - "SILVER_500": "#AAA", - "SILVER_700": "#888", - "SILVER_900": "#666", - "SLATE_100": "#888", - "SLATE_300": "#666", - "SLATE_500": "#444", - "SLATE_700": "#222", - "SLATE_900": "#111", - "BLACK_100": "#474341", - "BLACK_300": "#403C3A", - "BLACK_500": "#393634", - "BLACK_700": "#33302F", - "BLACK_900": "#2B2928", - "accent_bg_color": "$primary", - "accent_fg_color": "$onPrimary", - "accent_color": "$primary", - "destructive_bg_color": "$error", - "destructive_fg_color": "$onError", - "destructive_color": "$error", - "success_bg_color": "#81C995", - "success_fg_color": "rgba(0, 0, 0, 0.87)", - "warning_bg_color": "#FDD633", - "warning_fg_color": "rgba(0, 0, 0, 0.87)", - "error_bg_color": "$error", - "error_fg_color": "$onError", - "window_bg_color": "$windowBgColor", - "window_fg_color": "$onBackground", - "view_bg_color": "$surface", - "view_fg_color": "$onSurface", - "headerbar_bg_color": "mix(@dialog_bg_color, @window_bg_color, 0.5)", - "headerbar_fg_color": "$onSecondaryContainer", - "headerbar_border_color": "$headerbarBorderColor", - "headerbar_backdrop_color": "@headerbar_bg_color", - "headerbar_shade_color": "rgba(0, 0, 0, 0.09)", - "card_bg_color": "$cardBgColor", - "card_fg_color": "$onSecondaryContainer", - "card_shade_color": "rgba(0, 0, 0, 0.09)", - "dialog_bg_color": "$secondaryContainer", - "dialog_fg_color": "$onSecondaryContainer", - "popover_bg_color": "$secondaryContainer", - "popover_fg_color": "$onSecondaryContainer", - "thumbnail_bg_color": "#1a1b26", - "thumbnail_fg_color": "#AEE5FA", - "shade_color": "rgba(0, 0, 0, 0.36)", - "scrollbar_outline_color": "rgba(0, 0, 0, 0.5)" - }, - "palette": { - "blue_": {}, - "green_": {}, - "yellow_": {}, - "orange_": {}, - "red_": {}, - "purple_": {}, - "brown_": {}, - "light_": {}, - "dark_": {} - }, - "custom_css": { - "gtk4": "", - "gtk3": "" - }, - "plugins": {} -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scripts/templates/gtklock/main.scss b/home/desktops/hyprland/ags/scripts/templates/gtklock/main.scss deleted file mode 100755 index 00a279a..0000000 --- a/home/desktops/hyprland/ags/scripts/templates/gtklock/main.scss +++ /dev/null @@ -1,86 +0,0 @@ -// Could just sed but scss is way less hacky -@import '../../../scss/_material.scss'; // Which is ~/.config/ags/scss/_material.scss - -* { - all: unset; - border: 0rem; -} - -window { - background-color: transparentize($background, 0.9); - background-size: cover; - background-repeat: no-repeat; - background-position: center; -} - -#window-box { - border-radius: 1.5rem; - padding: 1.5rem; -} - -#input-label { - font-size: 1.5rem; - color: transparent; - background-color: transparent; - margin: -20rem; // bye bye -} - -#input-field { - background-color: $secondaryContainer; - color: $onSecondaryContainer; - caret-color: $onSecondaryContainer; - border-radius: 999px; - font-size: 1.3rem; - padding: 0.341rem 1.364rem; - margin: 0.477rem; - box-shadow: 2px 2px 4px rgba(22, 22, 22, 0.5); - min-height: 2.727rem; -} - -#unlock-button { - margin: -20rem; // bye bye - color: transparent; - background-color: transparent; -} - -#error-label { - color: $error; -} - -#clock-label { - font-family: 'Lexend'; - font-size: 6rem; - border-radius: 1.2rem; - padding: 0.5rem; - margin: 0.6rem; - margin-top: -35rem; // higher clock position - color: $onSecondaryContainer; - text-shadow: 1px 1px 2px rgba(22, 22, 30, 0.5); -} - -// #user-image {} - -// #powerbar-box {} - -#poweroff-button, -#reboot-button,, -#suspend-button { - background-color: $secondaryContainer; - color: $onSecondaryContainer; - min-width: 3rem; - min-height: 3rem; - margin: 0.341rem; - border-radius: 9999px; -} - -#poweroff-button:hover, -#reboot-button:hover, -#suspend-button:hover { - background-color: mix($secondaryContainer, white, 80%); -} - -#poweroff-button:active, -#reboot-button:active, -#suspend-button:active { - background-color: mix($secondaryContainer, white, 70%); -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scripts/templates/gtklock/style.css b/home/desktops/hyprland/ags/scripts/templates/gtklock/style.css deleted file mode 100755 index 995d316..0000000 --- a/home/desktops/hyprland/ags/scripts/templates/gtklock/style.css +++ /dev/null @@ -1,102 +0,0 @@ -/* Gtklock css */ - -* { - all: unset; - border: 0px; -} - -window { - background: rgba(0, 0, 0, 0.5); - background-size: cover; - background-repeat: no-repeat; - background-position: center; -} - -#window-box { - border-radius: 1.5rem; - padding: 1.5rem; - border: 0px solid black; -} - -#input-label { - font-size: 1.5rem; - color: transparent; - background-color: transparent; - margin: -20rem; -} - -#input-field { - background-color: $secondaryContainer; - color: $onSecondaryContainer; - caret-color: $onSecondaryContainer; - border-radius: 999px; - font-size: 1.3rem; - padding: 0.341rem 1.364rem; - margin: 0.477rem; - box-shadow: 2px 2px 4px rgba(22, 22, 22, 0.5); - min-height: 2.727rem; -} - -#unlock-button { - margin: -20rem; - color: transparent; - background-color: transparent; -} - -#error-label { - color: $error; -} - -#clock-label { - font-family: 'Lexend'; - font-size: 6rem; - border-radius: 1.2rem; - padding: 0.5rem; - margin: 0.6rem; - margin-top: -35rem; - color: $onSecondaryContainer; - text-shadow: 1px 1px 2px rgba(22, 22, 30, 0.5); -} - -#user-image {} - -#powerbar-box {} - -#poweroff-button { - background-color: $secondaryContainer; - color: $onSecondaryContainer; - min-width: 3rem; - min-height: 3rem; - margin: 10px; - border-radius: 99px; -} - -#suspend-button { - background-color: $secondaryContainer; - color: $onSecondaryContainer; - min-width: 3rem; - min-height: 3rem; - margin: 10px; - border-radius: 99px; -} - -#reboot-button { - background-color: $secondaryContainer; - color: $onSecondaryContainer; - min-width: 3rem; - min-height: 3rem; - margin: 10px; - border-radius: 99px; -} - -#poweroff-button:hover, -#reboot-button:hover, -#suspend-button:hover { - background: rgba(200, 200, 200, 0.3); -} - -#poweroff-button:active, -#reboot-button:active, -#suspend-button:active { - background: rgba(200, 200, 200, 0.5); -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scripts/templates/hypr/colors.conf b/home/desktops/hyprland/ags/scripts/templates/hypr/colors.conf deleted file mode 100755 index 58d55d4..0000000 --- a/home/desktops/hyprland/ags/scripts/templates/hypr/colors.conf +++ /dev/null @@ -1,5 +0,0 @@ -# Auto generated color theme for image at: [Local wallpaper] -general { - col.active_border = rgba($primaryAA) 45deg - col.inactive_border = rgba(555555FF) -} diff --git a/home/desktops/hyprland/ags/scripts/todo.js b/home/desktops/hyprland/ags/scripts/todo.js deleted file mode 100644 index 5fd332b..0000000 --- a/home/desktops/hyprland/ags/scripts/todo.js +++ /dev/null @@ -1,86 +0,0 @@ -const { Gio, Gdk, Gtk } = imports.gi; -import { Service, Utils } from '../imports.js'; -const { exec, execAsync } = Utils; - -const clamp = (num, min, max) => Math.min(Math.max(num, min), max); -function fileExists(filePath) { - let file = Gio.File.new_for_path(filePath); - return file.query_exists(null); -} - -class TodoService extends Service { - static { - Service.register( - this, - { 'updated': [], }, - ); - } - - _todoPath = ''; - _todoJson = []; - - refresh(value) { - this.emit('updated', value); - } - - connectWidget(widget, callback) { - this.connect(widget, callback, 'updated'); - } - - get todo_json() { - return this._todoJson; - } - - add(content) { - this._todoJson.push({ content, done: false }); - Utils.writeFile(JSON.stringify(this._todoJson), this._todoPath) - .catch(print); - this.emit('updated'); - } - - check(index) { - this._todoJson[index].done = true; - Utils.writeFile(JSON.stringify(this._todoJson), this._todoPath) - .catch(print); - this.emit('updated'); - } - - uncheck(index) { - this._todoJson[index].done = false; - Utils.writeFile(JSON.stringify(this._todoJson), this._todoPath) - .catch(print); - this.emit('updated'); - } - - remove(index) { - this._todoJson.splice(index, 1); - Utils.writeFile(JSON.stringify(this._todoJson), this._todoPath) - .catch(print); - this.emit('updated'); - } - - constructor() { - super(); - this._todoPath = `${App.configDir}/../../.cache/ags/user/todo.json`; - if (!fileExists(this._todoPath)) { // No? create file with empty array - Utils.exec(`bash -c 'mkdir -p ~/.cache/ags/user'`); - Utils.exec(`touch ${this._todoPath}`); - Utils.writeFile("[]", this._todoPath).then(() => { - this._todoJson = JSON.parse(Utils.readFile(this._todoPath)) - }).catch(print); - } - else { - const fileContents = Utils.readFile(this._todoPath); - this._todoJson = JSON.parse(fileContents); - } - } -} - -// the singleton instance -const service = new TodoService(); - -// make it global for easy use with cli -globalThis.todo = service; - -// export to use in other modules -export default service; \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scripts/utils/find_firefox_profile.sh b/home/desktops/hyprland/ags/scripts/utils/find_firefox_profile.sh deleted file mode 100755 index 7b305b7..0000000 --- a/home/desktops/hyprland/ags/scripts/utils/find_firefox_profile.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -cd ~/.mozilla/firefox/ -if [[ $(grep '\[Profile[^0]\]' profiles.ini) ]] -then PROFPATH=$(grep -E '^\[Profile|^Path|^Default' profiles.ini | grep -1 '^Default=1' | grep '^Path' | cut -c6-) -else PROFPATH=$(grep 'Path=' profiles.ini | sed 's/^Path=//') -fi - -echo "$HOME/.mozilla/firefox/$PROFPATH" diff --git a/home/desktops/hyprland/ags/scss/_bar.scss b/home/desktops/hyprland/ags/scss/_bar.scss deleted file mode 100644 index cb512d5..0000000 --- a/home/desktops/hyprland/ags/scss/_bar.scss +++ /dev/null @@ -1,468 +0,0 @@ -// Made to be pixel-perfect with 11pt font size -// 1rem = 11pt = 14.6666666667px - -// Init -$black: black; -$white: white; -$notchSecondaryContainer: $secondaryContainer; -$notchOnSecondaryContainer: $onSecondaryContainer; -$notchPrimary: $primary; -$notchOnPrimary: $onPrimary; - -// Check dark mode. Set colors accordingly for the fake snotch that's always black -@if $darkmode ==true { - $notchSecondaryContainer: $secondaryContainer; - $notchOnSecondaryContainer: $onSecondaryContainer; - $notchPrimary: $primary; - $notchOnPrimary: $onPrimary; -} - -@else { - $notchSecondaryContainer: $onSecondaryContainer; - $notchOnSecondaryContainer: $secondaryContainer; - $notchPrimary: $primaryContainer; - $notchOnPrimary: $onPrimaryContainer; -} - -.bar-bg { - background-color: $t_background; - min-height: 2.727rem; -} - -.bar-sidespace { - min-width: 1.5rem; -} - -.bar-group-margin { - padding: 0.2rem; -} - -.bar-group { - // @include elevation-border; - background-color: $t_surface; -} - -.bar-group-center { - border-bottom-left-radius: 1.364rem; - border-bottom-right-radius: 1.364rem; - // background-color: $t_surface; - background-color: $black; // Hard code: fake notch -} - -.corner-bar-group { - border-radius: 1.364rem; // Half of bar height - border-width: 0.068rem; - // background-color: $t_surface; - background-color: $black; // Hard code: fake notch -} - -.bar-group-pad { - padding: 0rem 1.023rem; -} - -.bar-group-pad-less { - padding: 0rem 0.681rem; -} - -.bar-group-pad-system { - padding-left: 1.023rem; - padding-right: 0.547rem; -} - -.bar-group-pad-music { - padding-right: 1.023rem; - // padding-left: 0.273rem; -} - -.bar-group-pad-left { - padding-left: 1.364rem; - padding-right: 0.681rem; -} - -.bar-group-pad-right { - padding-left: 0.681rem; - padding-right: 1.364rem; -} - -.bar-group-pad-leftonly { - padding-left: 0.681rem; -} - -.bar-group-pad-rightonly { - padding-right: 0.681rem; -} - -.bar-group-standalone { - border-radius: 1.364rem; - -gtk-outline-radius: 1.364rem; -} - -.bar-group-round { - border-radius: 10rem; - -gtk-outline-radius: 10rem; -} - -.bar-group-middle { - border-radius: 0.477rem; - -gtk-outline-radius: 0.477rem; -} - -.bar-group-left { - border-radius: 0.477rem; - -gtk-outline-radius: 0.477rem; - border-top-left-radius: 1.364rem; - border-bottom-left-radius: 1.364rem; -} - -.bar-group-right { - border-radius: 0.477rem; - -gtk-outline-radius: 0.477rem; - border-top-right-radius: 1.364rem; - border-bottom-right-radius: 1.364rem; -} - -.bar-separator { - @include full-rounding; - min-width: 0.341rem; - min-height: 0.341rem; - background-color: mix($t_surface, $t_onSurface, 90%); - margin: 0rem 0.341rem; -} - -.bar-clock { - @include titlefont; - font-size: 1.2727rem; - color: $onBackground; -} - -.bar-date { - @include titlefont; - font-size: 1rem; - color: $onBackground; -} - -.bar-ws { - min-height: 1.636rem; - min-width: 1.772rem; - font-size: 1.091rem; - @include mainfont; - border-top: 0.068rem solid; - border-bottom: 0.068rem solid; - border-color: transparent; - color: $white; -} - -.bar-ws-active-box { - min-height: 1.636rem; - min-width: 1.772rem; - transition: 300ms cubic-bezier(0.05, 0.7, 0.1, 1); -} - -.bar-ws-active { - min-height: 1.636rem; - min-width: 1.772rem; - font-size: 1.091rem; - border: 0.4rem solid $black; - @include mainfont; - - background-clip: content-box; - background-color: $notchSecondaryContainer; - color: $notchOnSecondaryContainer; - border-radius: 999px; -} - -.bar-ws-active-middledecor { - min-width: 0.682rem; - min-height: 0.682rem; - border-radius: 9999px; - background-color: $black; - margin: 0rem 0.409rem; -} - -.bar-ws-occupied { - background-color: $notchSecondaryContainer; - color: $notchOnSecondaryContainer; - min-width: 1.772rem; - border-top: 0.068rem solid $notchOnSecondaryContainer; - border-bottom: 0.068rem solid $notchOnSecondaryContainer; -} - -.bar-ws-occupied-left { - background-color: $notchSecondaryContainer; - color: $notchOnSecondaryContainer; - min-width: 1.704rem; - border-top-left-radius: 999px; - border-bottom-left-radius: 999px; - - border-left: 0.068rem solid $notchOnSecondaryContainer; - border-top: 0.068rem solid $notchOnSecondaryContainer; - border-bottom: 0.068rem solid $notchOnSecondaryContainer; - border-right: 0px solid transparent; -} - -.bar-ws-occupied-right { - background-color: $notchSecondaryContainer; - color: $notchOnSecondaryContainer; - min-width: 1.704rem; - border-top-right-radius: 999px; - border-bottom-right-radius: 999px; - - border-right: 0.068rem solid $notchOnSecondaryContainer; - border-top: 0.068rem solid $notchOnSecondaryContainer; - border-bottom: 0.068rem solid $notchOnSecondaryContainer; - border-left: 0px solid transparent; -} - -.bar-ws-occupied-left-right { - @include full-rounding; - background-color: $notchSecondaryContainer; - color: $notchOnSecondaryContainer; - min-width: 1.636rem; - border: 0.068rem solid $notchOnSecondaryContainer; -} - -.bar-ws-empty { - color: white; - border-color: transparent; -} - -.bar-batt { - @include full-rounding; - padding: 0rem 0.341rem; - background-color: $t_secondaryContainer; - color: $t_onSecondaryContainer; - // border: 1px solid $onSecondaryContainer; -} - -.bar-sidemodule { - min-width: 26rem; -} - -.bar-batt-low { - background-color: $error; - color: $errorContainer; -} - -.bar-batt-full { - background-color: $successContainer; - color: $onSuccessContainer; -} - -.bar-batt-prog-low { - background-color: $error; - color: $errorContainer; -} - -.bar-batt-prog-full { - background-color: $successContainer; - color: $onSuccessContainer; -} - -.bar-music-playstate { - min-height: 1.770rem; - min-width: 1.770rem; - border-radius: 10rem; - margin-left: 0.273rem; - background-color: $secondaryContainer; - color: $onSecondaryContainer; -} - -.bar-music-circprog { - @include fluent_decel_long; - margin-left: 0.273rem; - min-width: 0.068rem; // 1px - min-height: 1.770rem; - padding: 0rem; - background-color: $secondaryContainer; - color: $onSecondaryContainer; -} - -.bar-music-playstate-playing { - min-height: 1.770rem; - min-width: 1.770rem; - border-radius: 10rem; - margin-left: 0.273rem; - background-color: $secondaryContainer; - color: $onSecondaryContainer; - // border: 1px solid $onSecondaryContainer; -} - -.bar-music-playstate-txt { - transition: 100ms cubic-bezier(0.05, 0.7, 0.1, 1); - @include icon-material; - font-size: 1.568rem; - margin: -0.1rem 0rem; - margin-left: 0.2rem; - margin-right: 0.17rem; -} - -.bar-music-cover { - background-position: center; - background-repeat: no-repeat; - background-size: 100% auto; - min-width: 11.932rem; -} - -.bar-music-extended-bg { - border-radius: 1.364rem; - min-width: 34.091rem; -} - -.bar-music-extended-ctl-bg { - border-radius: 1.364rem; - background-color: rgba(30, 30, 30, 0.6); -} - -.bar-music-bottom-bg { - border-radius: 1.364rem; - min-width: 34.091rem; -} - -.bar-music-bottom-ctl-bg { - border-radius: 1.364rem; - background-color: rgba(30, 30, 30, 0.6); -} - -.bar-music-extended-textbox { - margin: 1.023rem; -} - -.bar-music-bottom-cover { - border-radius: 10rem; -} - -.bar-music-hide-false { - @include md3_decel; - transition-duration: 100ms; - opacity: 1; -} - -.bar-music-hide-true { - @include md3_accel; - transition-duration: 100ms; - opacity: 0; -} - -.bar-music-btn { - font-size: 1.364rem; - border-radius: 10rem; - min-height: 2.591rem; - min-width: 2.591rem; -} - -.bar-music-btn:hover { - background-color: $hovercolor; -} - -.bar-prog-batt { - min-height: 0.955rem; - min-width: 0.068rem; - padding: 0rem; - border-radius: 10rem; - - trough { - min-height: 0.954rem; - min-width: 0.068rem; - border-radius: 10rem; - } - - progress { - min-height: 0.680rem; - min-width: 0.680rem; - margin: 0rem 0.137rem; - border-radius: 10rem; - background-color: $t_onSecondaryContainer; - } -} - -.bar-prog-batt-low { - progress { - background-color: $errorContainer; - } -} - -.bar-prog-batt-full { - progress { - background-color: $onSuccessContainer; - } -} - -.bar-batt-chargestate { - border-radius: 10rem; - background-color: transparent; -} - -.bar-batt-chargestate-charging { - border-radius: 10rem; - min-width: 0.681rem; - min-height: 0.681rem; - background-color: $t_onSecondaryContainer; -} - -.bar-batt-chargestate-low { - background-color: $errorContainer; -} - -.bar-batt-chargestate-full { - background-color: $onSuccessContainer; -} - -.bar-batt-percentage { - font-size: 1rem; - margin-top: -0.068rem; - font-weight: 500; -} - -.corner { - background-color: $t_background; - @include large-rounding; -} - -.corner-black { - background-color: $black; // Hard code because fake screen corner - @include large-rounding; -} - -.bar-topdesc { - margin-top: -0.136rem; - margin-bottom: -0.341rem; - color: $subtext; -} - -.bar-space-button { - padding: 0.341rem; -} - -.bar-space-button>box:first-child { - @include full-rounding; - padding: 0rem 0.682rem; -} - -.bar-space-button:hover>box:first-child { - background-color: $hovercolor; -} - -.bar-space-button:active>box:first-child { - background-color: $activecolor; -} - -.bar-space-button-leftmost { - box { - margin: 0rem 0.682rem; - } -} - -.bar-space-area-rightmost>box { - padding-right: 2.386rem; -} - -.bar-systray { - @include full-rounding; - min-height: 1.909rem; - min-width: 1.909rem; -} - -.bar-systray-item { - @include full-rounding; - min-width: 1.909rem; -} diff --git a/home/desktops/hyprland/ags/scss/_cheatsheet.scss b/home/desktops/hyprland/ags/scss/_cheatsheet.scss deleted file mode 100644 index 363b386..0000000 --- a/home/desktops/hyprland/ags/scss/_cheatsheet.scss +++ /dev/null @@ -1,51 +0,0 @@ -.cheatsheet-bg { - @include large-rounding; - @include elevation-border; - @include elevation2; - margin-bottom: 0.682rem; - background-color: $t_background; - padding: 1.364rem; -} - -.cheatsheet-key { - @include techfont; - min-height: 1.364rem; - min-width: 1.364rem; - margin: 0.17rem; - padding: 0.136rem 0.205rem; - border-radius: 0.409rem; - -gtk-outline-radius: 0.409rem; - color: $primary; - border: 0.068rem solid $primary; - box-shadow: 0rem 0.136rem 0rem $primary; - font-weight: 500; -} - -.cheatsheet-key-notkey { - min-height: 1.364rem; - padding: 0.136rem 0.205rem; - margin: 0.17rem; - color: $onPrimaryContainer; -} - -// .cheatsheet-action {} - -.cheatsheet-closebtn { - @include md3_decel; - @include full-rounding; - min-width: 2.386rem; - min-height: 2.386rem; -} - -.cheatsheet-closebtn:hover { - background-color: $surfaceVariant; -} - -.cheatsheet-closebtn:active { - background-color: mix($surfaceVariant, $onSurfaceVariant, 70%); -} - -.cheatsheet-category-title { - @include titlefont; - font-size: 1.705rem; -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scss/_colors.scss b/home/desktops/hyprland/ags/scss/_colors.scss deleted file mode 100755 index 2d9db22..0000000 --- a/home/desktops/hyprland/ags/scss/_colors.scss +++ /dev/null @@ -1,79 +0,0 @@ -// Transparent version -$transparentize_amount: 0.6; -$transparentize_surface_amount_less: 0.3; -$transparentize_surface_amount_less_less: 0.15; -$transparentize_surface_amount: 0.7; -$transparentize_surface_amount_more: 0.1; -$transparentize_surface_amount_subtract_surface: $transparentize_surface_amount - $transparentize_amount; - -@if $darkmode ==true { - // Less transparency - $transparentize_amount: 0.6; - $transparentize_surface_amount_less: 0.2; - $transparentize_surface_amount_less_less: 0.1; - $transparentize_surface_amount: 0.7; - $transparentize_surface_amount_more: 0.1; - $transparentize_surface_amount_subtract_surface: $transparentize_surface_amount - $transparentize_amount; -} - -// Extended material -$success: #4f6354; -$onSuccess: #ffffff; -$successContainer: #d1e8d5; -$onSuccessContainer: #0c1f13; - -@if $darkmode ==true { - // Dark variant - $success: #b5ccba; - $onSuccess: #213528; - $successContainer: #374b3e; - $onSuccessContainer: #d1e9d6; -} - -// Transparent material -$t_primary: transparentize($primary, $transparentize_amount); -$t_onPrimary: transparentize($onPrimary, $transparentize_amount); -$t_primaryContainer: transparentize($primaryContainer, $transparentize_amount); -$t_onPrimaryContainer: transparentize($onPrimaryContainer, $transparentize_amount); -$t_secondary: transparentize($secondary, $transparentize_amount); -$t_onSecondary: transparentize($onSecondary, $transparentize_amount); -$t_secondaryContainer: transparentize($secondaryContainer, $transparentize_amount); -$l_t_secondaryContainer: transparentize($secondaryContainer, $transparentize_surface_amount_less); -$t_onSecondaryContainer: transparentize($onSecondaryContainer, $transparentize_amount); -$t_t_t_onSecondaryContainer: transparentize($onSecondaryContainer, 0.93); -$t_tertiary: transparentize($tertiary, $transparentize_amount); -$t_onTertiary: transparentize($onTertiary, $transparentize_amount); -$t_tertiaryContainer: transparentize($tertiaryContainer, $transparentize_amount); -$t_onTertiaryContainer: transparentize($onTertiaryContainer, $transparentize_amount); -$t_error: transparentize($error, $transparentize_amount); -$t_onError: transparentize($onError, $transparentize_amount); -$t_errorContainer: transparentize($errorContainer, $transparentize_amount); -$t_onErrorContainer: transparentize($onErrorContainer, $transparentize_amount); -$t_colorbarbg: transparentize($colorbarbg, $transparentize_amount); -$t_background: transparentize($background, $transparentize_amount); -$t_t_background: transparentize($background, $transparentize_surface_amount_more); -$t_onBackground: transparentize($onBackground, $transparentize_amount); -$t_surface: transparentize($surface, $transparentize_surface_amount); -$t_t_surface: transparentize($surface, $transparentize_surface_amount_more); -$t_onSurface: transparentize($onSurface, $transparentize_surface_amount); -$t_surfaceVariant: transparentize($surfaceVariant, $transparentize_surface_amount); -$t_onSurfaceVariant: transparentize($onSurfaceVariant, $transparentize_surface_amount); -$t_t_surfaceVariant: transparentize($surfaceVariant, $transparentize_surface_amount_more); -$l_t_surfaceVariant: transparentize($surfaceVariant, $transparentize_surface_amount_less); -$l_l_t_surfaceVariant: transparentize($surfaceVariant, $transparentize_surface_amount_less_less); -$t_outline: transparentize($outline, $transparentize_amount); -$t_shadow: transparentize($shadow, $transparentize_amount); -$t_inverseSurface: transparentize($inverseSurface, $transparentize_amount); -$t_inverseOnSurface: transparentize($inverseOnSurface, $transparentize_amount); -$t_inversePrimary: transparentize($inversePrimary, $transparentize_amount); -// Transparent material (extended) -$t_success: transparentize($error, $transparentize_amount); -$t_onSuccess: transparentize($onError, $transparentize_amount); -$t_successContainer: transparentize($errorContainer, $transparentize_amount); -$t_onSuccessContainer: transparentize($onErrorContainer, $transparentize_amount); - -// Common stuff -$hovercolor: mix($t_surface, $t_onSurface, 50%); -$activecolor: mix($t_surface, $t_onSurface, 30%); -$subtext: mix($onBackground, $background, 70%); -$actiontext: mix($onBackground, $background, 85%); \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scss/_common.scss b/home/desktops/hyprland/ags/scss/_common.scss deleted file mode 100644 index 1edca48..0000000 --- a/home/desktops/hyprland/ags/scss/_common.scss +++ /dev/null @@ -1,43 +0,0 @@ -*:focus { - // box-shadow: inset 0rem 0rem 2px $t_onSurface; -} - -.menu { - padding: 0.681rem; - background: $surfaceVariant; - color: $onSurfaceVariant; - border-radius: 1.159rem; - -gtk-outline-radius: 1.159rem; -} - -.menubar>menuitem { - border-radius: 0.545rem; - -gtk-outline-radius: 0.545rem; - min-width: 13.636rem; - min-height: 2.727rem; -} - -.menu>menuitem { - padding: 0.4em 1.5rem; - background: transparent; - transition: 0.2s ease background; - border-radius: 0.545rem; - -gtk-outline-radius: 0.545rem; -} - -.menu>menuitem:hover { - background-color: mix($surfaceVariant, $onSurfaceVariant, 90%); -} - -.separator-line { - background-color: $surfaceVariant; - min-width: 0.068rem; - min-height: 0.068rem; -} - -tooltip { - @include large-rounding; - background-color: $surfaceVariant; - color: $onSurfaceVariant; - border: 1px solid $onSurfaceVariant; -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scss/_lib.scss b/home/desktops/hyprland/ags/scss/_lib.scss deleted file mode 100644 index 99e5f17..0000000 --- a/home/desktops/hyprland/ags/scss/_lib.scss +++ /dev/null @@ -1,696 +0,0 @@ -// Common colors -$hovercolor: rgba(128, 128, 128, 0.3); -$activecolor: rgba(128, 128, 128, 0.7); -$rounding_small: 0.818rem; -$rounding_mediumsmall: 0.955rem; -$rounding_medium: 1.159rem; -$rounding_mediumlarge: 1.364rem; -$rounding_large: 1.705rem; - -.test { - background-image: linear-gradient(45deg, - #F4D609 0%, #F4D609 10%, #212121 10%, #212121 20%, - #F4D609 20%, #F4D609 30%, #212121 30%, #212121 40%, - #F4D609 40%, #F4D609 50%, #212121 50%, #212121 60%, - #F4D609 60%, #F4D609 70%, #212121 70%, #212121 80%, - #F4D609 80%, #F4D609 90%, #212121 90%, #212121 100%); - background-repeat: repeat; -} - -.test-size { - min-height: 3rem; - min-width: 3rem; -} - -// Common rules -@mixin small-rounding { - border-radius: $rounding_small; // 10px - -gtk-outline-radius: $rounding_small; // 10px -} - -@mixin normal-rounding { - border-radius: $rounding_medium; // small-rounding + 5px - -gtk-outline-radius: $rounding_medium; // small-rounding + 5px -} - -@mixin large-rounding { - border-radius: $rounding_large; // normal-rounding + 10px - -gtk-outline-radius: $rounding_large; // normal-rounding + 10px -} - -@mixin full-rounding { - border-radius: 9999px; - -gtk-outline-radius: 9999px; -} - -@mixin titlefont { - // Geometric sans-serif - font-family: - 'Noto Sans', - 'Gabarito', - 'Lexend', - sans-serif; -} - -.txt-title { - @include titlefont; - font-size: 2.045rem; -} - -.txt-title-small { - @include titlefont; - font-size: 1.364rem; -} - -@mixin mainfont { - // Other clean sans-serif - font-family: - 'AR One Sans', - 'Inter', - 'Roboto', - 'Noto Sans', - sans-serif; - // font-weight: 500; -} - -@mixin icon-material { - // Material Design Icons - font-family: - 'Material Symbols Rounded', - 'Material Symbols Outlined', - 'Material Symbols Sharp'; -} - -@mixin icon-nerd { - // Nerd Fonts - font-family: - 'SpaceMono Nerd Font', - 'JetBrainsMono Nerd Font', - monospace; -} - -@mixin techfont { - // Monospace for sys info n stuff. Doesn't have to be a nerd font, but it's cool. - font-family: 'JetBrains Mono Nerd Font', 'JetBrains Mono NL', 'SpaceMono Nerd Font', monospace; -} - -.techfont { - @include techfont; -} - -@mixin subtext { - color: $subtext; -} - -@mixin actiontext { - color: $actiontext; -} - -@mixin elevation-safe { - background: $surface; - color: $onSurface; - box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.69); - margin: 7px; -} - -$elevation2_margin: 7px; - -@mixin elevation2 { - box-shadow: 0px 2px 3px transparentize($shadow, 0.55); - margin: $elevation2_margin; -} - -@mixin elevation2-margin { - margin: $elevation2_margin; -} - -@mixin elevation2-padding { - padding: $elevation2_margin; -} - -@mixin elevation3 { - box-shadow: 0px 2px 5px $shadow; - margin: 7px; -} - -@mixin md3_decel { - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); -} - -@mixin md3_decel_fast { - transition: 170ms cubic-bezier(0.05, 0.7, 0.1, 1); -} - -@mixin md3_accel { - transition: 150ms cubic-bezier(0.3, 0, 0.8, 0.15); -} - -@mixin md3_accel_fast { - transition: 100ms cubic-bezier(0.3, 0, 0.8, 0.15); -} - -@mixin fluent_decel { - // Used for small transitions, as this looks clear - transition: 200ms cubic-bezier(0.1, 1, 0, 1); -} - -@mixin fluent_decel_long { - // Used for small transitions, as this looks clear - transition: 1000ms cubic-bezier(0.1, 1, 0, 1); -} - -@mixin fluent_accel { - transition: 150ms cubic-bezier(0.42, 0, 1, 1); -} - -@mixin noanim { - transition: 0ms; -} - -@mixin anim-enter { - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); -} - -@mixin anim-exit { - transition: 150ms cubic-bezier(0.3, 0, 0.8, 0.15); -} - -@keyframes flyin-top { - from { - margin-top: -2.795rem; - } - - to { - margin-top: 0rem; - } -} - -@keyframes flyin-bottom { - from { - margin-top: 4.841rem; - margin-bottom: -4.841rem; - } - - to { - margin-bottom: 0rem; - margin-top: 0rem; - } -} - -@function tint($color, $percentage) { - @return mix(rgb(245, 250, 255), $color, $percentage); -} - -@function shade($color, $percentage) { - @return mix(rgb(0, 0, 0), $color, $percentage); -} - -.no-anim { - @include noanim; -} - -.txt { - color: $onBackground; -} - -.txt-shadow { - text-shadow: 1px 2px 8px rgba(0, 0, 0, 0.69); - margin: 10px; -} - -.txt-badonkers { - @include mainfont; - font-size: 3rem; -} - -.txt-tiddies { - @include mainfont; - font-size: 2.7273rem; -} - -.txt-hugeass { - @include mainfont; - font-size: 1.8182rem; -} - -.txt-larger { - @include mainfont; - font-size: 1.6363rem; -} - -.txt-large { - //16pt - @include mainfont; - font-size: 1.4545rem; -} - -.txt-norm { - //14pt - @include mainfont; - font-size: 1.2727rem; -} - -.txt-small { - //12pt - @include mainfont; - font-size: 1.0909rem; -} - -.txt-smallie { - //11pt - @include mainfont; - font-size: 1rem; -} - -.txt-smaller { - //10pt - @include mainfont; - font-size: 0.9091rem; -} - -.txt-smaller-offset { - margin-top: -0.136rem; -} - -.txt-tiny { - @include mainfont; - font-size: 0.7273rem; -} - -.txt-subtext { - @include subtext; -} - -.txt-action { - @include actiontext; -} - -.txt-semibold { - font-weight: 500; -} - -.txt-bold { - font-weight: bold; -} - -.titlefont { - @include titlefont; -} - -.mainfont { - @include mainfont; -} - -.icon-material { - @include icon-material; -} - -.separator-circle { - @include full-rounding; - background-color: $onSurface; - margin: 0rem 0.682rem; - min-width: 0.545rem; - min-height: 0.545rem; -} - -$overlay1: mix($onSurface, rgba(0, 0, 0, 0), 25%); -$overlay2: mix($onSurface, rgba(0, 0, 0, 0), 40%); - -.spacing-v-15>box { - margin-bottom: 1.023rem; -} - -.spacing-v-15>box:last-child { - margin-bottom: 0rem; -} - -.spacing-v-15>scrolledwindow { - margin-bottom: 1.023rem; -} - -.spacing-v-15>scrolledwindow:last-child { - margin-bottom: 0rem; -} - -.spacing-v-15>revealer { - margin-bottom: 1.023rem; -} - -.spacing-v-15>revealer:last-child { - margin-bottom: 0rem; -} - -.spacing-v-15>label { - margin-bottom: 1.023rem; -} - -.spacing-v-15>label:last-child { - margin-bottom: 0rem; -} - -.spacing-h-15>box { - margin-right: 1.023rem; -} - -.spacing-h-15>box:last-child { - margin-right: 0rem; -} - -.spacing-h-15>stack { - margin-right: 1.023rem; -} - -.spacing-h-15>stack:last-child { - margin-right: 0rem; -} - -.spacing-h-15>label { - margin-right: 1.023rem; -} - -.spacing-h-15>label:last-child { - margin-right: 0rem; -} - -.spacing-h-15>button { - margin-right: 1.023rem; -} - -.spacing-h-15>button:last-child { - margin-right: 0rem; -} - -.spacing-v-5>box { - margin-bottom: 0.341rem; -} - -.spacing-v-5>box:last-child { - margin-bottom: 0rem; -} - -.spacing-v-5>label { - margin-bottom: 0.341rem; -} - -.spacing-v-5>label:last-child { - margin-bottom: 0rem; -} - -.spacing-v-5>button { - margin-bottom: 0.341rem; -} - -.spacing-v-5>button:last-child { - margin-bottom: 0rem; -} - -.spacing-v-5-revealer>revealer>box { - margin-bottom: 0.341rem; -} - -.spacing-v-5-revealer>revealer:last-child>box { - margin-bottom: 0rem; -} - -.spacing-h-5>box { - margin-right: 0.341rem; -} - -.spacing-h-5>box:last-child { - margin-right: 0rem; -} - -.spacing-h-5>button { - margin-right: 0.341rem; -} - -.spacing-h-5>button:last-child { - margin-right: 0rem; -} - -.spacing-h-5>label { - margin-right: 0.341rem; -} - -.spacing-h-5>label:last-child { - margin-right: 0rem; -} - -.spacing-h-5>widget>box { - margin-right: 0.341rem; -} - -.spacing-h-5>widget:last-child>box { - margin-right: 0rem; -} - -.spacing-h-5>progressbar { - margin-right: 0.341rem; -} - -.spacing-h-5>progressbar:last-child { - margin-right: 0rem; -} - -.spacing-h-5>scrolledwindow { - margin-right: 0.341rem; -} - -.spacing-h-5>scrolledwindow:last-child { - margin-right: 0rem; -} - -.spacing-h-5>scrollbar { - margin-right: 0.341rem; -} - -.spacing-h-5>scrollbar:last-child { - margin-right: 0rem; -} - -.spacing-v-minus5>box { - margin-bottom: -0.341rem; -} - -.spacing-v-minus5>box:last-child { - margin-bottom: 0rem; -} - -.spacing-v-minus5>label { - margin-bottom: -0.341rem; -} - -.spacing-v-minus5>label:last-child { - margin-bottom: 0rem; -} - -.spacing-h-10>box { - margin-right: 0.682rem; -} - -.spacing-h-10>box:last-child { - margin-right: 0rem; -} - -.spacing-h-10>flowboxchild>button { - margin-right: 0.682rem; -} - -.spacing-h-10>flowboxchild:last-child>button { - margin-right: 0rem; -} - -.spacing-h-10>label { - margin-right: 0.682rem; -} - -.spacing-h-10>label:last-child { - margin-right: 0rem; -} - -.spacing-h-10>revealer { - margin-right: 0.682rem; -} - -.spacing-h-10>revealer:last-child { - margin-right: 0rem; -} - -.spacing-h-10>overlay { - margin-right: 0.682rem; -} - -.spacing-h-10>overlay:last-child { - margin-right: 0rem; -} - -.spacing-h-10>button { - margin-right: 0.682rem; -} - -.spacing-h-10>button:last-child { - margin-right: 0rem; -} - -.spacing-h-10>label { - margin-right: 0.682rem; -} - -.spacing-h-10>label:last-child { - margin-right: 0rem; -} - -.spacing-h-10>widget { - margin-right: 0.682rem; -} - -.spacing-h-10>widget:last-child { - margin-right: 0rem; -} - -.spacing-h-10>stack { - margin-right: 0.682rem; -} - -.spacing-h-10>stack:last-child { - margin-right: 0rem; -} - -.spacing-v-10>box { - margin-bottom: 0.682rem; -} - -.spacing-v-10>box:last-child { - margin-bottom: 0rem; -} - -.spacing-v-10>button { - margin-bottom: 0.682rem; -} - -.spacing-v-10>button:last-child { - margin-bottom: 0rem; -} - -.anim-enter { - @include anim-enter; -} - -.anim-exit { - @include anim-exit; -} - -@mixin elevation-border-softer { - border-top: 1px solid mix($t_t_surface, $t_onSurface, 80%); - border-left: 1px solid mix($t_t_surface, $t_onSurface, 80%); - border-right: 1px solid mix($t_t_surface, $t_onSurface, 85%); - border-bottom: 1px solid mix($t_t_surface, $t_onSurface, 85%); -} - -@mixin elevation-border { - border-top: 1px solid mix($t_t_surface, $onSurface, 90%); - border-left: 1px solid mix($t_t_surface, $onSurface, 90%); - border-right: 1px solid mix($t_t_surface, $onSurface, 95%); - border-bottom: 1px solid mix($t_t_surface, $onSurface, 95%); -} - -@mixin elevation-border-heavier { - border-top: 1px solid mix($t_t_surface, $onSurface, 80%); - border-left: 1px solid mix($t_t_surface, $onSurface, 80%); - border-right: 1px solid mix($t_t_surface, $onSurface, 85%); - border-bottom: 1px solid mix($t_t_surface, $onSurface, 85%); -} - -@mixin elevation-border-transparent { - border-top: 1px solid transparent; -} - -@mixin button-minsize { - min-width: 2.727rem; - min-height: 2.727rem; -} - -.button-minsize { - @include button-minsize; -} - -@mixin group-padding { - padding: 0.341rem; -} - -.group-padding { - @include group-padding; -} - -.margin-right-5 { - margin-right: 0.341rem; -} - -.margin-left-5 { - margin-left: 0.341rem; -} - -.margin-top-5 { - margin-top: 0.341rem; -} - -.margin-bottom-5 { - margin-bottom: 0.341rem; -} - -.margin-right-10 { - margin-right: 0.682rem; -} - -.margin-left-10 { - margin-left: 0.682rem; -} - -.margin-top-10 { - margin-top: 0.682rem; -} - -.margin-bottom-10 { - margin-bottom: 0.682rem; -} - -.invisible { - opacity: 0; - background-color: transparent; - color: transparent; -} - -.spacing-h--5>box { - margin-right: -0.341rem; -} - -.spacing-h--5>box:last-child { - margin-right: 0rem; -} - -.spacing-v--5>box { - margin-bottom: -0.341rem; -} - -.spacing-v--5>box:last-child { - margin-bottom: 0rem; -} - -.spacing-h--20>box { - margin-left: -1.364rem; -} - -.spacing-h--20>box:first-child { - margin-left: 0rem; -} - -$white: white; -$black: black; - -.instant { - transition: 0ms; -} - -.md3_decel { - @include md3_decel; -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scss/_material.scss b/home/desktops/hyprland/ags/scss/_material.scss deleted file mode 100755 index ac86335..0000000 --- a/home/desktops/hyprland/ags/scss/_material.scss +++ /dev/null @@ -1,29 +0,0 @@ -$darkmode: true; -$primary: #50d8ec; -$onPrimary: #00363d; -$primaryContainer: #004f58; -$onPrimaryContainer: #99f0ff; -$secondary: #b1cbd0; -$onSecondary: #1c3438; -$secondaryContainer: #334b4f; -$onSecondaryContainer: #cde7ec; -$tertiary: #bbc6ea; -$onTertiary: #24304d; -$tertiaryContainer: #3b4665; -$onTertiaryContainer: #dae2ff; -$error: #ba1b1b; -$onError: #ffffff; -$errorContainer: #ffdad4; -$onErrorContainer: #410001; -$colorbarbg: #191c1d; -$background: #191c1d; -$onBackground: #e1e3e3; -$surface: #191c1d; -$onSurface: #e1e3e3; -$surfaceVariant: #3f484a; -$onSurfaceVariant: #bfc8ca; -$outline: #899294; -$shadow: #000000; -$inverseOnSurface: #2d3132; -$inverseSurface: #eff1f1; -$inversePrimary: #4fd8ea; diff --git a/home/desktops/hyprland/ags/scss/_notifications.scss b/home/desktops/hyprland/ags/scss/_notifications.scss deleted file mode 100644 index 40e743d..0000000 --- a/home/desktops/hyprland/ags/scss/_notifications.scss +++ /dev/null @@ -1,126 +0,0 @@ -$notif_surface: $t_background; - -@mixin notif-rounding { - @include small-rounding; -} - -.notif-low { - @include notif-rounding; - background-color: $l_l_t_surfaceVariant; - color: $onSurfaceVariant; - padding: $rounding_small; - padding-right: $rounding_small + 0.545rem; -} - -.notif-normal { - @include notif-rounding; - background-color: $l_l_t_surfaceVariant; - color: $onSurfaceVariant; - padding: $rounding_small; - padding-right: $rounding_small + 0.545rem; -} - -.notif-critical { - @include notif-rounding; - background-color: $error; - color: $onError; - padding: $rounding_small; - padding-right: $rounding_small + 0.545rem; -} - -.popup-notif-low { - @include notif-rounding; - min-width: 30.682rem; - background-color: $notif_surface; - color: $onSurfaceVariant; - padding: $rounding_small; - padding-right: $rounding_small + 0.545rem; -} - -.popup-notif-normal { - @include notif-rounding; - min-width: 30.682rem; - background-color: $notif_surface; - color: $onSurfaceVariant; - padding: $rounding_small; - padding-right: $rounding_small + 0.545rem; -} - -.popup-notif-critical { - @include notif-rounding; - min-width: 30.682rem; - background-color: $error; - color: $onError; - padding: $rounding_small; - padding-right: $rounding_small + 0.545rem; -} - -.notif-body-low { - color: mix($onSurfaceVariant, $surfaceVariant, 67%); -} - -.notif-body-normal { - color: mix($onSurfaceVariant, $surfaceVariant, 67%); -} - -.notif-body-critical { - color: mix($onError, $error, 67%); -} - -.notif-icon { - @include full-rounding; - min-width: 3.409rem; - min-height: 3.409rem; -} - -.notif-icon-material { - background-color: $t_secondaryContainer; - color: $onSecondaryContainer; -} - -.notif-icon-material-low { - background-color: $t_secondaryContainer; - color: $onSecondaryContainer; -} - -.notif-icon-material-normal { - background-color: $t_secondaryContainer; - color: $onSecondaryContainer; -} - -.notif-icon-material-critical { - background-color: $t_errorContainer; - color: $onErrorContainer; -} - -.notif-close-btn { - @include notif-rounding; - padding: 0rem 0.136rem; -} - -.notif-close-btn:hover { - background: $hovercolor; -} - -.notif-close-btn:active { - background: $activecolor; -} - -.notif-closeall-btn { - @include notif-rounding; - padding: 0.341rem 0.341rem; -} - -.notif-closeall-btn:hover { - background-color: $hovercolor; -} - -.notif-closeall-btn:active { - background-color: $activecolor; -} - -.osd-notif { - @include notif-rounding; - background-color: transparentize($background, $transparentize_surface_amount_subtract_surface); - min-width: 30.682rem; -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scss/_osd.scss b/home/desktops/hyprland/ags/scss/_osd.scss deleted file mode 100644 index 33ced71..0000000 --- a/home/desktops/hyprland/ags/scss/_osd.scss +++ /dev/null @@ -1,59 +0,0 @@ -.osd-bg { - min-width: 8.864rem; - min-height: 3.409rem; -} - -.osd-value { - background-color: $t_background; - border-radius: 1.023rem; - padding: 0.625rem 1.023rem; - padding-top: 0.313rem; - margin: 10px; - @include elevation2; -} - -.osd-progress { - min-height: 0.955rem; - min-width: 0.068rem; - padding: 0rem; - border-radius: 10rem; - @include fluent_decel; - - trough { - min-height: 0.954rem; - min-width: 0.068rem; - border-radius: 10rem; - background-color: $onPrimaryContainer; - } - - progress { - @include fluent_decel; - min-height: 0.680rem; - min-width: 0.680rem; - margin: 0rem 0.137rem; - border-radius: 10rem; - background-color: $primaryContainer; - } -} - -.osd-icon { - color: $onPrimaryContainer; -} - -.osd-label { - font-size: 1.023rem; - font-weight: 500; - color: $onBackground; - margin-top: 0.341rem; -} - -.osd-value-txt { - @include titlefont; - font-size: 1.688rem; - font-weight: 500; - color: $onBackground; -} - -.osd-notifs { - padding-top: 0.313rem; -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scss/_osk.scss b/home/desktops/hyprland/ags/scss/_osk.scss deleted file mode 100644 index 22e62e5..0000000 --- a/home/desktops/hyprland/ags/scss/_osk.scss +++ /dev/null @@ -1,97 +0,0 @@ -$osk_key_height: 2.5rem; -$osk_key_width: 2.5rem; -$osk_key_padding: 0.188rem; -$osk_key_rounding: 0.682rem; -$osk_key_fontsize: 1.091rem; - -.osk-window { - @include md3_decel_fast; - @include large-rounding; - @include elevation-border; - @include elevation2; - // min-height: 29.591rem; - // min-width: 50rem; - background-color: $t_background; - padding: 1.023rem; -} - -.osk-show { - @include md3_decel_fast; -} - -.osk-hide { - margin-top: 30.682rem; - margin-bottom: -30.682rem; - // opacity: 0; - @include md3_accel_fast; -} - -.osk-key { - border-radius: $osk_key_rounding; - background-color: $t_surfaceVariant; - color: $onSurfaceVariant; - padding: $osk_key_padding; - font-weight: 500; - font-size: $osk_key_fontsize; -} - -.osk-key:hover { - background-color: mix($t_surfaceVariant, $t_onSurfaceVariant, 90%); -} - -.osk-key:active { - background-color: mix($t_surfaceVariant, $t_onSurfaceVariant, 70%); - font-size: $osk_key_fontsize; -} - -.osk-key-active { - background-color: mix($t_surfaceVariant, $t_onSurfaceVariant, 70%); -} - -.osk-key-normal { - min-width: $osk_key_width; - min-height: $osk_key_height; -} - -.osk-key-fn { - min-width: $osk_key_width * 1.005; - min-height: $osk_key_height / 2; -} - -.osk-key-tab { - min-width: $osk_key_width * 1.6; - min-height: $osk_key_height; -} - -.osk-key-caps { - min-width: $osk_key_width * 1.9; - min-height: $osk_key_height; -} - -.osk-key-shift { - min-width: $osk_key_width * 2.5; - min-height: $osk_key_height; -} - -.osk-key-control { - min-width: $osk_key_width * 1.3; - min-height: $osk_key_height; -} - -.osk-control-button { - border-radius: $osk_key_rounding; - background-color: $t_surfaceVariant; - color: $onSurfaceVariant; - font-weight: 500; - font-size: $osk_key_fontsize; - padding: 0.682rem; -} - -.osk-control-button:hover { - background-color: mix($t_surfaceVariant, $t_onSurfaceVariant, 90%); -} - -.osk-control-button:active { - background-color: mix($t_surfaceVariant, $t_onSurfaceVariant, 70%); - font-size: $osk_key_fontsize; -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scss/_overview.scss b/home/desktops/hyprland/ags/scss/_overview.scss deleted file mode 100644 index 4232d36..0000000 --- a/home/desktops/hyprland/ags/scss/_overview.scss +++ /dev/null @@ -1,130 +0,0 @@ -.overview-search-box { - @include md3_decel; - @include large-rounding; - @include elevation-border; - @include elevation2; - min-width: 13.636rem; - min-height: 3.409rem; - padding: 0rem 1.364rem; - padding-right: 2.864rem; - background-color: $t_background; - color: $onBackground; - - selection { - background-color: $secondary; - color: $onSecondary; - } - caret-color: transparent; -} - -.overview-search-box-extended { - min-width: 25.909rem; - caret-color: $onSecondaryContainer; -} - -.overview-search-prompt { - color: $subtext; -} - -.overview-search-icon { - margin: 0rem 1.023rem; -} - -.overview-search-prompt-box { - margin-left: -18.545rem; - margin-right: $elevation2_margin + 1px; -} - -.overview-search-icon-box { - margin-left: -18.545rem; - margin-right: $elevation2_margin + 1px; -} - -.overview-search-results { - // min-height: 2.813rem; - // min-height: 37.5rem; - @include large-rounding; - @include elevation-border; - @include elevation2; - min-width: 28.773rem; - padding: 0.682rem; - background-color: $t_background; - color: $onBackground; -} - -.overview-search-results-icon { - margin: 0rem 0.682rem; - font-size: 2.386rem; -} -.overview-search-results-txt { - margin-right: 0.682rem; -} - -.overview-search-results-txt-cmd { - margin-right: 0.682rem; - @include techfont; - font-size: 1.227rem; -} - -.overview-search-result-btn { - @include normal-rounding; - padding: 0.341rem; - min-width: 2.386rem; - min-height: 2.386rem; - - caret-color: transparent; -} - -.overview-search-result-btn:focus, -.overview-search-result-btn:hover { - background-color: $hovercolor; -} - -.overview-search-result-btn:active { - background-color: $activecolor; -} - -.overview-tasks { - @include large-rounding; - @include elevation-border; - @include elevation2; - padding: 0.341rem; - background-color: $t_background; - color: $onBackground; -} - -.overview-tasks-workspace { - @include normal-rounding; - // @include elevation-border; - margin: 0.341rem; - background-color: mix($t_t_surface, $t_onSurface, 93%); -} - -.overview-tasks-window { - @include normal-rounding; - // @include elevation-border-softer; - @include md3_decel; - background-color: $l_t_secondaryContainer; - color: $onSecondaryContainer; - border: 0.068rem solid $t_t_t_onSecondaryContainer; -} - -.overview-tasks-window:hover { - background-color: mix($l_t_secondaryContainer, $primary, 95%); -} - -.overview-tasks-window:focus { - background-color: mix($l_t_secondaryContainer, $primary, 95%); -} - -.overview-tasks-window:active { - background-color: mix($l_t_secondaryContainer, $primary, 90%); -} - -.overview-tasks-window-selected { - background-color: mix($l_t_secondaryContainer, $primary, 90%); -} - -.overview-tasks-window-dragging { - opacity: 0.2; -} \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scss/_session.scss b/home/desktops/hyprland/ags/scss/_session.scss deleted file mode 100644 index d302207..0000000 --- a/home/desktops/hyprland/ags/scss/_session.scss +++ /dev/null @@ -1,36 +0,0 @@ -.session-bg { - margin-top: -2.727rem; - background-color: mix($t_t_background, $background, 70%); -} - -.session-button { - @include large-rounding; - min-width: 8.182rem; - min-height: 8.182rem; - background-color: $surfaceVariant; - color: $onSurfaceVariant; - font-size: 3rem; -} - -.session-button-focused { - background-color: $secondaryContainer; - color: $onSecondaryContainer; -} - -.session-button-desc { - background-color: mix($surface, $surfaceVariant, 50%); - color: mix($onSurface, $onSurfaceVariant, 50%); - border-bottom-left-radius: $rounding_large; - border-bottom-right-radius: $rounding_large; - padding: 0.205rem 0.341rem; - font-weight: 700; -} - -.session-button-cancel { - @include large-rounding; - min-width: 8.182rem; - min-height: 5.455rem; - background-color: $surfaceVariant; - color: $onSurfaceVariant; - font-size: 3rem; -} diff --git a/home/desktops/hyprland/ags/scss/_sidebars.scss b/home/desktops/hyprland/ags/scss/_sidebars.scss deleted file mode 100644 index 8f165f6..0000000 --- a/home/desktops/hyprland/ags/scss/_sidebars.scss +++ /dev/null @@ -1,389 +0,0 @@ -// sideleft sideright stuff - -.sidebar-right { - @include md3_decel; - @include large-rounding; - @include elevation-border; - @include elevation2; - // min-width: 29.591rem; - // min-height: 29.591rem; - background-color: $t_background; - padding: 1.023rem; -} - -.sideright-show { - @include md3_decel; -} - -.sideright-hide { - margin-right: -30.682rem; - // opacity: 0; - @include md3_accel; -} - -.sidebar-left { - @include md3_decel; - @include large-rounding; - @include elevation-border; - @include elevation2; - // min-width: 29.591rem; // COMMENT THIS LATER IF TEXT WRAP IS USED - // min-height: 29.591rem; - background-color: $t_background; - padding: 1.023rem; -} - -.sideleft-show { - @include md3_decel; -} - -.sideleft-hide { - margin-left: -30.682rem; - // opacity: 0; - @include md3_accel; -} - -.sidebar-group { - @include normal-rounding; - // @include elevation-border; - @include group-padding; - background-color: $t_surface; -} - -.sidebar-group-nopad { - @include normal-rounding; - // @include elevation-border; - background-color: $t_surface; -} - -.sidebar-group-invisible { - @include group-padding; -} - -.sidebar-group-invisible-morehorizpad { - padding: 0.341rem 0.682rem; -} - -.sidebar-iconbutton { - @include full-rounding; - @include md3_decel; - color: $onSurface; - min-width: 2.727rem; - min-height: 2.727rem; -} - -.sidebar-iconbutton:hover { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 80%); -} - -.sidebar-iconbutton:active { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 60%); -} - -.sidebar-button { - @include md3_decel; - padding: 0rem $rounding_small; - background-color: $t_secondaryContainer; - color: $onSecondaryContainer; -} - -.sidebar-button-nopad { - @include md3_decel; - background-color: $t_secondaryContainer; - color: $onSecondaryContainer; -} - -.sidebar-button:hover { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 80%); -} - -.sidebar-button:active { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 60%); -} - -.sidebar-button-nopad:hover { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 80%); -} - -.sidebar-button-nopad:active { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 60%); -} - -.sidebar-button-left { - border-top-left-radius: $rounding_small; - border-bottom-left-radius: $rounding_small; -} - -.sidebar-button-right { - border-top-right-radius: $rounding_small; - border-bottom-right-radius: $rounding_mediumsmall; -} - -.sidebar-button-alone { - @include small-rounding; -} - -.sidebar-button-alone-normal { - @include small-rounding; -} - -.sidebar-button-active { - background-color: $primary; - color: $onPrimary; -} - -.sidebar-button-active:hover { - background-color: mix($primary, $hovercolor, 90%); -} - -.sidebar-button-active:active { - background-color: mix($primary, $hovercolor, 70%); -} - -.sidebar-buttons-separator { - min-width: 0.068rem; - min-height: 0.068rem; - background-color: $onSurfaceVariant; -} - -.sidebar-navrail { - // background-color: $t_surface; - padding: 0rem $rounding_medium; -} - -.sidebar-navrail-btn>box>label { - @include full-rounding; - @include md3_decel; -} - -.sidebar-navrail-btn:hover>box>label:first-child { - background-color: mix($t_surfaceVariant, $onSurfaceVariant, 90%); -} - -.sidebar-navrail-btn:active>box>label:first-child { - background-color: mix($surfaceVariant, $onSurfaceVariant, 75%); -} - -.sidebar-navrail-btn-active>box>label:first-child { - background-color: $secondaryContainer; - color: $onSecondaryContainer; -} - -.sidebar-navrail-btn-active:hover>box>label:first-child { - background-color: mix($secondaryContainer, $hovercolor, 90%); - color: mix($onSecondaryContainer, $hovercolor, 90%); -} - -.sidebar-sysinfo-grouppad { - padding: 1.159rem; -} - -.sidebar-memory-ram-circprog { - @include fluent_decel_long; - min-width: $rounding_small; - min-height: 4.091rem; - padding: 0.409rem; - background-color: $secondaryContainer; - color: $onSecondaryContainer; - font-size: 0px; -} - -.sidebar-memory-swap-circprog { - @include fluent_decel_long; - min-width: $rounding_small; - min-height: 2.255rem; - padding: 0.409rem; - margin: 0.918rem; - background-color: $secondaryContainer; - color: $onSecondaryContainer; - font-size: 0px; -} - -.sidebar-cpu-circprog { - min-width: $rounding_small; - min-height: 3.409rem; - padding: 0.409rem; - background-color: $secondaryContainer; - color: $onSecondaryContainer; - @include fluent_decel_long; - font-size: 0px; -} - -// .sidebar-sysinfo-txt { -// font-size: 1.0909rem; -// @include techfont; -// } - -.sidebar-viewport { - @include small-rounding; -} - -.sidebar-scrollbar { - trough { - @include full-rounding; - min-width: 0.545rem; - background-color: transparent; - } - - slider { - @include full-rounding; - min-width: 0.273rem; - min-height: 2.045rem; - background-color: $t_onSurfaceVariant; - } - - slider:hover { - background-color: mix($t_onSurfaceVariant, $onSurfaceVariant, 80%); - } - - slider:active { - background-color: mix($onSurfaceVariant, $surfaceVariant, 50%); - } -} - -.sidebar-calendar-btn { - @include full-rounding; - @include md3_decel; - min-height: 2.523rem; - min-width: 2.523rem; - color: $onSurface; -} - -.sidebar-calendar-btn:hover { - background-color: $hovercolor; -} - -.sidebar-calendar-btn:active { - background-color: $activecolor; -} - -.sidebar-calendar-btn-txt { - margin-left: -10.341rem; - margin-right: -10.341rem; -} - -.sidebar-calendar-btn-today { - background-color: $primary; - color: $onPrimary; -} - -.sidebar-calendar-btn-today:hover { - background-color: mix($primary, $hovercolor, 90%); -} - -.sidebar-calendar-btn-today:active { - background-color: mix($primary, $hovercolor, 70%); -} - -.sidebar-calendar-btn-othermonth { - color: mix($onSurface, $surface, 50%); -} - -.sidebar-calendar-header { - margin: 0.341rem; -} - -.sidebar-calendar-monthyear-btn { - @include full-rounding; - padding: 0rem 0.682rem; - background-color: $t_surfaceVariant; - color: $onSurfaceVariant; -} - -.sidebar-calendar-monthyear-btn:hover { - background-color: mix($t_surfaceVariant, $onSurfaceVariant, 95%); - color: mix($onSurfaceVariant, $surfaceVariant, 95%); -} - -.sidebar-calendar-monthyear-btn:active { - background-color: mix($surfaceVariant, $onSurfaceVariant, 85%); - color: mix($onSurfaceVariant, $surfaceVariant, 85%); -} - -.sidebar-calendar-monthshift-btn { - @include full-rounding; - min-width: 2.045rem; - min-height: 2.045rem; - background-color: $t_surfaceVariant; - color: $onSurfaceVariant; -} - -.sidebar-calendar-monthshift-btn:hover { - background-color: mix($t_surfaceVariant, $onSurfaceVariant, 95%); - color: mix($onSurfaceVariant, $surfaceVariant, 95%); -} - -.sidebar-calendar-monthshift-btn:active { - background-color: mix($surfaceVariant, $onSurfaceVariant, 85%); - color: mix($onSurfaceVariant, $surfaceVariant, 85%); -} - -.sidebar-todo-selector-tab { - @include small-rounding; - transition: 0ms; - min-height: 2.5rem; - color: $onSurface; -} - -.sidebar-todo-selector-tab:hover { - background-color: mix($t_surfaceVariant, $onSurfaceVariant, 90%); -} - -.sidebar-todo-selector-tab:active { - background-color: mix($surfaceVariant, $onSurfaceVariant, 75%); -} - -.sidebar-todo-selector-tab-active>box>label { - color: $primary; -} - -.sidebar-todo-selector-highlight-offset { - margin-top: -0.205rem; - margin-bottom: 0.205rem; -} - -.sidebar-todo-selector-highlight { - transition: 180ms ease-in-out; // Doesn't look that good, but it syncs with GtkStack animation of the actual todo widget content - color: $primary; - padding: 0rem 2.045rem; - min-height: 0.205rem; -} - -.sidebar-todo-item-action { - border-radius: 9999px; - min-width: 1.705rem; - min-height: 1.705rem; -} - -.sidebar-todo-item-action:hover { - background-color: mix($t_surface, $t_onSurface, 95%); -} - -.sidebar-todo-item-action:active { - background-color: mix($t_surface, $t_onSurface, 85%); -} - -.sidebar-clipboard-item { - border-radius: $rounding_small; - min-height: 2.045rem; - padding: 0.341rem; - background-color: $t_secondaryContainer; - color: $onSecondaryContainer; -} - -.sidebar-clipboard-item:hover { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 90%); -} - -.sidebar-clipboard-item:active { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 80%); -} - -// cool gradient background from amberol -// .main-window { -// background: linear-gradient(127deg, alpha(@background_color_0, .55), alpha(@background_color_0, 0) 70.71%), -// linear-gradient(217deg, alpha(@background_color_1, .55), alpha(@background_color_1, 0) 70.71%), -// linear-gradient(336deg, alpha(@background_color_2, .55), alpha(@background_color_2, 0) 70.71%); -// transition-property: background; -// transition-duration: 250ms; -// transition-timing-function: ease; -// } \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scss/common/a11y-button.scss b/home/desktops/hyprland/ags/scss/common/a11y-button.scss new file mode 100644 index 0000000..7f3213d --- /dev/null +++ b/home/desktops/hyprland/ags/scss/common/a11y-button.scss @@ -0,0 +1,45 @@ +@import "./button"; + +@mixin accs-button($flat: false, $reactive: true) { + @include button($flat: true, $reactive: false, $focusable: false); + color: $fg-color; + + > * { + border-radius: $radii; + transition: $transition; + + @if $flat { + background-color: transparent; + box-shadow: none; + } @else { + background-color: $widget-bg; + box-shadow: inset 0 0 0 $border-width $border-color; + } + } + + @if $reactive { + &:focus > *, + &.focused > * { + @include button-focus; + } + + &:hover > * { + @include button-hover; + } + + &:active, + &.active, + &.on, + &:checked { + > * { + @include button-active; + } + + &:hover > * { + box-shadow: + inset 0 0 0 $border-width $border-color, + inset 0 0 0 99px $hover; + } + } + } +} diff --git a/home/desktops/hyprland/ags/scss/common/button.scss b/home/desktops/hyprland/ags/scss/common/button.scss new file mode 100644 index 0000000..5521486 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/common/button.scss @@ -0,0 +1,69 @@ +@mixin button-focus() { + box-shadow: inset 0 0 0 $border-width $accent; + background-color: $hover; + color: $hover-fg; +} + +@mixin button-hover() { + box-shadow: inset 0 0 0 $border-width $border-color; + background-color: $hover; + color: $hover-fg; +} + +@mixin button-active() { + box-shadow: inset 0 0 0 $border-width $border-color; + background-image: $active-gradient; + background-color: $accent; + color: $accent-fg; +} + +@mixin button-disabled() { + box-shadow: none; + background-color: transparent; + color: transparentize($fg-color, 0.7); +} + +@mixin button($flat: false, $reactive: true, $radii: $radii, $focusable: true) { + all: unset; + transition: $transition; + border-radius: $radii; + color: $fg-color; + + @if $flat { + background-color: transparent; + background-image: none; + box-shadow: none; + } @else { + background-color: $widget-bg; + box-shadow: inset 0 0 0 $border-width $border-color; + } + + @if $reactive { + @if $focusable { + &:focus { + @include button-focus; + } + } + + &:hover { + @include button-hover; + } + + &:active, + &.on, + &.active, + &:checked { + @include button-active; + + &:hover { + box-shadow: + inset 0 0 0 $border-width $border-color, + inset 0 0 0 99px $hover; + } + } + } + + &:disabled { + @include button-disabled; + } +} diff --git a/home/desktops/hyprland/ags/scss/common/floating-widget.scss b/home/desktops/hyprland/ags/scss/common/floating-widget.scss new file mode 100644 index 0000000..d1d5ede --- /dev/null +++ b/home/desktops/hyprland/ags/scss/common/floating-widget.scss @@ -0,0 +1,12 @@ +@mixin floating-widget { + @if $drop-shadow { + box-shadow: 0 0 5px 0 $shadow; + } + + margin: max($spacing, 8px); + border: $border-width solid $popover-border-color; + background-color: $bg-color; + color: $fg-color; + border-radius: $popover-radius; + padding: $popover-padding; +} diff --git a/home/desktops/hyprland/ags/scss/common/hidden.scss b/home/desktops/hyprland/ags/scss/common/hidden.scss new file mode 100644 index 0000000..fc0f404 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/common/hidden.scss @@ -0,0 +1,15 @@ +@mixin hidden { + background-color: transparent; + background-image: none; + border-color: transparent; + box-shadow: none; + -gtk-icon-transform: scale(0); + + * { + background-color: transparent; + background-image: none; + border-color: transparent; + box-shadow: none; + -gtk-icon-transform: scale(0); + } +} diff --git a/home/desktops/hyprland/ags/scss/common/menu.scss b/home/desktops/hyprland/ags/scss/common/menu.scss new file mode 100644 index 0000000..4622c9f --- /dev/null +++ b/home/desktops/hyprland/ags/scss/common/menu.scss @@ -0,0 +1,29 @@ +window.popup { + > * { + border: none; + box-shadow: none; + } + + menu { + border-radius: $popover-radius; + background-color: $bg-color; + padding: $popover-padding; + border: $border-width solid $popover-border-color; + + separator { + background-color: $border-color; + } + + menuitem { + @include button; + padding: $spacing/2; + margin: $spacing/2 0; + &:first-child { + margin-top: 0; + } + &:last-child { + margin-bottom: 0; + } + } + } +} diff --git a/home/desktops/hyprland/ags/scss/common/scrollable.scss b/home/desktops/hyprland/ags/scss/common/scrollable.scss new file mode 100644 index 0000000..35be0c8 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/common/scrollable.scss @@ -0,0 +1,28 @@ +@mixin scrollable { + scrollbar, + scrollbar * { + all: unset; + } + + scrollbar.vertical { + transition: $transition; + background-color: transparentize($bg-color, 0.7); + + &:hover { + background-color: transparentize($bg-color, 0.3); + + slider { + background-color: transparentize($fg-color, 0.3); + min-width: 0.6em; + } + } + } + + scrollbar.vertical slider { + background-color: transparentize($fg-color, 0.5); + border-radius: $radii; + min-width: 0.4em; + min-height: 2em; + transition: $transition; + } +} diff --git a/home/desktops/hyprland/ags/scss/common/slider.scss b/home/desktops/hyprland/ags/scss/common/slider.scss new file mode 100644 index 0000000..fb2bfa5 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/common/slider.scss @@ -0,0 +1,79 @@ +@import "./unset"; + +@mixin slider( + $width: 0.7em, + $slider-width: 0.5em, + $gradient: $active-gradient, + $slider: true, + $focusable: true, + $radii: $radii +) { + @include unset($rec: true); + + trough { + transition: $transition; + border-radius: $radii; + border: $border; + background-color: $widget-bg; + min-height: $width; + min-width: $width; + + highlight, + progress { + border-radius: max($radii - $border-width, 0); + background-image: $gradient; + min-height: $width; + min-width: $width; + } + } + + slider { + box-shadow: none; + background-color: transparent; + border: $border-width solid transparent; + transition: $transition; + border-radius: $radii; + min-height: $width; + min-width: $width; + margin: -$slider-width; + } + + &:hover { + trough { + background-color: $hover; + } + + slider { + @if $slider { + background-color: $fg-color; + border-color: $border-color; + + @if $drop-shadow { + box-shadow: 0 0 3px 0 $shadow; + } + } + } + } + + &:disabled { + highlight, + progress { + background-color: transparentize($fg-color, 0.4); + background-image: none; + } + } + + @if $focusable { + trough:focus { + background-color: $hover; + box-shadow: inset 0 0 0 $border-width $accent; + + slider { + @if $slider { + background-color: $fg-color; + box-shadow: inset 0 0 0 $border-width $accent; + } + } + } + } +} diff --git a/home/desktops/hyprland/ags/scss/common/spacing.scss b/home/desktops/hyprland/ags/scss/common/spacing.scss new file mode 100644 index 0000000..ae7737d --- /dev/null +++ b/home/desktops/hyprland/ags/scss/common/spacing.scss @@ -0,0 +1,45 @@ +@mixin spacing($multiplier: 1, $spacing: $spacing, $rec: false) { + &.horizontal > * { + margin: 0 $spacing * $multiplier / 2; + &:first-child { + margin-left: 0; + } + &:last-child { + margin-right: 0; + } + } + + &.vertical > * { + margin: $spacing * $multiplier / 2 0; + &:first-child { + margin-top: 0; + } + &:last-child { + margin-bottom: 0; + } + } + + @if $rec { + box { + &.horizontal > * { + margin: 0 $spacing * $multiplier / 2; + &:first-child { + margin-left: 0; + } + &:last-child { + margin-right: 0; + } + } + + &.vertical > * { + margin: $spacing * $multiplier / 2 0; + &:first-child { + margin-top: 0; + } + &:last-child { + margin-bottom: 0; + } + } + } + } +} diff --git a/home/desktops/hyprland/ags/scss/common/switch.scss b/home/desktops/hyprland/ags/scss/common/switch.scss new file mode 100644 index 0000000..27082e5 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/common/switch.scss @@ -0,0 +1,16 @@ +@import "./button"; + +@mixin switch { + @include button; + + slider { + background-color: $accent-fg; + border-radius: $radii; + min-width: 24px; + min-height: 24px; + } + + image { + color: transparent; + } +} diff --git a/home/desktops/hyprland/ags/scss/common/text-border.scss b/home/desktops/hyprland/ags/scss/common/text-border.scss new file mode 100644 index 0000000..fbfd156 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/common/text-border.scss @@ -0,0 +1,13 @@ +@mixin text-border { + text-shadow: + -1 * $border-width -1 * $border-width 0 $border-color, + $border-width $border-width 0 $border-color, + -1 * $border-width $border-width 0 $border-color, + $border-width -1 * $border-width 0 $border-color; + + -gtk-icon-shadow: + -1 * $border-width -1 * $border-width 0 $border-color, + $border-width $border-width 0 $border-color, + -1 * $border-width $border-width 0 $border-color, + $border-width -1 * $border-width 0 $border-color; +} diff --git a/home/desktops/hyprland/ags/scss/common/tooltip.scss b/home/desktops/hyprland/ags/scss/common/tooltip.scss new file mode 100644 index 0000000..b19aff2 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/common/tooltip.scss @@ -0,0 +1,18 @@ +tooltip { + * { + all: unset; + } + + background-color: transparent; + border: none; + + > * > * { + background-color: $bg-color; + border-radius: $radii; + border: $border-width solid $popover-border-color; + color: $fg-color; + padding: 8px; + margin: 4px; + box-shadow: 0 0 3px 0 $shadow; + } +} diff --git a/home/desktops/hyprland/ags/scss/common/unset.scss b/home/desktops/hyprland/ags/scss/common/unset.scss new file mode 100644 index 0000000..1dce620 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/common/unset.scss @@ -0,0 +1,9 @@ +@mixin unset($rec: false) { + all: unset; + + @if $rec { + * { + all: unset; + } + } +} diff --git a/home/desktops/hyprland/ags/scss/common/widget.scss b/home/desktops/hyprland/ags/scss/common/widget.scss new file mode 100644 index 0000000..b3d9694 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/common/widget.scss @@ -0,0 +1,7 @@ +@mixin widget { + transition: $transition; + border-radius: $radii; + color: $fg-color; + background-color: $widget-bg; + border: $border; +} diff --git a/home/desktops/hyprland/ags/scss/main.scss b/home/desktops/hyprland/ags/scss/main.scss index d16a772..5e491c0 100644 --- a/home/desktops/hyprland/ags/scss/main.scss +++ b/home/desktops/hyprland/ags/scss/main.scss @@ -1,28 +1,36 @@ -// Reset -* { - all: unset; -} +@import "/tmp/ags/scss/options"; +@import "./variables"; -// Colors -@import './material'; // Material colors -@import './colors'; // Global color definitions. Uses material colors as base. -@import './lib'; // Global mixins and functions -@import './common'; // Context menu n stuff +// common +@import "./common/unset"; +@import "./common/widget"; +@import "./common/button"; +@import "./common/a11y-button"; +@import "./common/floating-widget"; +@import "./common/slider"; +@import "./common/scrollable"; +@import "./common/switch"; +@import "./common/hidden"; +@import "./common/text-border"; +@import "./common/tooltip"; +@import "./common/menu"; +@import "./common/spacing"; -// Components -@import './bar'; -@import './cheatsheet'; -@import './sidebars'; -@import './osd'; -@import './overview'; -@import './osk'; -@import './session'; -@import './notifications'; +// widgets +@import "./widgets/about"; +@import "./widgets/applauncher"; +@import "./widgets/bar"; +@import "./widgets/desktop"; +@import "./widgets/notifications"; +@import "./widgets/overview"; +@import "./widgets/osd"; +@import "./widgets/dashboard"; +@import "./widgets/dock"; +@import "./widgets/powermenu"; +@import "./widgets/lockscreen"; +@import "./widgets/media"; +@import "./widgets/quicksettings"; +@import "./widgets/settings"; -// Classes for interaction -.growingRadial { - transition: 300ms cubic-bezier(0.2, 0.0, 0, 1.0); -} -.fadingRadial { - transition: 50ms cubic-bezier(0.2, 0.0, 0, 1.0); -} \ No newline at end of file +// additional overrides +@import "/tmp/ags/scss/additional"; diff --git a/home/desktops/hyprland/ags/scss/scss.js b/home/desktops/hyprland/ags/scss/scss.js deleted file mode 100644 index b627c0e..0000000 --- a/home/desktops/hyprland/ags/scss/scss.js +++ /dev/null @@ -1,30 +0,0 @@ -const { App, Service, Utils } = ags; -const { execAsync, CONFIG_DIR } = Utils; - -async function setupScss() { - try { - await execAsync(['sassc', `${CONFIG_DIR}/scss/main.scss`, `${CONFIG_DIR}/style.css`]); - App.resetCss(); - App.applyCss(`${CONFIG_DIR}/style.css`); - } catch (error) { - print(error); - } -} - -class ThemeService extends Service { - static { Service.register(this); } - - constructor() { - super(); - this.setup(); - } - - setup() { - setupScss(); - } -} - -var Theme = class Theme { - static { globalThis['Theme'] = this; } - static instance = new ThemeService(); -}; \ No newline at end of file diff --git a/home/desktops/hyprland/ags/scss/variables.scss b/home/desktops/hyprland/ags/scss/variables.scss new file mode 100644 index 0000000..578729b --- /dev/null +++ b/home/desktops/hyprland/ags/scss/variables.scss @@ -0,0 +1,32 @@ +// variables are defined in options.js +// these ones are derived from those + +$hover: transparentize($_widget-bg, ($widget-opacity * 0.9) / 100); +$widget-bg: transparentize($_widget-bg, $widget-opacity / 100); +$active-gradient: linear-gradient($accent-gradient); + +$hover-fg: if( + $color-scheme == "dark", + lighten($fg-color, 10%), + darken($fg-color, 8%) +); + +$border-color: transparentize($_border-color, $border-opacity / 100); +$border: $border-width solid $border-color; + +$text-shadow: 2px 2px 2px $shadow; + +$popover-border-color: transparentize( + $_border-color, + max(($border-opacity - 1) / 100, 0) +); +$popover-padding: $padding * $popover-padding-multiplier; +$popover-radius: if($radii == 0, 0, $radii + $popover-padding); + +$wm-gaps: floor($spacing * $wm-gaps-multiplier); + +$shader-fg: #fff; + +* { + font-size: $font-size; +} diff --git a/home/desktops/hyprland/ags/scss/widgets/about.scss b/home/desktops/hyprland/ags/scss/widgets/about.scss new file mode 100644 index 0000000..ae72356 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/widgets/about.scss @@ -0,0 +1,62 @@ +window#about { + @include unset; + + .window-content { + @include floating-widget; + min-width: 300px; + } + + .avatar { + min-width: 200px; + min-height: 200px; + background-size: cover; + border: $border; + margin: $spacing 0; + } + + .labels { + .title { + font-size: 1.2em; + } + + .author { + color: transparentize($fg-color, 0.2); + } + + .version { + margin-top: $spacing; + margin-bottom: $spacing * 2; + border-radius: $radii; + background-color: $widget-bg; + color: $accent; + padding: $padding; + } + } + + .buttons { + padding-bottom: $popover-padding; + + button { + @include button; + padding: $padding; + + &:first-child { + border-radius: $radii $radii 0 0; + } + + &:last-child { + border-radius: 0 0 $radii $radii; + } + } + } + + .dont-show { + @include button; + padding: $padding; + + image { + font-size: 1.4em; + color: $red; + } + } +} diff --git a/home/desktops/hyprland/ags/scss/widgets/applauncher.scss b/home/desktops/hyprland/ags/scss/widgets/applauncher.scss new file mode 100644 index 0000000..913adb7 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/widgets/applauncher.scss @@ -0,0 +1,71 @@ +window#applauncher .window-content { + @include floating_widget; + + entry { + @include button; + padding: $padding; + margin-bottom: $spacing; + + label, + image { + color: $fg-color; + } + } + + separator { + min-height: 1px; + background-color: $hover; + } + + scrolledwindow { + @include scrollable; + min-width: $applauncher-width; + min-height: $applauncher-height; + } + + button.app-item { + @include button($flat: true, $reactive: false); + > box { + @include spacing(0.5); + } + transition: $transition; + padding: $padding; + + label { + transition: $transition; + + &.title { + color: $fg-color; + } + + &.description { + color: transparentize($fg-color, 0.3); + } + } + + image { + transition: $transition; + } + + &:hover, + &:focus { + .title { + color: $accent; + } + + image { + -gtk-icon-shadow: 2px 2px $accent; + } + } + + &:active { + background-color: transparentize($accent, 0.5); + border-radius: $radii; + box-shadow: inset 0 0 0 $border-width $border-color; + + .title { + color: $fg-color; + } + } + } +} diff --git a/home/desktops/hyprland/ags/scss/widgets/bar.scss b/home/desktops/hyprland/ags/scss/widgets/bar.scss new file mode 100644 index 0000000..9506a90 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/widgets/bar.scss @@ -0,0 +1,283 @@ +$bar-spacing: $spacing / 2; +$button-radius: if( + $bar-style == "floating", + max(0, $radii - $bar-spacing), + $radii +); + +@mixin panel-button($flat: $bar-flat-buttons, $reactive: true) { + @include unset; + + @if $bar-style == "separated" { + transition: $transition; + + > * { + @include floating-widget; + border-radius: $radii; + margin: $wm-gaps $bar-spacing; + transition: $transition; + } + + &:hover > * { + color: $hover-fg; + + @if $drop-shadow { + box-shadow: + 0 0 min(6px, $spacing/2) 0 $shadow, + inset 0 0 0 99px $hover; + } @else { + box-shadow: inset 0 0 0 99px $hover; + } + } + + &:active > *, + &.active > * { + label, + image { + color: $accent-fg; + } + background-image: $active-gradient; + background-color: $accent; + } + } @else { + @include accs-button($flat, $reactive); + + > * { + border-radius: $button-radius; + margin: $bar-spacing; + } + } + + label, + image { + font-weight: bold; + } + + > * { + padding: $padding * 0.4 $padding * 0.8; + } +} + +.panel { + @if $bar-style == "normal" { + background-color: $bg-color; + } + + @if not $screen-corners and $bar-style == "normal" { + @if $bar-position == "bottom" { + border-top: $border; + } @else { + border-bottom: $border; + } + } + + @if $bar-style == "floating" { + @include floating-widget; + border-radius: $radii; + margin: $wm-gaps; + padding: 0; + } + + @if $bar-style == "separated" { + > .end > button:last-child > * { + margin-right: $wm-gaps; + } + + > .start > button:first-child > * { + margin-left: $wm-gaps; + } + } + + .panel-button { + @include panel-button; + } + + .tray-item, + .color-picker { + @include panel-button($flat: true); + } + + separator { + background-color: transparentize($fg-color, 0.86); + border-radius: $radii; + min-height: 5px; + min-width: 5px; + } + + .overview { + label { + color: transparentize($accent, 0.2); + } + &:hover label { + color: $accent; + } + &:active label, + &.active label { + color: $accent-fg; + } + } + + .powermenu, + .recorder { + image { + color: transparentize($red, 0.3); + } + &:hover image { + color: transparentize($red, 0.15); + } + &:active image { + color: $red; + } + } + + .focused-client > box > box, + .quicksettings > box > box { + @include spacing( + $spacing: if($bar-spacing == 0, $padding / 2, $bar-spacing) + ); + } + + /* stylelint-disable-next-line selector-not-notation */ + .quicksettings:not(.active):not(:active) { + .bluetooth { + color: $blue; + } + + .battery { + &.low { + color: $red; + } + &.charged, + &.charging { + color: $green; + } + } + } + + .media { + &.spotify image { + color: $green; + } + &.firefox image { + color: $orange; + } + &.mpv image { + color: $magenta; + } + } + + .notifications { + image { + color: $yellow; + } + } + + .battery-bar { + .font-icon { + font-size: 1.15em; + } + + @if $battery-bar-full { + > box { + padding: 0; + } + } + + image, + .font-icon { + margin-right: $bar-spacing * 0.5; + } + + levelbar trough { + @include widget; + min-width: $battery-bar-width; + min-height: $battery-bar-height; + + block.filled { + border-radius: max($radii - $border-width, 0); + background-image: $active-gradient; + } + } + + @mixin color($color) { + image, + label { + color: $color; + } + + block.filled { + background-image: linear-gradient( + to right, + $color, + lighten($color, 6%) + ); + } + } + + .medium { + @include color($yellow); + } + .low { + @include color($red); + } + .charging { + @include color($green); + } + &:active { + @include color($accent-fg); + } + + .whole-button { + label { + color: $fg-color; + text-shadow: $text-shadow; + } + + trough, + block.filled { + border-radius: $button-radius; + } + + @if $bar-style == "separated" { + trough { + border: none; + } + } + } + } + + .workspaces button { + all: unset; + + .indicator { + font-size: 0; + min-width: 8px; + min-height: 8px; + border-radius: $radii * 0.6; + box-shadow: inset 0 0 0 $border-width $border-color; + margin: 0 $padding/2; + transition: $transition/2; + background-color: transparentize($fg-color, 0.8); + } + + &.occupied .indicator { + background-color: transparentize($fg-color, 0.2); + min-width: 10px; + min-height: 10px; + } + + &:hover .indicator { + box-shadow: inset 0 0 0 10px transparentize($fg-color, 0.8); + } + + &.active .indicator, + &:active .indicator { + background-color: $accent; + } + + &.active .indicator { + min-width: 24px; + min-height: 16px; + } + } +} diff --git a/home/desktops/hyprland/ags/scss/widgets/dashboard.scss b/home/desktops/hyprland/ags/scss/widgets/dashboard.scss new file mode 100644 index 0000000..f979626 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/widgets/dashboard.scss @@ -0,0 +1,131 @@ +@mixin calendar { + @include widget; + padding: $padding * 2 $padding * 2 0; + + calendar { + all: unset; + + &.button { + @include button($flat: true); + } + + &:selected { + box-shadow: + inset 0 -8px 0 0 transparentize($accent, 0.5), + inset 0 0 0 1px $accent; + border-radius: $radii * 0.6; + } + + &.header { + background-color: transparent; + border: none; + color: transparentize($fg-color, 0.5); + } + + &.highlight { + background-color: transparent; + color: transparentize($accent, 0.5); + } + + &:indeterminate { + color: transparentize($fg-color, 0.9); + } + font-size: 1.1em; + padding: 0.2em; + } +} + +window#dashboard .window-content { + @include floating-widget; + + .notifications { + min-width: $notifications-width; + + .header { + margin-bottom: $spacing; + margin-right: $spacing; + + > label { + margin-left: $radii / 2; + } + + button { + @include button; + padding: $padding/2 $padding; + } + } + + .notification-scrollable { + @include scrollable; + } + + .notification-list { + margin-right: $spacing; + } + + .notification { + @include notification; + + > box { + @include widget; + padding: $padding; + margin-bottom: $spacing; + } + } + + .placeholder { + image { + font-size: 7em; + } + label { + font-size: 1.2em; + } + } + } + + separator { + background-color: $popover-border-color; + min-width: 2px; + border-radius: $radii; + margin-right: $spacing; + } + + .datemenu, + .system-info { + @include spacing; + } + + .clock-box { + padding: $padding; + + .clock { + font-size: 5em; + } + + .uptime { + color: transparentize($fg-color, 0.2); + } + } + + .calendar { + @include calendar; + } + + .circular-progress-box { + @include widget; + padding: $padding; + + .circular-progress { + min-height: $sys-info-size; + min-width: $sys-info-size; + margin: $padding/2; + font-size: $padding; + background-color: $bg-color; + color: $accent; + + image { + font-size: 1.8em; + } + } + } +} diff --git a/home/desktops/hyprland/ags/scss/widgets/desktop.scss b/home/desktops/hyprland/ags/scss/widgets/desktop.scss new file mode 100644 index 0000000..4f3197c --- /dev/null +++ b/home/desktops/hyprland/ags/scss/widgets/desktop.scss @@ -0,0 +1,81 @@ +window.corner .corner { + background-color: $bg-color; + border-radius: $radii * 2; + min-width: 2px; + min-height: 2px; +} + +window.desktop { + @if $bar-style == "normal" { + border-radius: if($screen-corners, $radii * 2, 0); + box-shadow: inset 0 0 $wm-gaps / 2 0 $shadow; + } + + .clock-box-shadow { + border: 5px solid $wallpaper-fg; + border-radius: $radii; + + .clock-box { + border-radius: max($radii - 5px, 0); + padding: 0 14px; + + .clock { + color: $wallpaper-fg; + font-size: 140px; + font-family: $mono-font; + } + + .separator-box { + padding: 24px 12px; + + separator { + border-radius: $radii; + min-width: 16px; + min-height: 16px; + background-color: $wallpaper-fg; + } + } + } + } + + .date { + color: $wallpaper-fg; + font-size: 48px; + } + + @if $drop-shadow { + .clock-box-shadow, + separator { + box-shadow: 2px 2px 2px 0 $shadow; + } + + .clock-box { + box-shadow: inset 2px 2px 2px 0 $shadow; + } + + label { + text-shadow: $text-shadow; + } + } @else { + .clock-box-shadow { + box-shadow: + 0 0 0 $border-width $border-color, + inset 0 0 0 $border-width $border-color; + } + + separator { + border: $border; + } + + label { + @include text-border; + } + } +} + +.desktop-menu { + image { + margin-left: -14px; + margin-right: 6px; + } +} diff --git a/home/desktops/hyprland/ags/scss/widgets/dock.scss b/home/desktops/hyprland/ags/scss/widgets/dock.scss new file mode 100644 index 0000000..98e2778 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/widgets/dock.scss @@ -0,0 +1,44 @@ +@mixin dock($spacing: $spacing * 0.7) { + separator { + border-radius: $radii; + background-color: transparentize($fg-color, 0.8); + margin: 0 $spacing; + min-width: 2px; + min-height: 2em; + } + + button { + @include accs-button($flat: true); + + .box { + margin: $spacing / 2; + } + + image { + margin: $padding; + + @if $color-scheme == "light" { + -gtk-icon-shadow: $text-shadow; + } + } + + .indicator { + min-width: 8px; + min-height: 8px; + background-color: $fg-color; + border-radius: $radii; + margin-bottom: $padding/2; + + &.focused { + background-image: $active-gradient; + } + } + } +} + +window.floating-dock .dock { + @include dock; + @include floating-widget; + border-radius: if($radii == 0, 0, $radii + $spacing / 2); + padding: $spacing / 2; +} diff --git a/home/desktops/hyprland/ags/scss/widgets/lockscreen.scss b/home/desktops/hyprland/ags/scss/widgets/lockscreen.scss new file mode 100644 index 0000000..010a69f --- /dev/null +++ b/home/desktops/hyprland/ags/scss/widgets/lockscreen.scss @@ -0,0 +1,26 @@ +window.lockscreen { + background-color: rgba(0, 0, 0, 0.25); + + .avatar { + @include widget; + border-radius: $radii * 2; + min-height: 200px; + min-width: 200px; + } + + .content { + @include floating-widget; + padding: $spacing * 4; + } + + spinner { + margin-top: $spacing * 2; + } + + entry { + @include button; + margin-top: $spacing * 2; + padding: $spacing; + min-height: 20px; + } +} diff --git a/home/desktops/hyprland/ags/scss/widgets/media.scss b/home/desktops/hyprland/ags/scss/widgets/media.scss new file mode 100644 index 0000000..a773f9b --- /dev/null +++ b/home/desktops/hyprland/ags/scss/widgets/media.scss @@ -0,0 +1,120 @@ +@mixin player-color($color) { + button { + .shuffle.enabled { + color: $color; + } + + .loop { + &.playlist, + &.track { + color: $color; + } + } + + &:active label { + color: $color; + } + } + + .position-slider:hover trough { + background-color: transparentize($color, 0.5); + } + + .player-icon { + color: $color; + } +} + +@mixin media() { + @include widget; + + label { + color: $shader-fg; + text-shadow: $text-shadow; + } + + .blurred-cover, + .cover { + background-size: cover; + background-position: center; + border-radius: $radii * 0.8; + opacity: 0.8; + } + + .cover { + min-height: 100px; + min-width: 100px; + box-shadow: 2px 2px 2px 0 $shadow; + margin: $padding; + opacity: 0.9; + } + + .labels { + margin-top: $padding; + + label { + font-size: 1.1em; + text-shadow: $text-shadow; + + &.title { + font-weight: bold; + } + } + } + + .position-slider { + @include slider( + $width: 0.4em, + $slider: false, + $gradient: linear-gradient($shader-fg, $shader-fg), + $radii: 0 + ); + margin-bottom: $padding/2; + + trough { + border: none; + background-color: transparentize($shader-fg, 0.7); + } + } + + .footer-box { + margin: -$padding/2 $padding $padding/2; + + image { + -gtk-icon-shadow: $text-shadow; + } + } + + .controls button { + @include unset; + + label { + font-size: 2em; + color: transparentize($shader-fg, 0.2); + transition: $transition; + + &.shuffle, + &.loop { + font-size: 1.4em; + } + } + + &:hover label { + color: transparentize($shader-fg, 0.1); + } + + &:active label { + color: $shader-fg; + } + } + + &.spotify { + @include player-color($green); + } + &.firefox { + @include player-color($orange); + } + &.mpv { + @include player-color($magenta); + } +} diff --git a/home/desktops/hyprland/ags/scss/widgets/notifications.scss b/home/desktops/hyprland/ags/scss/widgets/notifications.scss new file mode 100644 index 0000000..7372cf2 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/widgets/notifications.scss @@ -0,0 +1,81 @@ +@mixin notification() { + &.critical > box { + box-shadow: inset 0 0 0.5em 0 $red; + } + + &:hover button.close-button { + @include button-hover; + background-color: transparentize($red, 0.5); + } + + .content { + .title { + margin-right: $spacing; + color: $fg-color; + font-size: 1.1em; + } + + .time { + color: transparentize($fg-color, 0.2); + } + + .description { + font-size: 0.9em; + color: transparentize($fg-color, 0.2); + } + + .icon { + border-radius: $radii * 0.8; + margin-right: $spacing; + + &.img { + border: $border; + } + } + } + + box.actions { + @include spacing(0.5); + margin-top: $spacing; + + button { + @include button; + border-radius: $radii * 0.8; + font-size: 1.2em; + padding: $padding * 0.7; + } + } + + button.close-button { + @include button($flat: true); + margin-left: $spacing / 2; + border-radius: $radii * 0.8; + min-width: 1.2em; + min-height: 1.2em; + + &:hover { + background-color: transparentize($red, 0.2); + } + + &:active { + background-image: linear-gradient($red, $red); + } + } +} + +window.notifications { + @include unset; + + .notification { + @include notification; + + > box { + @include floating-widget; + border-radius: $radii; + } + + .description { + min-width: 350px; + } + } +} diff --git a/home/desktops/hyprland/ags/scss/widgets/osd.scss b/home/desktops/hyprland/ags/scss/widgets/osd.scss new file mode 100644 index 0000000..ba815bf --- /dev/null +++ b/home/desktops/hyprland/ags/scss/widgets/osd.scss @@ -0,0 +1,19 @@ +window.indicator .progress { + @include floating-widget; + padding: $padding / 2; + border-radius: if($radii == 0, 0, $radii + $padding / 2); + + .fill { + border-radius: $radii; + background-color: $accent; + color: $accent-fg; + + image { + -gtk-icon-transform: scale(0.7); + } + + .font-icon { + font-size: 34px; + } + } +} diff --git a/home/desktops/hyprland/ags/scss/widgets/overview.scss b/home/desktops/hyprland/ags/scss/widgets/overview.scss new file mode 100644 index 0000000..44569a5 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/widgets/overview.scss @@ -0,0 +1,30 @@ +window#overview .window-content { + @include floating-widget; + @include spacing; + + .workspace { + &.active > widget { + border-color: $accent; + } + + > widget { + @include widget; + border-radius: if($radii == 0, 0, $radii + $padding); + + &:drop(active) { + border-color: $accent; + } + } + } + + .client { + @include button; + border-radius: $radii; + margin: $padding; + + &.hidden { + @include hidden; + transition: 0; + } + } +} diff --git a/home/desktops/hyprland/ags/scss/widgets/powermenu.scss b/home/desktops/hyprland/ags/scss/widgets/powermenu.scss new file mode 100644 index 0000000..629a5fd --- /dev/null +++ b/home/desktops/hyprland/ags/scss/widgets/powermenu.scss @@ -0,0 +1,84 @@ +window#powermenu, +window#verification { + .shader { + background-color: rgba(0, 0, 0, 0.05); + } +} + +window#verification .window-content { + @include floating-widget; + min-width: 300px; + min-height: 100px; + + .text-box { + .title { + font-size: 1.6em; + } + + .desc { + color: transparentize($fg-color, 0.1); + font-size: 1.1em; + } + } + + .buttons { + @include spacing; + margin-top: $padding; + + button { + @include button; + font-size: 1.5em; + padding: $padding; + } + } +} + +window#powermenu .window-content { + @include floating-widget; + @include spacing(2); + padding: $popover-padding + $spacing * 1.5; + border-radius: if( + $radii == 0, + 0, + $popover-radius + ($popover-padding + $spacing * 1.5) + ); + + button { + @include unset; + + image { + @include button; + border-radius: $popover-radius; + min-width: 1.7em; + min-height: 1.7em; + font-size: 4em; + } + + label, + image { + color: transparentize($fg-color, 0.1); + } + + &:hover { + image { + @include button-hover; + } + label { + color: $fg-color; + } + } + &:focus image { + @include button-focus; + } + &:active image { + @include button-active; + } + + &:focus, + &:active { + label { + color: $accent; + } + } + } +} diff --git a/home/desktops/hyprland/ags/scss/widgets/quicksettings.scss b/home/desktops/hyprland/ags/scss/widgets/quicksettings.scss new file mode 100644 index 0000000..f7965f2 --- /dev/null +++ b/home/desktops/hyprland/ags/scss/widgets/quicksettings.scss @@ -0,0 +1,165 @@ +window#quicksettings .window-content { + @include floating-widget; + @include spacing; + + .avatar { + @include widget; + opacity: 0.9; + } + + .header { + @include spacing($rec: true); + + button, + .uptime, + .battery { + @include button; + padding: $padding; + font-weight: bold; + min-height: 20px; + min-width: 20px; + + image { + font-size: 1.2em; + } + } + + .battery { + @include spacing($multiplier: 0.5); + } + } + + .battery-progress { + label { + color: $accent-fg; + font-weight: bold; + } + + &.charging label { + font-size: $padding * 2; + } + + &.half label { + color: $fg-color; + } + + progressbar { + @include slider($width: $padding * 3.6); + } + + &.low progressbar { + @include slider( + $width: $padding * 3.6, + $gradient: linear-gradient(to right, $red, $red) + ); + } + } + + .sliders-box { + @include widget; + @include spacing($rec: true); + @include spacing(0); + padding: $padding; + + button { + @include button($flat: true); + padding: $padding / 2; + } + + scale { + @include slider; + margin-left: $spacing * -0.5; + } + + .menu { + margin: $spacing 0; + background-color: $bg-color; + border: $border-width solid $popover-border-color; + border-radius: $radii; + } + } + + .mixer-item { + scale { + @include slider($width: 7px); + } + image { + font-size: 1.2em; + } + } + + .row { + @include spacing($rec: true); + } + + .menu { + @include unset; + @include widget; + @include spacing($rec: true); + padding: $padding; + margin-top: $spacing; + + .title { + @include spacing(0.5); + } + + separator { + margin: 0 $radii / 2; + } + + button { + @include button($flat: true); + padding: $padding / 2; + } + + switch { + @include switch; + } + } + + .toggle-button { + @include button; + font-weight: bold; + + .label-box { + @include spacing(0.5); + } + + button { + @include button($flat: true); + padding: $padding; + + &:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + + &:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + } + + &.active { + background-color: $accent; + + label, + image { + color: $accent-fg; + } + } + } + + .simple-toggle { + @include button; + padding: $padding $padding * 1.1; + } + + .media { + @include spacing; + + .player { + @include media; + } + } +} diff --git a/home/desktops/hyprland/ags/scss/widgets/settings.scss b/home/desktops/hyprland/ags/scss/widgets/settings.scss new file mode 100644 index 0000000..3e8236b --- /dev/null +++ b/home/desktops/hyprland/ags/scss/widgets/settings.scss @@ -0,0 +1,143 @@ +window#settings-dialog { + background-color: $bg-color; + + .page { + @include scrollable; + } + + .page-content { + margin: $spacing; + } + + .sidebar-box { + @include spacing($rec: true); + background-color: $widget-bg; + border-right: $border; + padding: $spacing / 2; + + button { + @include button($flat: true); + padding: $padding / 2 $padding * 2; + } + + scrolledwindow { + @include scrollable; + } + } + + .sidebar-header { + background-color: $widget-bg; + border-right: $border; + border-bottom: $border; + padding: $spacing / 2; + + button { + @include button($flat: true); + padding: $padding / 2 $padding; + } + + button:last-child { + margin-left: $spacing / 2; + } + } + + .sidebar-footer { + background-color: $widget-bg; + border-right: $border; + border-top: $border; + padding: $spacing / 2; + + button { + @include button($flat: true); + padding: $padding / 2 $padding; + } + } + + entry.search { + @include button; + border-radius: 0; + padding: $padding; + } + + .row { + @include widget; + border-radius: 0; + border-bottom-width: 0; + padding: $padding; + transition: border-radius 0; + + &:last-child { + border-radius: 0 0 $radii $radii; + border-bottom-width: $border-width; + } + + &:first-child { + border-radius: $radii $radii 0 0; + } + + &:first-child:last-child { + border-radius: $radii; + } + + .overlay-padding { + min-height: $font-size * 3; + } + + &:hover { + background-color: $hover; + } + + entry, + button { + @include button; + padding: $padding; + } + + switch { + @include switch; + } + + spinbutton { + @include unset; + + entry { + border-radius: $radii 0 0 $radii; + } + + button { + border-radius: 0; + } + + button:last-child { + border-radius: 0 $radii $radii 0; + } + } + + .enum-setter { + label { + background-color: $widget-bg; + border-top: $border; + border-bottom: $border; + padding: 0 $padding; + } + + button:first-child { + border-radius: $radii 0 0 $radii; + } + + button:last-child { + border-radius: 0 $radii $radii 0; + } + } + } + + .id, + .note { + font-size: 0.8em; + color: transparentize($fg-color, $amount: 0.5); + } + + .id { + font-family: $mono-font; + } +} diff --git a/home/desktops/hyprland/ags/style.css b/home/desktops/hyprland/ags/style.css deleted file mode 100644 index aa77cab..0000000 --- a/home/desktops/hyprland/ags/style.css +++ /dev/null @@ -1,1536 +0,0 @@ -* { - all: unset; } - -.test { - background-image: linear-gradient(45deg, #F4D609 0%, #F4D609 10%, #212121 10%, #212121 20%, #F4D609 20%, #F4D609 30%, #212121 30%, #212121 40%, #F4D609 40%, #F4D609 50%, #212121 50%, #212121 60%, #F4D609 60%, #F4D609 70%, #212121 70%, #212121 80%, #F4D609 80%, #F4D609 90%, #212121 90%, #212121 100%); - background-repeat: repeat; } - -.test-size { - min-height: 3rem; - min-width: 3rem; } - -.txt-title { - font-family: 'Noto Sans', 'Gabarito', 'Lexend', sans-serif; - font-size: 2.045rem; } - -.txt-title-small { - font-family: 'Noto Sans', 'Gabarito', 'Lexend', sans-serif; - font-size: 1.364rem; } - -.techfont { - font-family: 'JetBrains Mono Nerd Font', 'JetBrains Mono NL', 'SpaceMono Nerd Font', monospace; } - -@keyframes flyin-top { - from { - margin-top: -2.795rem; } - to { - margin-top: 0rem; } } - -@keyframes flyin-bottom { - from { - margin-top: 4.841rem; - margin-bottom: -4.841rem; } - to { - margin-bottom: 0rem; - margin-top: 0rem; } } - -.no-anim { - transition: 0ms; } - -.txt { - color: #e1e3e3; } - -.txt-shadow { - text-shadow: 1px 2px 8px rgba(0, 0, 0, 0.69); - margin: 10px; } - -.txt-badonkers { - font-family: 'AR One Sans', 'Inter', 'Roboto', 'Noto Sans', sans-serif; - font-size: 3rem; } - -.txt-tiddies { - font-family: 'AR One Sans', 'Inter', 'Roboto', 'Noto Sans', sans-serif; - font-size: 2.7273rem; } - -.txt-hugeass { - font-family: 'AR One Sans', 'Inter', 'Roboto', 'Noto Sans', sans-serif; - font-size: 1.8182rem; } - -.txt-larger { - font-family: 'AR One Sans', 'Inter', 'Roboto', 'Noto Sans', sans-serif; - font-size: 1.6363rem; } - -.txt-large { - font-family: 'AR One Sans', 'Inter', 'Roboto', 'Noto Sans', sans-serif; - font-size: 1.4545rem; } - -.txt-norm { - font-family: 'AR One Sans', 'Inter', 'Roboto', 'Noto Sans', sans-serif; - font-size: 1.2727rem; } - -.txt-small { - font-family: 'AR One Sans', 'Inter', 'Roboto', 'Noto Sans', sans-serif; - font-size: 1.0909rem; } - -.txt-smallie { - font-family: 'AR One Sans', 'Inter', 'Roboto', 'Noto Sans', sans-serif; - font-size: 1rem; } - -.txt-smaller { - font-family: 'AR One Sans', 'Inter', 'Roboto', 'Noto Sans', sans-serif; - font-size: 0.9091rem; } - -.txt-smaller-offset { - margin-top: -0.136rem; } - -.txt-tiny { - font-family: 'AR One Sans', 'Inter', 'Roboto', 'Noto Sans', sans-serif; - font-size: 0.7273rem; } - -.txt-subtext { - color: #a5a7a8; } - -.txt-action { - color: #c3c5c5; } - -.txt-semibold { - font-weight: 500; } - -.txt-bold { - font-weight: bold; } - -.titlefont { - font-family: 'Noto Sans', 'Gabarito', 'Lexend', sans-serif; } - -.mainfont { - font-family: 'AR One Sans', 'Inter', 'Roboto', 'Noto Sans', sans-serif; } - -.icon-material { - font-family: 'Material Symbols Rounded', 'Material Symbols Outlined', 'Material Symbols Sharp'; } - -.separator-circle { - border-radius: 9999px; - -gtk-outline-radius: 9999px; - background-color: #e1e3e3; - margin: 0rem 0.682rem; - min-width: 0.545rem; - min-height: 0.545rem; } - -.spacing-v-15 > box { - margin-bottom: 1.023rem; } - -.spacing-v-15 > box:last-child { - margin-bottom: 0rem; } - -.spacing-v-15 > scrolledwindow { - margin-bottom: 1.023rem; } - -.spacing-v-15 > scrolledwindow:last-child { - margin-bottom: 0rem; } - -.spacing-v-15 > revealer { - margin-bottom: 1.023rem; } - -.spacing-v-15 > revealer:last-child { - margin-bottom: 0rem; } - -.spacing-v-15 > label { - margin-bottom: 1.023rem; } - -.spacing-v-15 > label:last-child { - margin-bottom: 0rem; } - -.spacing-h-15 > box { - margin-right: 1.023rem; } - -.spacing-h-15 > box:last-child { - margin-right: 0rem; } - -.spacing-h-15 > stack { - margin-right: 1.023rem; } - -.spacing-h-15 > stack:last-child { - margin-right: 0rem; } - -.spacing-h-15 > label { - margin-right: 1.023rem; } - -.spacing-h-15 > label:last-child { - margin-right: 0rem; } - -.spacing-h-15 > button { - margin-right: 1.023rem; } - -.spacing-h-15 > button:last-child { - margin-right: 0rem; } - -.spacing-v-5 > box { - margin-bottom: 0.341rem; } - -.spacing-v-5 > box:last-child { - margin-bottom: 0rem; } - -.spacing-v-5 > label { - margin-bottom: 0.341rem; } - -.spacing-v-5 > label:last-child { - margin-bottom: 0rem; } - -.spacing-v-5 > button { - margin-bottom: 0.341rem; } - -.spacing-v-5 > button:last-child { - margin-bottom: 0rem; } - -.spacing-v-5-revealer > revealer > box { - margin-bottom: 0.341rem; } - -.spacing-v-5-revealer > revealer:last-child > box { - margin-bottom: 0rem; } - -.spacing-h-5 > box { - margin-right: 0.341rem; } - -.spacing-h-5 > box:last-child { - margin-right: 0rem; } - -.spacing-h-5 > button { - margin-right: 0.341rem; } - -.spacing-h-5 > button:last-child { - margin-right: 0rem; } - -.spacing-h-5 > label { - margin-right: 0.341rem; } - -.spacing-h-5 > label:last-child { - margin-right: 0rem; } - -.spacing-h-5 > widget > box { - margin-right: 0.341rem; } - -.spacing-h-5 > widget:last-child > box { - margin-right: 0rem; } - -.spacing-h-5 > progressbar { - margin-right: 0.341rem; } - -.spacing-h-5 > progressbar:last-child { - margin-right: 0rem; } - -.spacing-h-5 > scrolledwindow { - margin-right: 0.341rem; } - -.spacing-h-5 > scrolledwindow:last-child { - margin-right: 0rem; } - -.spacing-h-5 > scrollbar { - margin-right: 0.341rem; } - -.spacing-h-5 > scrollbar:last-child { - margin-right: 0rem; } - -.spacing-v-minus5 > box { - margin-bottom: -0.341rem; } - -.spacing-v-minus5 > box:last-child { - margin-bottom: 0rem; } - -.spacing-v-minus5 > label { - margin-bottom: -0.341rem; } - -.spacing-v-minus5 > label:last-child { - margin-bottom: 0rem; } - -.spacing-h-10 > box { - margin-right: 0.682rem; } - -.spacing-h-10 > box:last-child { - margin-right: 0rem; } - -.spacing-h-10 > flowboxchild > button { - margin-right: 0.682rem; } - -.spacing-h-10 > flowboxchild:last-child > button { - margin-right: 0rem; } - -.spacing-h-10 > label { - margin-right: 0.682rem; } - -.spacing-h-10 > label:last-child { - margin-right: 0rem; } - -.spacing-h-10 > revealer { - margin-right: 0.682rem; } - -.spacing-h-10 > revealer:last-child { - margin-right: 0rem; } - -.spacing-h-10 > overlay { - margin-right: 0.682rem; } - -.spacing-h-10 > overlay:last-child { - margin-right: 0rem; } - -.spacing-h-10 > button { - margin-right: 0.682rem; } - -.spacing-h-10 > button:last-child { - margin-right: 0rem; } - -.spacing-h-10 > label { - margin-right: 0.682rem; } - -.spacing-h-10 > label:last-child { - margin-right: 0rem; } - -.spacing-h-10 > widget { - margin-right: 0.682rem; } - -.spacing-h-10 > widget:last-child { - margin-right: 0rem; } - -.spacing-h-10 > stack { - margin-right: 0.682rem; } - -.spacing-h-10 > stack:last-child { - margin-right: 0rem; } - -.spacing-v-10 > box { - margin-bottom: 0.682rem; } - -.spacing-v-10 > box:last-child { - margin-bottom: 0rem; } - -.spacing-v-10 > button { - margin-bottom: 0.682rem; } - -.spacing-v-10 > button:last-child { - margin-bottom: 0rem; } - -.anim-enter { - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); } - -.anim-exit { - transition: 150ms cubic-bezier(0.3, 0, 0.8, 0.15); } - -.button-minsize { - min-width: 2.727rem; - min-height: 2.727rem; } - -.group-padding { - padding: 0.341rem; } - -.margin-right-5 { - margin-right: 0.341rem; } - -.margin-left-5 { - margin-left: 0.341rem; } - -.margin-top-5 { - margin-top: 0.341rem; } - -.margin-bottom-5 { - margin-bottom: 0.341rem; } - -.margin-right-10 { - margin-right: 0.682rem; } - -.margin-left-10 { - margin-left: 0.682rem; } - -.margin-top-10 { - margin-top: 0.682rem; } - -.margin-bottom-10 { - margin-bottom: 0.682rem; } - -.invisible { - opacity: 0; - background-color: transparent; - color: transparent; } - -.spacing-h--5 > box { - margin-right: -0.341rem; } - -.spacing-h--5 > box:last-child { - margin-right: 0rem; } - -.spacing-v--5 > box { - margin-bottom: -0.341rem; } - -.spacing-v--5 > box:last-child { - margin-bottom: 0rem; } - -.spacing-h--20 > box { - margin-left: -1.364rem; } - -.spacing-h--20 > box:first-child { - margin-left: 0rem; } - -.instant { - transition: 0ms; } - -.md3_decel { - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); } - -.menu { - padding: 0.681rem; - background: #3f484a; - color: #bfc8ca; - border-radius: 1.159rem; - -gtk-outline-radius: 1.159rem; } - -.menubar > menuitem { - border-radius: 0.545rem; - -gtk-outline-radius: 0.545rem; - min-width: 13.636rem; - min-height: 2.727rem; } - -.menu > menuitem { - padding: 0.4em 1.5rem; - background: transparent; - transition: 0.2s ease background; - border-radius: 0.545rem; - -gtk-outline-radius: 0.545rem; } - -.menu > menuitem:hover { - background-color: #4c5557; } - -.separator-line { - background-color: #3f484a; - min-width: 0.068rem; - min-height: 0.068rem; } - -tooltip { - border-radius: 1.705rem; - -gtk-outline-radius: 1.705rem; - background-color: #3f484a; - color: #bfc8ca; - border: 1px solid #bfc8ca; } - -.bar-bg { - background-color: rgba(25, 28, 29, 0.4); - min-height: 2.727rem; } - -.bar-sidespace { - min-width: 1.5rem; } - -.bar-group-margin { - padding: 0.2rem; } - -.bar-group { - background-color: rgba(25, 28, 29, 0.3); } - -.bar-group-center { - border-bottom-left-radius: 1.364rem; - border-bottom-right-radius: 1.364rem; - background-color: black; } - -.corner-bar-group { - border-radius: 1.364rem; - border-width: 0.068rem; - background-color: black; } - -.bar-group-pad { - padding: 0rem 1.023rem; } - -.bar-group-pad-less { - padding: 0rem 0.681rem; } - -.bar-group-pad-system { - padding-left: 1.023rem; - padding-right: 0.547rem; } - -.bar-group-pad-music { - padding-right: 1.023rem; } - -.bar-group-pad-left { - padding-left: 1.364rem; - padding-right: 0.681rem; } - -.bar-group-pad-right { - padding-left: 0.681rem; - padding-right: 1.364rem; } - -.bar-group-pad-leftonly { - padding-left: 0.681rem; } - -.bar-group-pad-rightonly { - padding-right: 0.681rem; } - -.bar-group-standalone { - border-radius: 1.364rem; - -gtk-outline-radius: 1.364rem; } - -.bar-group-round { - border-radius: 10rem; - -gtk-outline-radius: 10rem; } - -.bar-group-middle { - border-radius: 0.477rem; - -gtk-outline-radius: 0.477rem; } - -.bar-group-left { - border-radius: 0.477rem; - -gtk-outline-radius: 0.477rem; - border-top-left-radius: 1.364rem; - border-bottom-left-radius: 1.364rem; } - -.bar-group-right { - border-radius: 0.477rem; - -gtk-outline-radius: 0.477rem; - border-top-right-radius: 1.364rem; - border-bottom-right-radius: 1.364rem; } - -.bar-separator { - border-radius: 9999px; - -gtk-outline-radius: 9999px; - min-width: 0.341rem; - min-height: 0.341rem; - background-color: rgba(45, 48, 49, 0.3); - margin: 0rem 0.341rem; } - -.bar-clock { - font-family: 'Noto Sans', 'Gabarito', 'Lexend', sans-serif; - font-size: 1.2727rem; - color: #e1e3e3; } - -.bar-date { - font-family: 'Noto Sans', 'Gabarito', 'Lexend', sans-serif; - font-size: 1rem; - color: #e1e3e3; } - -.bar-ws { - min-height: 1.636rem; - min-width: 1.772rem; - font-size: 1.091rem; - font-family: 'AR One Sans', 'Inter', 'Roboto', 'Noto Sans', sans-serif; - border-top: 0.068rem solid; - border-bottom: 0.068rem solid; - border-color: transparent; - color: white; } - -.bar-ws-active-box { - min-height: 1.636rem; - min-width: 1.772rem; - transition: 300ms cubic-bezier(0.05, 0.7, 0.1, 1); } - -.bar-ws-active { - min-height: 1.636rem; - min-width: 1.772rem; - font-size: 1.091rem; - border: 0.4rem solid black; - font-family: 'AR One Sans', 'Inter', 'Roboto', 'Noto Sans', sans-serif; - background-clip: content-box; - background-color: #334b4f; - color: #cde7ec; - border-radius: 999px; } - -.bar-ws-active-middledecor { - min-width: 0.682rem; - min-height: 0.682rem; - border-radius: 9999px; - background-color: black; - margin: 0rem 0.409rem; } - -.bar-ws-occupied { - background-color: #334b4f; - color: #cde7ec; - min-width: 1.772rem; - border-top: 0.068rem solid #cde7ec; - border-bottom: 0.068rem solid #cde7ec; } - -.bar-ws-occupied-left { - background-color: #334b4f; - color: #cde7ec; - min-width: 1.704rem; - border-top-left-radius: 999px; - border-bottom-left-radius: 999px; - border-left: 0.068rem solid #cde7ec; - border-top: 0.068rem solid #cde7ec; - border-bottom: 0.068rem solid #cde7ec; - border-right: 0px solid transparent; } - -.bar-ws-occupied-right { - background-color: #334b4f; - color: #cde7ec; - min-width: 1.704rem; - border-top-right-radius: 999px; - border-bottom-right-radius: 999px; - border-right: 0.068rem solid #cde7ec; - border-top: 0.068rem solid #cde7ec; - border-bottom: 0.068rem solid #cde7ec; - border-left: 0px solid transparent; } - -.bar-ws-occupied-left-right { - border-radius: 9999px; - -gtk-outline-radius: 9999px; - background-color: #334b4f; - color: #cde7ec; - min-width: 1.636rem; - border: 0.068rem solid #cde7ec; } - -.bar-ws-empty { - color: white; - border-color: transparent; } - -.bar-batt { - border-radius: 9999px; - -gtk-outline-radius: 9999px; - padding: 0rem 0.341rem; - background-color: rgba(51, 75, 79, 0.4); - color: rgba(205, 231, 236, 0.4); } - -.bar-sidemodule { - min-width: 26rem; } - -.bar-batt-low { - background-color: #ba1b1b; - color: #ffdad4; } - -.bar-batt-full { - background-color: #374b3e; - color: #d1e9d6; } - -.bar-batt-prog-low { - background-color: #ba1b1b; - color: #ffdad4; } - -.bar-batt-prog-full { - background-color: #374b3e; - color: #d1e9d6; } - -.bar-music-playstate { - min-height: 1.770rem; - min-width: 1.770rem; - border-radius: 10rem; - margin-left: 0.273rem; - background-color: #334b4f; - color: #cde7ec; } - -.bar-music-circprog { - transition: 1000ms cubic-bezier(0.1, 1, 0, 1); - margin-left: 0.273rem; - min-width: 0.068rem; - min-height: 1.770rem; - padding: 0rem; - background-color: #334b4f; - color: #cde7ec; } - -.bar-music-playstate-playing { - min-height: 1.770rem; - min-width: 1.770rem; - border-radius: 10rem; - margin-left: 0.273rem; - background-color: #334b4f; - color: #cde7ec; } - -.bar-music-playstate-txt { - transition: 100ms cubic-bezier(0.05, 0.7, 0.1, 1); - font-family: 'Material Symbols Rounded', 'Material Symbols Outlined', 'Material Symbols Sharp'; - font-size: 1.568rem; - margin: -0.1rem 0rem; - margin-left: 0.2rem; - margin-right: 0.17rem; } - -.bar-music-cover { - background-position: center; - background-repeat: no-repeat; - background-size: 100% auto; - min-width: 11.932rem; } - -.bar-music-extended-bg { - border-radius: 1.364rem; - min-width: 34.091rem; } - -.bar-music-extended-ctl-bg { - border-radius: 1.364rem; - background-color: rgba(30, 30, 30, 0.6); } - -.bar-music-bottom-bg { - border-radius: 1.364rem; - min-width: 34.091rem; } - -.bar-music-bottom-ctl-bg { - border-radius: 1.364rem; - background-color: rgba(30, 30, 30, 0.6); } - -.bar-music-extended-textbox { - margin: 1.023rem; } - -.bar-music-bottom-cover { - border-radius: 10rem; } - -.bar-music-hide-false { - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); - transition-duration: 100ms; - opacity: 1; } - -.bar-music-hide-true { - transition: 150ms cubic-bezier(0.3, 0, 0.8, 0.15); - transition-duration: 100ms; - opacity: 0; } - -.bar-music-btn { - font-size: 1.364rem; - border-radius: 10rem; - min-height: 2.591rem; - min-width: 2.591rem; } - -.bar-music-btn:hover { - background-color: rgba(128, 128, 128, 0.3); } - -.bar-prog-batt { - min-height: 0.955rem; - min-width: 0.068rem; - padding: 0rem; - border-radius: 10rem; } - .bar-prog-batt trough { - min-height: 0.954rem; - min-width: 0.068rem; - border-radius: 10rem; } - .bar-prog-batt progress { - min-height: 0.680rem; - min-width: 0.680rem; - margin: 0rem 0.137rem; - border-radius: 10rem; - background-color: rgba(205, 231, 236, 0.4); } - -.bar-prog-batt-low progress { - background-color: #ffdad4; } - -.bar-prog-batt-full progress { - background-color: #d1e9d6; } - -.bar-batt-chargestate { - border-radius: 10rem; - background-color: transparent; } - -.bar-batt-chargestate-charging { - border-radius: 10rem; - min-width: 0.681rem; - min-height: 0.681rem; - background-color: rgba(205, 231, 236, 0.4); } - -.bar-batt-chargestate-low { - background-color: #ffdad4; } - -.bar-batt-chargestate-full { - background-color: #d1e9d6; } - -.bar-batt-percentage { - font-size: 1rem; - margin-top: -0.068rem; - font-weight: 500; } - -.corner { - background-color: rgba(25, 28, 29, 0.4); - border-radius: 1.705rem; - -gtk-outline-radius: 1.705rem; } - -.corner-black { - background-color: black; - border-radius: 1.705rem; - -gtk-outline-radius: 1.705rem; } - -.bar-topdesc { - margin-top: -0.136rem; - margin-bottom: -0.341rem; - color: #a5a7a8; } - -.bar-space-button { - padding: 0.341rem; } - -.bar-space-button > box:first-child { - border-radius: 9999px; - -gtk-outline-radius: 9999px; - padding: 0rem 0.682rem; } - -.bar-space-button:hover > box:first-child { - background-color: rgba(128, 128, 128, 0.3); } - -.bar-space-button:active > box:first-child { - background-color: rgba(128, 128, 128, 0.7); } - -.bar-space-button-leftmost box { - margin: 0rem 0.682rem; } - -.bar-space-area-rightmost > box { - padding-right: 2.386rem; } - -.bar-systray { - border-radius: 9999px; - -gtk-outline-radius: 9999px; - min-height: 1.909rem; - min-width: 1.909rem; } - -.bar-systray-item { - border-radius: 9999px; - -gtk-outline-radius: 9999px; - min-width: 1.909rem; } - -.cheatsheet-bg { - border-radius: 1.705rem; - -gtk-outline-radius: 1.705rem; - border-top: 1px solid rgba(49, 52, 53, 0.91); - border-left: 1px solid rgba(49, 52, 53, 0.91); - border-right: 1px solid rgba(37, 40, 41, 0.905); - border-bottom: 1px solid rgba(37, 40, 41, 0.905); - box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); - margin: 7px; - margin-bottom: 0.682rem; - background-color: rgba(25, 28, 29, 0.4); - padding: 1.364rem; } - -.cheatsheet-key { - font-family: 'JetBrains Mono Nerd Font', 'JetBrains Mono NL', 'SpaceMono Nerd Font', monospace; - min-height: 1.364rem; - min-width: 1.364rem; - margin: 0.17rem; - padding: 0.136rem 0.205rem; - border-radius: 0.409rem; - -gtk-outline-radius: 0.409rem; - color: #50d8ec; - border: 0.068rem solid #50d8ec; - box-shadow: 0rem 0.136rem 0rem #50d8ec; - font-weight: 500; } - -.cheatsheet-key-notkey { - min-height: 1.364rem; - padding: 0.136rem 0.205rem; - margin: 0.17rem; - color: #99f0ff; } - -.cheatsheet-closebtn { - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); - border-radius: 9999px; - -gtk-outline-radius: 9999px; - min-width: 2.386rem; - min-height: 2.386rem; } - -.cheatsheet-closebtn:hover { - background-color: #3f484a; } - -.cheatsheet-closebtn:active { - background-color: #656e70; } - -.cheatsheet-category-title { - font-family: 'Noto Sans', 'Gabarito', 'Lexend', sans-serif; - font-size: 1.705rem; } - -.sidebar-right { - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); - border-radius: 1.705rem; - -gtk-outline-radius: 1.705rem; - border-top: 1px solid rgba(49, 52, 53, 0.91); - border-left: 1px solid rgba(49, 52, 53, 0.91); - border-right: 1px solid rgba(37, 40, 41, 0.905); - border-bottom: 1px solid rgba(37, 40, 41, 0.905); - box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); - margin: 7px; - background-color: rgba(25, 28, 29, 0.4); - padding: 1.023rem; } - -.sideright-show { - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); } - -.sideright-hide { - margin-right: -30.682rem; - transition: 150ms cubic-bezier(0.3, 0, 0.8, 0.15); } - -.sidebar-left { - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); - border-radius: 1.705rem; - -gtk-outline-radius: 1.705rem; - border-top: 1px solid rgba(49, 52, 53, 0.91); - border-left: 1px solid rgba(49, 52, 53, 0.91); - border-right: 1px solid rgba(37, 40, 41, 0.905); - border-bottom: 1px solid rgba(37, 40, 41, 0.905); - box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); - margin: 7px; - background-color: rgba(25, 28, 29, 0.4); - padding: 1.023rem; } - -.sideleft-show { - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); } - -.sideleft-hide { - margin-left: -30.682rem; - transition: 150ms cubic-bezier(0.3, 0, 0.8, 0.15); } - -.sidebar-group { - border-radius: 1.159rem; - -gtk-outline-radius: 1.159rem; - padding: 0.341rem; - background-color: rgba(25, 28, 29, 0.3); } - -.sidebar-group-nopad { - border-radius: 1.159rem; - -gtk-outline-radius: 1.159rem; - background-color: rgba(25, 28, 29, 0.3); } - -.sidebar-group-invisible { - padding: 0.341rem; } - -.sidebar-group-invisible-morehorizpad { - padding: 0.341rem 0.682rem; } - -.sidebar-iconbutton { - border-radius: 9999px; - -gtk-outline-radius: 9999px; - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); - color: #e1e3e3; - min-width: 2.727rem; - min-height: 2.727rem; } - -.sidebar-iconbutton:hover { - background-color: rgba(82, 106, 110, 0.4); } - -.sidebar-iconbutton:active { - background-color: rgba(113, 137, 142, 0.4); } - -.sidebar-button { - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); - padding: 0rem 0.818rem; - background-color: rgba(51, 75, 79, 0.4); - color: #cde7ec; } - -.sidebar-button-nopad { - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); - background-color: rgba(51, 75, 79, 0.4); - color: #cde7ec; } - -.sidebar-button:hover { - background-color: rgba(82, 106, 110, 0.4); } - -.sidebar-button:active { - background-color: rgba(113, 137, 142, 0.4); } - -.sidebar-button-nopad:hover { - background-color: rgba(82, 106, 110, 0.4); } - -.sidebar-button-nopad:active { - background-color: rgba(113, 137, 142, 0.4); } - -.sidebar-button-left { - border-top-left-radius: 0.818rem; - border-bottom-left-radius: 0.818rem; } - -.sidebar-button-right { - border-top-right-radius: 0.818rem; - border-bottom-right-radius: 0.955rem; } - -.sidebar-button-alone { - border-radius: 0.818rem; - -gtk-outline-radius: 0.818rem; } - -.sidebar-button-alone-normal { - border-radius: 0.818rem; - -gtk-outline-radius: 0.818rem; } - -.sidebar-button-active { - background-color: #50d8ec; - color: #00363d; } - -.sidebar-button-active:hover { - background-color: rgba(81, 214, 234, 0.93); } - -.sidebar-button-active:active { - background-color: rgba(83, 210, 228, 0.79); } - -.sidebar-buttons-separator { - min-width: 0.068rem; - min-height: 0.068rem; - background-color: #bfc8ca; } - -.sidebar-navrail { - padding: 0rem 1.159rem; } - -.sidebar-navrail-btn > box > label { - border-radius: 9999px; - -gtk-outline-radius: 9999px; - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); } - -.sidebar-navrail-btn:hover > box > label:first-child { - background-color: rgba(112, 121, 123, 0.37); } - -.sidebar-navrail-btn:active > box > label:first-child { - background-color: #5f686a; } - -.sidebar-navrail-btn-active > box > label:first-child { - background-color: #334b4f; - color: #cde7ec; } - -.sidebar-navrail-btn-active:hover > box > label:first-child { - background-color: rgba(52, 76, 80, 0.93); - color: rgba(204, 229, 234, 0.93); } - -.sidebar-sysinfo-grouppad { - padding: 1.159rem; } - -.sidebar-memory-ram-circprog { - transition: 1000ms cubic-bezier(0.1, 1, 0, 1); - min-width: 0.818rem; - min-height: 4.091rem; - padding: 0.409rem; - background-color: #334b4f; - color: #cde7ec; - font-size: 0px; } - -.sidebar-memory-swap-circprog { - transition: 1000ms cubic-bezier(0.1, 1, 0, 1); - min-width: 0.818rem; - min-height: 2.255rem; - padding: 0.409rem; - margin: 0.918rem; - background-color: #334b4f; - color: #cde7ec; - font-size: 0px; } - -.sidebar-cpu-circprog { - min-width: 0.818rem; - min-height: 3.409rem; - padding: 0.409rem; - background-color: #334b4f; - color: #cde7ec; - transition: 1000ms cubic-bezier(0.1, 1, 0, 1); - font-size: 0px; } - -.sidebar-viewport { - border-radius: 0.818rem; - -gtk-outline-radius: 0.818rem; } - -.sidebar-scrollbar trough { - border-radius: 9999px; - -gtk-outline-radius: 9999px; - min-width: 0.545rem; - background-color: transparent; } - -.sidebar-scrollbar slider { - border-radius: 9999px; - -gtk-outline-radius: 9999px; - min-width: 0.273rem; - min-height: 2.045rem; - background-color: rgba(191, 200, 202, 0.3); } - -.sidebar-scrollbar slider:hover { - background-color: rgba(191, 200, 202, 0.44); } - -.sidebar-scrollbar slider:active { - background-color: #7f888a; } - -.sidebar-calendar-btn { - border-radius: 9999px; - -gtk-outline-radius: 9999px; - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); - min-height: 2.523rem; - min-width: 2.523rem; - color: #e1e3e3; } - -.sidebar-calendar-btn:hover { - background-color: rgba(128, 128, 128, 0.3); } - -.sidebar-calendar-btn:active { - background-color: rgba(128, 128, 128, 0.7); } - -.sidebar-calendar-btn-txt { - margin-left: -10.341rem; - margin-right: -10.341rem; } - -.sidebar-calendar-btn-today { - background-color: #50d8ec; - color: #00363d; } - -.sidebar-calendar-btn-today:hover { - background-color: rgba(81, 214, 234, 0.93); } - -.sidebar-calendar-btn-today:active { - background-color: rgba(83, 210, 228, 0.79); } - -.sidebar-calendar-btn-othermonth { - color: #7d8080; } - -.sidebar-calendar-header { - margin: 0.341rem; } - -.sidebar-calendar-monthyear-btn { - border-radius: 9999px; - -gtk-outline-radius: 9999px; - padding: 0rem 0.682rem; - background-color: rgba(63, 72, 74, 0.3); - color: #bfc8ca; } - -.sidebar-calendar-monthyear-btn:hover { - background-color: rgba(92, 101, 103, 0.335); - color: #b9c2c4; } - -.sidebar-calendar-monthyear-btn:active { - background-color: #525b5d; - color: #acb5b7; } - -.sidebar-calendar-monthshift-btn { - border-radius: 9999px; - -gtk-outline-radius: 9999px; - min-width: 2.045rem; - min-height: 2.045rem; - background-color: rgba(63, 72, 74, 0.3); - color: #bfc8ca; } - -.sidebar-calendar-monthshift-btn:hover { - background-color: rgba(92, 101, 103, 0.335); - color: #b9c2c4; } - -.sidebar-calendar-monthshift-btn:active { - background-color: #525b5d; - color: #acb5b7; } - -.sidebar-todo-selector-tab { - border-radius: 0.818rem; - -gtk-outline-radius: 0.818rem; - transition: 0ms; - min-height: 2.5rem; - color: #e1e3e3; } - -.sidebar-todo-selector-tab:hover { - background-color: rgba(112, 121, 123, 0.37); } - -.sidebar-todo-selector-tab:active { - background-color: #5f686a; } - -.sidebar-todo-selector-tab-active > box > label { - color: #50d8ec; } - -.sidebar-todo-selector-highlight-offset { - margin-top: -0.205rem; - margin-bottom: 0.205rem; } - -.sidebar-todo-selector-highlight { - transition: 180ms ease-in-out; - color: #50d8ec; - padding: 0rem 2.045rem; - min-height: 0.205rem; } - -.sidebar-todo-item-action { - border-radius: 9999px; - min-width: 1.705rem; - min-height: 1.705rem; } - -.sidebar-todo-item-action:hover { - background-color: rgba(35, 38, 39, 0.3); } - -.sidebar-todo-item-action:active { - background-color: rgba(55, 58, 59, 0.3); } - -.sidebar-clipboard-item { - border-radius: 0.818rem; - min-height: 2.045rem; - padding: 0.341rem; - background-color: rgba(51, 75, 79, 0.4); - color: #cde7ec; } - -.sidebar-clipboard-item:hover { - background-color: rgba(66, 91, 95, 0.4); } - -.sidebar-clipboard-item:active { - background-color: rgba(82, 106, 110, 0.4); } - -.osd-bg { - min-width: 8.864rem; - min-height: 3.409rem; } - -.osd-value { - background-color: rgba(25, 28, 29, 0.4); - border-radius: 1.023rem; - padding: 0.625rem 1.023rem; - padding-top: 0.313rem; - margin: 10px; - box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); - margin: 7px; } - -.osd-progress { - min-height: 0.955rem; - min-width: 0.068rem; - padding: 0rem; - border-radius: 10rem; - transition: 200ms cubic-bezier(0.1, 1, 0, 1); } - .osd-progress trough { - min-height: 0.954rem; - min-width: 0.068rem; - border-radius: 10rem; - background-color: #99f0ff; } - .osd-progress progress { - transition: 200ms cubic-bezier(0.1, 1, 0, 1); - min-height: 0.680rem; - min-width: 0.680rem; - margin: 0rem 0.137rem; - border-radius: 10rem; - background-color: #004f58; } - -.osd-icon { - color: #99f0ff; } - -.osd-label { - font-size: 1.023rem; - font-weight: 500; - color: #e1e3e3; - margin-top: 0.341rem; } - -.osd-value-txt { - font-family: 'Noto Sans', 'Gabarito', 'Lexend', sans-serif; - font-size: 1.688rem; - font-weight: 500; - color: #e1e3e3; } - -.osd-notifs { - padding-top: 0.313rem; } - -.overview-search-box { - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); - border-radius: 1.705rem; - -gtk-outline-radius: 1.705rem; - border-top: 1px solid rgba(49, 52, 53, 0.91); - border-left: 1px solid rgba(49, 52, 53, 0.91); - border-right: 1px solid rgba(37, 40, 41, 0.905); - border-bottom: 1px solid rgba(37, 40, 41, 0.905); - box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); - margin: 7px; - min-width: 13.636rem; - min-height: 3.409rem; - padding: 0rem 1.364rem; - padding-right: 2.864rem; - background-color: rgba(25, 28, 29, 0.4); - color: #e1e3e3; - caret-color: transparent; } - .overview-search-box selection { - background-color: #b1cbd0; - color: #1c3438; } - -.overview-search-box-extended { - min-width: 25.909rem; - caret-color: #cde7ec; } - -.overview-search-prompt { - color: #a5a7a8; } - -.overview-search-icon { - margin: 0rem 1.023rem; } - -.overview-search-prompt-box { - margin-left: -18.545rem; - margin-right: 8px; } - -.overview-search-icon-box { - margin-left: -18.545rem; - margin-right: 8px; } - -.overview-search-results { - border-radius: 1.705rem; - -gtk-outline-radius: 1.705rem; - border-top: 1px solid rgba(49, 52, 53, 0.91); - border-left: 1px solid rgba(49, 52, 53, 0.91); - border-right: 1px solid rgba(37, 40, 41, 0.905); - border-bottom: 1px solid rgba(37, 40, 41, 0.905); - box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); - margin: 7px; - min-width: 28.773rem; - padding: 0.682rem; - background-color: rgba(25, 28, 29, 0.4); - color: #e1e3e3; } - -.overview-search-results-icon { - margin: 0rem 0.682rem; - font-size: 2.386rem; } - -.overview-search-results-txt { - margin-right: 0.682rem; } - -.overview-search-results-txt-cmd { - margin-right: 0.682rem; - font-family: 'JetBrains Mono Nerd Font', 'JetBrains Mono NL', 'SpaceMono Nerd Font', monospace; - font-size: 1.227rem; } - -.overview-search-result-btn { - border-radius: 1.159rem; - -gtk-outline-radius: 1.159rem; - padding: 0.341rem; - min-width: 2.386rem; - min-height: 2.386rem; - caret-color: transparent; } - -.overview-search-result-btn:focus, -.overview-search-result-btn:hover { - background-color: rgba(128, 128, 128, 0.3); } - -.overview-search-result-btn:active { - background-color: rgba(128, 128, 128, 0.7); } - -.overview-tasks { - border-radius: 1.705rem; - -gtk-outline-radius: 1.705rem; - border-top: 1px solid rgba(49, 52, 53, 0.91); - border-left: 1px solid rgba(49, 52, 53, 0.91); - border-right: 1px solid rgba(37, 40, 41, 0.905); - border-bottom: 1px solid rgba(37, 40, 41, 0.905); - box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); - margin: 7px; - padding: 0.341rem; - background-color: rgba(25, 28, 29, 0.4); - color: #e1e3e3; } - -.overview-tasks-workspace { - border-radius: 1.159rem; - -gtk-outline-radius: 1.159rem; - margin: 0.341rem; - background-color: rgba(29, 32, 33, 0.858); } - -.overview-tasks-window { - border-radius: 1.159rem; - -gtk-outline-radius: 1.159rem; - transition: 200ms cubic-bezier(0.05, 0.7, 0.1, 1); - background-color: rgba(51, 75, 79, 0.8); - color: #cde7ec; - border: 0.068rem solid rgba(205, 231, 236, 0.07); } - -.overview-tasks-window:hover { - background-color: rgba(53, 85, 90, 0.81); } - -.overview-tasks-window:focus { - background-color: rgba(53, 85, 90, 0.81); } - -.overview-tasks-window:active { - background-color: rgba(55, 95, 101, 0.82); } - -.overview-tasks-window-selected { - background-color: rgba(55, 95, 101, 0.82); } - -.overview-tasks-window-dragging { - opacity: 0.2; } - -.osk-window { - transition: 170ms cubic-bezier(0.05, 0.7, 0.1, 1); - border-radius: 1.705rem; - -gtk-outline-radius: 1.705rem; - border-top: 1px solid rgba(49, 52, 53, 0.91); - border-left: 1px solid rgba(49, 52, 53, 0.91); - border-right: 1px solid rgba(37, 40, 41, 0.905); - border-bottom: 1px solid rgba(37, 40, 41, 0.905); - box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); - margin: 7px; - background-color: rgba(25, 28, 29, 0.4); - padding: 1.023rem; } - -.osk-show { - transition: 170ms cubic-bezier(0.05, 0.7, 0.1, 1); } - -.osk-hide { - margin-top: 30.682rem; - margin-bottom: -30.682rem; - transition: 100ms cubic-bezier(0.3, 0, 0.8, 0.15); } - -.osk-key { - border-radius: 0.682rem; - background-color: rgba(63, 72, 74, 0.3); - color: #bfc8ca; - padding: 0.188rem; - font-weight: 500; - font-size: 1.091rem; } - -.osk-key:hover { - background-color: rgba(76, 85, 87, 0.3); } - -.osk-key:active { - background-color: rgba(101, 110, 112, 0.3); - font-size: 1.091rem; } - -.osk-key-active { - background-color: rgba(101, 110, 112, 0.3); } - -.osk-key-normal { - min-width: 2.5rem; - min-height: 2.5rem; } - -.osk-key-fn { - min-width: 2.5125rem; - min-height: 1.25rem; } - -.osk-key-tab { - min-width: 4rem; - min-height: 2.5rem; } - -.osk-key-caps { - min-width: 4.75rem; - min-height: 2.5rem; } - -.osk-key-shift { - min-width: 6.25rem; - min-height: 2.5rem; } - -.osk-key-control { - min-width: 3.25rem; - min-height: 2.5rem; } - -.osk-control-button { - border-radius: 0.682rem; - background-color: rgba(63, 72, 74, 0.3); - color: #bfc8ca; - font-weight: 500; - font-size: 1.091rem; - padding: 0.682rem; } - -.osk-control-button:hover { - background-color: rgba(76, 85, 87, 0.3); } - -.osk-control-button:active { - background-color: rgba(101, 110, 112, 0.3); - font-size: 1.091rem; } - -.session-bg { - margin-top: -2.727rem; - background-color: rgba(25, 28, 29, 0.93); } - -.session-button { - border-radius: 1.705rem; - -gtk-outline-radius: 1.705rem; - min-width: 8.182rem; - min-height: 8.182rem; - background-color: #3f484a; - color: #bfc8ca; - font-size: 3rem; } - -.session-button-focused { - background-color: #334b4f; - color: #cde7ec; } - -.session-button-desc { - background-color: #2c3234; - color: #d0d6d7; - border-bottom-left-radius: 1.705rem; - border-bottom-right-radius: 1.705rem; - padding: 0.205rem 0.341rem; - font-weight: 700; } - -.session-button-cancel { - border-radius: 1.705rem; - -gtk-outline-radius: 1.705rem; - min-width: 8.182rem; - min-height: 5.455rem; - background-color: #3f484a; - color: #bfc8ca; - font-size: 3rem; } - -.notif-low { - border-radius: 0.818rem; - -gtk-outline-radius: 0.818rem; - background-color: rgba(63, 72, 74, 0.9); - color: #bfc8ca; - padding: 0.818rem; - padding-right: 1.363rem; } - -.notif-normal { - border-radius: 0.818rem; - -gtk-outline-radius: 0.818rem; - background-color: rgba(63, 72, 74, 0.9); - color: #bfc8ca; - padding: 0.818rem; - padding-right: 1.363rem; } - -.notif-critical { - border-radius: 0.818rem; - -gtk-outline-radius: 0.818rem; - background-color: #ba1b1b; - color: #ffffff; - padding: 0.818rem; - padding-right: 1.363rem; } - -.popup-notif-low { - border-radius: 0.818rem; - -gtk-outline-radius: 0.818rem; - min-width: 30.682rem; - background-color: rgba(25, 28, 29, 0.4); - color: #bfc8ca; - padding: 0.818rem; - padding-right: 1.363rem; } - -.popup-notif-normal { - border-radius: 0.818rem; - -gtk-outline-radius: 0.818rem; - min-width: 30.682rem; - background-color: rgba(25, 28, 29, 0.4); - color: #bfc8ca; - padding: 0.818rem; - padding-right: 1.363rem; } - -.popup-notif-critical { - border-radius: 0.818rem; - -gtk-outline-radius: 0.818rem; - min-width: 30.682rem; - background-color: #ba1b1b; - color: #ffffff; - padding: 0.818rem; - padding-right: 1.363rem; } - -.notif-body-low { - color: #959ea0; } - -.notif-body-normal { - color: #959ea0; } - -.notif-body-critical { - color: #e8b4b4; } - -.notif-icon { - border-radius: 9999px; - -gtk-outline-radius: 9999px; - min-width: 3.409rem; - min-height: 3.409rem; } - -.notif-icon-material { - background-color: rgba(51, 75, 79, 0.4); - color: #cde7ec; } - -.notif-icon-material-low { - background-color: rgba(51, 75, 79, 0.4); - color: #cde7ec; } - -.notif-icon-material-normal { - background-color: rgba(51, 75, 79, 0.4); - color: #cde7ec; } - -.notif-icon-material-critical { - background-color: rgba(255, 218, 212, 0.4); - color: #410001; } - -.notif-close-btn { - border-radius: 0.818rem; - -gtk-outline-radius: 0.818rem; - padding: 0rem 0.136rem; } - -.notif-close-btn:hover { - background: rgba(128, 128, 128, 0.3); } - -.notif-close-btn:active { - background: rgba(128, 128, 128, 0.7); } - -.notif-closeall-btn { - border-radius: 0.818rem; - -gtk-outline-radius: 0.818rem; - padding: 0.341rem 0.341rem; } - -.notif-closeall-btn:hover { - background-color: rgba(128, 128, 128, 0.3); } - -.notif-closeall-btn:active { - background-color: rgba(128, 128, 128, 0.7); } - -.osd-notif { - border-radius: 0.818rem; - -gtk-outline-radius: 0.818rem; - background-color: rgba(25, 28, 29, 0.9); - min-width: 30.682rem; } - -.growingRadial { - transition: 300ms cubic-bezier(0.2, 0, 0, 1); } - -.fadingRadial { - transition: 50ms cubic-bezier(0.2, 0, 0, 1); } diff --git a/home/desktops/hyprland/ags/tsconfig.json b/home/desktops/hyprland/ags/tsconfig.json new file mode 100644 index 0000000..7026c9c --- /dev/null +++ b/home/desktops/hyprland/ags/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ES2022", + "lib": ["ES2022"], + "allowJs": true, + "checkJs": true, + "strict": true, + "noImplicitAny": false, + "baseUrl": ".", + "typeRoots": ["./types/ags.d.ts", "./node_modules/@girs"], + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + } +} diff --git a/home/desktops/hyprland/ags/windows/bar.js b/home/desktops/hyprland/ags/windows/bar.js deleted file mode 100644 index 1e4b171..0000000 --- a/home/desktops/hyprland/ags/windows/bar.js +++ /dev/null @@ -1,54 +0,0 @@ -const { Gdk, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../imports.js'; -const { execAsync, exec } = Utils; - -import { ModuleWorkspaces } from "../modules/workspaces.js"; -import { ModuleMusic } from "../modules/music.js"; -import { ModuleSystem } from "../modules/system.js"; -import { ModuleLeftSpace } from "../modules/leftspace.js"; -import { ModuleRightSpace } from "../modules/rightspace.js"; -import { RoundedCorner } from "../modules/lib/roundedcorner.js"; - -const left = Widget.Box({ - className: 'bar-sidemodule', - children: [ModuleMusic()], -}); - -const center = Widget.Box({ - children: [ - RoundedCorner('topright', { className: 'corner-bar-group' }), - ModuleWorkspaces(), - RoundedCorner('topleft', { className: 'corner-bar-group' }), - ], -}); - -const right = Widget.Box({ - className: 'bar-sidemodule', - children: [ModuleSystem()], -}); - -export default () => Widget.Window({ - name: 'bar', - anchor: ['top', 'left', 'right'], - monitor: 1, - exclusive: true, - visible: true, - child: Widget.CenterBox({ - className: 'bar-bg', - startWidget: ModuleLeftSpace(), - centerWidget: Widget.Box({ - className: 'spacing-h--20', - children: [ - left, - center, - right, - ] - }), - endWidget: ModuleRightSpace(), - setup: (self) => { - const styleContext = self.get_style_context(); - const minHeight = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL); - // execAsync(['bash', '-c', `hyprctl keyword monitor ,addreserved,${minHeight},0,0,0`]).catch(print); - } - }), -}); diff --git a/home/desktops/hyprland/ags/windows/cheatsheet.js b/home/desktops/hyprland/ags/windows/cheatsheet.js deleted file mode 100644 index 9783d40..0000000 --- a/home/desktops/hyprland/ags/windows/cheatsheet.js +++ /dev/null @@ -1,88 +0,0 @@ -const { Gdk, Gtk } = imports.gi; -import { Service, Widget } from '../imports.js'; -import { Keybinds } from "../modules/keybinds.js"; -import { setupCursorHover } from "../modules/lib/cursorhover.js"; - -const cheatsheetHeader = () => Widget.CenterBox({ - vertical: false, - startWidget: Widget.Box({}), - centerWidget: Widget.Box({ - vertical: true, - className: "spacing-h-15", - children: [ - Widget.Box({ - halign: 'center', - className: 'spacing-h-5', - children: [ - Widget.Label({ - halign: 'center', - style: 'margin-right: 0.682rem;', - className: 'txt-title txt', - label: 'Cheat sheet', - }), - Widget.Label({ - valign: 'center', - className: "cheatsheet-key txt-small", - label: "", - }), - Widget.Label({ - valign: 'center', - className: "cheatsheet-key-notkey txt-small", - label: "+", - }), - Widget.Label({ - valign: 'center', - className: "cheatsheet-key txt-small", - label: "/", - }) - ] - }), - Widget.Label({ - justify: Gtk.Justification.CENTER, - className: 'txt-small txt', - label: 'Sheet data stored in ~/.config/ags/data/keybinds.js\nChange keybinds in ~/.config/hypr/keybinds.conf' - }), - ] - }), - endWidget: Widget.Button({ - valign: 'start', - halign: 'end', - className: "cheatsheet-closebtn icon-material txt txt-hugeass", - onClicked: () => { - App.toggleWindow('cheatsheet'); - }, - child: Widget.Label({ - className: 'icon-material txt txt-hugeass', - label: 'close' - }), - setup: (button) => setupCursorHover(button), - }), -}); - -const clickOutsideToClose = Widget.EventBox({ - onPrimaryClick: () => App.closeWindow('cheatsheet'), - onSecondaryClick: () => App.closeWindow('cheatsheet'), - onMiddleClick: () => App.closeWindow('cheatsheet'), -}); - -export default () => Widget.Window({ - name: 'cheatsheet', - exclusive: false, - focusable: true, - popup: true, - visible: false, - child: Widget.Box({ - vertical: true, - children: [ - clickOutsideToClose, - Widget.Box({ - vertical: true, - className: "cheatsheet-bg spacing-v-15", - children: [ - cheatsheetHeader(), - Keybinds(), - ] - }), - ], - }) -}); diff --git a/home/desktops/hyprland/ags/windows/corners.js b/home/desktops/hyprland/ags/windows/corners.js deleted file mode 100644 index 9da7aed..0000000 --- a/home/desktops/hyprland/ags/windows/corners.js +++ /dev/null @@ -1,43 +0,0 @@ -import { Widget } from "../imports.js"; -import { RoundedCorner } from "../modules/lib/roundedcorner.js"; - -export const CornerTopleft = (monitor) => - Widget.Window({ - name: "cornertl", - layer: "top", - monitor, - anchor: ["top", "left"], - exclusive: false, - visible: true, - child: RoundedCorner("topleft", { className: "corner-black" }), - }); -export const CornerTopright = (monitor) => - Widget.Window({ - name: "cornertr", - layer: "top", - monitor, - anchor: ["top", "right"], - exclusive: false, - visible: true, - child: RoundedCorner("topright", { className: "corner-black" }), - }); -export const CornerBottomleft = (monitor) => - Widget.Window({ - name: "cornerbl", - layer: "top", - monitor, - anchor: ["bottom", "left"], - exclusive: false, - visible: true, - child: RoundedCorner("bottomleft", { className: "corner-black" }), - }); -export const CornerBottomright = (monitor) => - Widget.Window({ - name: "cornerbr", - layer: "top", - monitor, - anchor: ["bottom", "right"], - exclusive: false, - visible: true, - child: RoundedCorner("bottomright", { className: "corner-black" }), - }); diff --git a/home/desktops/hyprland/ags/windows/lib/popupwindow.js b/home/desktops/hyprland/ags/windows/lib/popupwindow.js deleted file mode 100644 index a242ae0..0000000 --- a/home/desktops/hyprland/ags/windows/lib/popupwindow.js +++ /dev/null @@ -1,27 +0,0 @@ -import { App, Widget } from '../../imports.js'; -const { Revealer, Box, Window } = Widget; - - -export default ({ - name, - child, - showClassName, - hideClassName, - ...props -}) => Window({ - name, - popup: true, - visible: false, - layer: 'overlay', - ...props, - - child: Box({ - className: `${showClassName} ${hideClassName}`, - connections: [[App, (self, currentName, visible) => { - if (currentName === name) { - self.toggleClassName(hideClassName, !visible); - } - }]], - child: child, - }), -}); \ No newline at end of file diff --git a/home/desktops/hyprland/ags/windows/osd.js b/home/desktops/hyprland/ags/windows/osd.js deleted file mode 100644 index 662b29e..0000000 --- a/home/desktops/hyprland/ags/windows/osd.js +++ /dev/null @@ -1,12 +0,0 @@ -import { Widget } from '../imports.js'; -import Osd from "../modules/onscreendisplay.js"; - -export default (monitor) => Widget.Window({ - name: `indicator${monitor}`, - monitor, - className: 'indicator', - layer: 'overlay', - visible: true, - anchor: ['top'], - child: Osd(), -}); diff --git a/home/desktops/hyprland/ags/windows/osk.js b/home/desktops/hyprland/ags/windows/osk.js deleted file mode 100644 index f2ad6f9..0000000 --- a/home/desktops/hyprland/ags/windows/osk.js +++ /dev/null @@ -1,12 +0,0 @@ -const { Gdk, Gtk } = imports.gi; -import { Widget } from '../imports.js'; -import PopupWindow from './lib/popupwindow.js'; -import OnScreenKeyboard from "../modules/onscreenkeyboard.js"; - -export default () => PopupWindow({ - anchor: ['bottom'], - name: 'osk', - showClassName: 'osk-show', - hideClassName: 'osk-hide', - child: OnScreenKeyboard(), -}); diff --git a/home/desktops/hyprland/ags/windows/overview.js b/home/desktops/hyprland/ags/windows/overview.js deleted file mode 100644 index 1a5464c..0000000 --- a/home/desktops/hyprland/ags/windows/overview.js +++ /dev/null @@ -1,18 +0,0 @@ -import { Widget } from '../imports.js'; -import { SearchAndWindows } from "../modules/overview.js"; - -export default () => Widget.Window({ - name: 'overview', - exclusive: false, - focusable: true, - popup: true, - visible: false, - anchor: ['top'], - layer: 'overlay', - child: Widget.Box({ - vertical: true, - children: [ - SearchAndWindows(), - ] - }), -}) diff --git a/home/desktops/hyprland/ags/windows/session.js b/home/desktops/hyprland/ags/windows/session.js deleted file mode 100644 index e1bcd91..0000000 --- a/home/desktops/hyprland/ags/windows/session.js +++ /dev/null @@ -1,13 +0,0 @@ -const { Gdk, Gtk } = imports.gi; -import { Widget } from '../imports.js'; -import SessionScreen from "../modules/sessionscreen.js"; - -export default () => Widget.Window({ // On-screen keyboard - name: 'session', - popup: true, - visible: false, - focusable: true, - layer: 'overlay', - // anchor: ['top', 'bottom', 'left', 'right'], - child: SessionScreen(), -}) \ No newline at end of file diff --git a/home/desktops/hyprland/ags/windows/sideleft.js b/home/desktops/hyprland/ags/windows/sideleft.js deleted file mode 100644 index 27199f7..0000000 --- a/home/desktops/hyprland/ags/windows/sideleft.js +++ /dev/null @@ -1,11 +0,0 @@ -import PopupWindow from './lib/popupwindow.js'; -import SidebarLeft from "../modules/sideleft.js"; - -export default () => PopupWindow({ - focusable: true, - anchor: ['left', 'bottom'], - name: 'sideleft', - showClassName: 'sideleft-show', - hideClassName: 'sideleft-hide', - child: SidebarLeft(), -}); diff --git a/home/desktops/hyprland/ags/windows/sideright.js b/home/desktops/hyprland/ags/windows/sideright.js deleted file mode 100644 index f308d25..0000000 --- a/home/desktops/hyprland/ags/windows/sideright.js +++ /dev/null @@ -1,12 +0,0 @@ -import { Widget } from '../imports.js'; -import PopupWindow from './lib/popupwindow.js'; -import SidebarRight from "../modules/sideright.js"; - -export default () => PopupWindow({ - focusable: true, - anchor: ['right', 'top', 'bottom'], - name: 'sideright', - showClassName: 'sideright-show', - hideClassName: 'sideright-hide', - child: SidebarRight(), -}); diff --git a/home/desktops/hyprland/default.nix b/home/desktops/hyprland/default.nix index ab1ff6b..0a5c580 100644 --- a/home/desktops/hyprland/default.nix +++ b/home/desktops/hyprland/default.nix @@ -29,7 +29,6 @@ exec-once = [ "swww init" "ags" - "waybar" "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY XAUTHORITY" "dbus-update-activation-environment DISPLAY WAYLAND_DISPLAY XAUTHORITY" "gnome-keyring-daemon --start --components=secrets" @@ -148,8 +147,6 @@ }; programs.kitty = import ./kitty.nix {inherit pkgs;}; programs.anyrun = import ./anyrun.nix {inherit pkgs;}; - programs.waybar = import ./waybar.nix {inherit pkgs;}; - programs.foot.enable = true; services.udiskie.enable = true; services.udiskie.tray = "never"; diff --git a/home/desktops/hyprland/dunst.nix b/home/desktops/hyprland/dunst.nix deleted file mode 100644 index ebba77e..0000000 --- a/home/desktops/hyprland/dunst.nix +++ /dev/null @@ -1,8 +0,0 @@ -{ - enable = true; - settings = { - global = { - origin = "top-left"; - }; - }; -} diff --git a/home/desktops/hyprland/waybar.nix b/home/desktops/hyprland/waybar.nix deleted file mode 100644 index 31031e4..0000000 --- a/home/desktops/hyprland/waybar.nix +++ /dev/null @@ -1,129 +0,0 @@ -{pkgs}: { - enable = true; - settings = { - mainBar = { - layer = "top"; - position = "top"; - modules-left = ["hyprland/workspaces"]; - modules-center = ["clock"]; - modules-right = ["tray" "group/power"]; - - "clock" = { - format = "{:%H:%M}"; - }; - - "custom/weather" = { - format = "{}"; - tooltip = true; - interval = 3600; - exec = "${pkgs.wttrbar}/bin/wttrbar --location Berlin --custom-indicator \"{ICON}{temp_C}°\""; - return-type = "json"; - }; - - "group/power" = { - orientation = "inherit"; - drawer = { - transition-duration = 500; - children-class = "not-power"; - transition-left-to-right = false; - }; - modules = [ - "custom/launcher" - "custom/power" - #"custom/quit" - #"custom/lock" - "custom/reboot" - ]; - }; - - "custom/launcher" = { - format = " "; - tooltip = false; - on-click = "anyrun"; - }; - - "custom/quit" = { - format = "󰗼 "; - tooltip = false; - on-click = "hyprctl dispatch exit"; - }; - "custom/lock" = { - format = "󰍁 "; - tooltip = false; - on-click = "swaylock"; - }; - "custom/reboot" = { - format = "󰜉 "; - tooltip = false; - on-click = "reboot"; - }; - "custom/power" = { - format = " "; - tooltip = false; - on-click = "shutdown now"; - }; - - "hyprland/workspaces" = { - format = "{windows}"; - format-window-separator = " "; - window-rewrite-default = ""; - window-rewrite = { - "title<.*youtube.*>" = ""; - "title" = ""; - "title" = ""; - "title" = "󰢩"; - "class" = ""; - "class" = ""; - "class" = "󰺵"; - "class<.gimp.*>" = ""; - "class" = ""; - "class" = "󰆍"; - "class" = "󰂫"; - "class" = "󰓓"; - "class" = "󰏆"; - "class" = "󰭹"; - "class" = ""; - "class" = "󰼁"; - "class" = "󰙯"; - "class" = "󰝰"; - }; - }; - }; - }; - style = - /* - css - */ - '' - * { - font-weight: bold; - } - - window#waybar { - background: black; - } - - #workspaces { - } - - #workspaces button { - opacity: 0.5; - padding: 0; - border-radius: 0; - border-width: 0; - font-size: 16px; - padding-left: 2px; - padding-right: 2px; - border-top: 2px solid transparent; - transition: all 250ms ease; - } - - #workspaces button.active { - opacity: 1; - } - - #workspaces button.visible { - border-top-color: currentcolor; - } - ''; -}