diff --git a/.editorconfig b/.editorconfig index 0a51807d3..4af9e4943 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,7 +1,39 @@ root = true [*] +charset = utf-8 end_of_line = lf +indent_style = tab +indent_size = 4 insert_final_newline = true +tab_width = 4 +trim_trailing_whitespace = false + +[*.md] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = false + +[*.{nix,yml,yaml}] indent_style = space -indent_size = 2 \ No newline at end of file +indent_size = 2 +tab_width = 2 + +[*.yuck] +indent_style = spaces +indent_size = 4 + +[*.{js, sh}] +indent_style = spaces +indent_size = 2 + +[*.{diff,patch}] +end_of_line = unset +insert_final_newline = unset +trim_trailing_whitespace = unset + +[secrets.yaml] +indent_size = unset + +[*.lock] +indent_size = unset diff --git a/.envrc b/.envrc index 3550a30f2..30fa1673f 100644 --- a/.envrc +++ b/.envrc @@ -1 +1,2 @@ use flake +export DIRENV_WARN_TIMEOUT=5m diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..ff3caea67 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +flake/templates/* linguist-vendored diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 28205a28a..f14a2817b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @isabelroses \ No newline at end of file +* @isabelroses diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..e69de29bb diff --git a/.github/README.md b/.github/README.md index 7de9aef82..cec7ad84a 100644 --- a/.github/README.md +++ b/.github/README.md @@ -10,40 +10,45 @@ ### config layout -- 🏠 [home](../home) +- 🏠 [home](../home/) - 🖥️ [hosts](../hosts/) - - 🐉 [hydra](../hosts/hydra/) A super mid spec laptop - ☀️ [amatarasu](../hosts/amatarasu/) My high end gameing machine + - 👴 [bernie](../hosts/bernie/) A server configuration for some of my infastrucior + - 🇧[beta](../hosts/beta/) A consept configuration for a new local server + - 🐉 [hydra](../hosts/hydra/) A super mid spec laptop + - ⚸ [lilith](../hosts/lilith/) A nixos iso image that can be qickly deployed and acessed via ssh +- 📖 [lib](../lib/) Useful repeated functions +- 🧩 [parts](../parts/) Nixos parts breaking down the complex confiuration into smaller more managable chuncks - 🔌 [modules](../modules/) - [common](../modules/common/) Common configuration settings - [core](../modules/common/core/) Core parts of the configuration - - [options](../modules/common/options/) Selecteable settings that can be used to toggle certain settings - - [system](../modules/common/system/) System configurations + - [secrets](../modules/common/secrets/) Sops secured system secrets + - [types](../modules/common/types/) System type configurations (e.g. laptop, servers, desktop) - [extra](../modules/extra/) Prebuilt configrations & spare parts - - [desktop](../modules/extra/desktop/) Default desktop config - - [server](../modules/extra/server/) Deafult server config - - [virtualization](../modules/extra/virtualization/) Settings for virtualization + - [options](../modules/common/options/) Selecteable settings that can be used to toggle certain settings
Hyprland Shortcuts -| Shortcut | What it does | -|---|---| -| SUPER+RETURN | open terminal | -| SUPER+B | open browser | -| SUPER+C | open editor | -| SUPER+O | open notes | -| SUPER+E | open file manager | -| SUPER+Q | quit | -| SUPER+D | launcher | -| SUPER+F | fullscreen | -| SUPER+[number] | open workspace [number] | +| Shortcut | What it does | +| ------------------------------- | -------------------------- | +| SUPER+RETURN | open terminal | +| SUPER+B | open browser | +| SUPER+C | open editor | +| SUPER+O | open notes | +| SUPER+E | open file manager | +| SUPER+Q | quit | +| SUPER+D | launcher | +| SUPER+F | fullscreen | +| SUPER+[number] | open workspace [number] | | SUPER+SHIFT+[number] | move to workspace [number] |
### credits -- [numtide/srvos](https://github.com/numtide/srvos) -- [nullishamy](https://github.com/nullishamy/derivation-station/) -- [nekowinston](https://github.com/nekowinston/dotfiles) +- [NotAShelf](https://github.com/notashelf/nyx) - The carry (and basicly half this repo) +- [numtide/srvos](https://github.com/numtide/srvos) - Server stuff +- [nullishamy](https://github.com/nullishamy/derivation-station) - Home-Manager Stuff +- [nekowinston](https://github.com/nekowinston/dotfiles) - Basicly answers all my questions +- [getchoo](https://github.com/getchoo) - For several things here and there diff --git a/.github/assets/flake.svg b/.github/assets/flake.svg index 443f9d863..f71e2ca5c 100644 --- a/.github/assets/flake.svg +++ b/.github/assets/flake.svg @@ -1,48 +1,48 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..f5a0afc56 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: daily + time: "03:00" + open-pull-requests-limit: 10 + reviewers: + - isabelroses + assignees: + - isabelroses diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..4a98566e2 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,57 @@ +name: Build and populate cache + +on: + workflow_dispatch: + push: + branches: + - main + paths-ignore: + - .github/** + - assets/** + - .gitignore + - docs/** + - README.md + schedule: + - cron: "25 1 * * *" + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + package: + - bellado + - catppuccinifier-cli + - lutgen-rs + - patched-gjs + - ags + - plymouth-theme-catppuccin + + steps: + - uses: easimon/maximize-build-space@v8 + with: + overprovision-lvm: true + remove-android: true + remove-dotnet: true + remove-haskell: true + + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@main + with: + logger: pretty + + - name: Setup cachix + uses: cachix/cachix-action@v12 + with: + name: isabelroses + signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}" + authToken: "${{ secrets.CACHIX_TOKEN }}" + + - name: Set default git branch (to reduce log spam) + run: git config --global init.defaultBranch main + + - name: Build from the matrix + run: nix build -L .#${{ matrix.package }} diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 64ec2a055..4ac157061 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -1,19 +1,25 @@ -name: Nix Flake Check +name: Validate Nix Flake -on: [push, pull_request, workflow_dispatch] +on: + workflow_dispatch: + push: + paths: + - "**.nix" + - "**.lock" + - ".github/workflows/check.yml" jobs: - checks: - name: Check expressions + check-flake: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: cachix/install-nix-action@v18 + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@main with: - install_url: https://nixos.org/nix/install - extra_nix_config: | - auto-optimise-store = true - experimental-features = nix-command flakes - access-tokens = ${{ secrets.AUTH_TOKEN }} - - run: nix flake check + logger: pretty + + - name: Check Flake + run: nix flake check --accept-flake-config diff --git a/.github/workflows/fmt.yml b/.github/workflows/fmt.yml index af72b8fc2..0950c0b41 100644 --- a/.github/workflows/fmt.yml +++ b/.github/workflows/fmt.yml @@ -1,18 +1,17 @@ -name: Formatting Check +name: Validate Flake Formatting -on: [push, pull_request, workflow_dispatch] +on: [push, workflow_dispatch] jobs: - checks: - name: Check expressions + check-formatting: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: cachix/install-nix-action@v18 + - uses: actions/checkout@v4 + + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@main with: - install_url: https://nixos.org/nix/install - extra_nix_config: | - auto-optimise-store = true - experimental-features = nix-command flakes + logger: pretty + github_access_token: ${{ secrets.GITHUB_TOKEN }} - run: nix run nixpkgs#alejandra -- -c . diff --git a/.github/workflows/update.yml b/.github/workflows/update.yml new file mode 100644 index 000000000..ccb7bda4b --- /dev/null +++ b/.github/workflows/update.yml @@ -0,0 +1,29 @@ +name: Bump Flake Inputs +on: + workflow_dispatch: + schedule: + - cron: "0 0 * * *" + +jobs: + update-lockfile: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4.1.0 + + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@main + with: + logger: pretty + + - name: Update Lockfile + uses: DeterminateSystems/update-flake-lock@main + id: update + with: + pr-title: "CI: bump flake inputs" + + - name: Merge Changes + run: | + gh pr merge ${{ steps.update.outputs.pull-request-number }} --squash --delete-branch + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 4812d58f9..659459369 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ +# Ingore nixos build outputs result .direnv/ + +# Ignore pre-commit config +.pre-commit-config.yaml diff --git a/.sops.yaml b/.sops.yaml index 016116f86..5702ab68d 100755 --- a/.sops.yaml +++ b/.sops.yaml @@ -3,5 +3,5 @@ keys: creation_rules: - path_regex: modules/common/secrets/[^/]+\.yaml$ - key_groups: - - age: - - *isabel + - age: + - *isabel diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..fcd63736d --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Isabel + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/flake.lock b/flake.lock index 014322523..0bfcbb00d 100644 --- a/flake.lock +++ b/flake.lock @@ -2,18 +2,16 @@ "nodes": { "ags": { "inputs": { - "dongsu8142-nur": "dongsu8142-nur", "nixpkgs": [ - "bella-nur", "nixpkgs" ] }, "locked": { - "lastModified": 1692814506, - "narHash": "sha256-hSoT3iT5uW7P/H2Z9JsOqvqcV7SezlXUELJ7yvBL+rg=", + "lastModified": 1698179569, + "narHash": "sha256-CrOXArJ4+pSUmx9NsM69ATBVkJVCEccqO2ZIEwcji04=", "owner": "Aylur", "repo": "ags", - "rev": "b02412c7c39ce3d82d6825be98601b3dfe372da8", + "rev": "1229e8847f6331e5f7ab47a9474a8822d062134f", "type": "github" }, "original": { @@ -22,23 +20,57 @@ "type": "github" } }, - "bella-nur": { + "alpha-nvim": { + "flake": false, + "locked": { + "lastModified": 1689470865, + "narHash": "sha256-wgjYus4XlJ0GoQWTo5gf7yyKYhseOXKOqUXEiwXpEJQ=", + "owner": "goolord", + "repo": "alpha-nvim", + "rev": "e4fc5e29b731bdf55d204c5c6a11dc3be70f3b65", + "type": "github" + }, + "original": { + "owner": "goolord", + "repo": "alpha-nvim", + "type": "github" + } + }, + "auto-cpufreq": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1698113985, + "narHash": "sha256-nuSj6m50eRAB7d/tngmWUb47J+HMpLlDlzPYHNh5DD4=", + "owner": "AdnanHodzic", + "repo": "auto-cpufreq", + "rev": "d3760eaf37468a33d90b2e812bfcf6de06711a94", + "type": "github" + }, + "original": { + "owner": "AdnanHodzic", + "repo": "auto-cpufreq", + "type": "github" + } + }, + "bellado": { "inputs": { - "ags": "ags", - "catppuccinifier": "catppuccinifier", "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1692860477, - "narHash": "sha256-7TheFw61jYwyZeqlia//yGvXiJOp7U3SvLPuIe2JQ2w=", + "lastModified": 1696727195, + "narHash": "sha256-R+4eaviYu0SrW9xr8ZrYjemLamzWOdwoOrrkGOtXEUY=", "owner": "isabelroses", - "repo": "nur", - "rev": "017a96bd2b2a5bfb878e2e09674bcc695c28aa33", + "repo": "bellado", + "rev": "4fa6b3ca680b647a912a8f6198148a3cd222a704", "type": "github" }, "original": { "owner": "isabelroses", - "repo": "nur", + "repo": "bellado", "type": "github" } }, @@ -58,17 +90,33 @@ "type": "gitlab" } }, + "bufdelete-nvim": { + "flake": false, + "locked": { + "lastModified": 1688027130, + "narHash": "sha256-UubYRfRAXZ89WOc3QFMvAMjNjLW6bV4nDgSa1CRZkIM=", + "owner": "famiu", + "repo": "bufdelete.nvim", + "rev": "07d1f8ba79dec59d42b975a4df1c732b2e4e37b4", + "type": "github" + }, + "original": { + "owner": "famiu", + "repo": "bufdelete.nvim", + "type": "github" + } + }, "catppuccin": { "inputs": { - "flake-compat": "flake-compat_2", + "flake-compat": "flake-compat", "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1692027154, - "narHash": "sha256-41Eug3MJHYRM4kDx00qvoXZ5kr+Dlvr6c7GpCRFIdVo=", + "lastModified": 1697225301, + "narHash": "sha256-EKKclzHBNgRmnZPMuzVbX5KAqkBdxMutDDauqLWOhf4=", "owner": "isabelroses", "repo": "ctp-nix", - "rev": "0b448d3e12a9429ee95d6c9c44f5f5035fdbc2b4", + "rev": "8c39bd3d2adeb68b541fa174bf0163d4365ecbd5", "type": "github" }, "original": { @@ -77,21 +125,56 @@ "type": "github" } }, + "catppuccin-toolbox": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs_3", + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1697961149, + "narHash": "sha256-0UeE/xr23CpkkP9lig0O6YnN/AsdM28VGSQTHTBaLSk=", + "owner": "catppuccin", + "repo": "toolbox", + "rev": "5b5b4a50dd9183b4182818528202f990de5bd422", + "type": "github" + }, + "original": { + "owner": "catppuccin", + "repo": "toolbox", + "type": "github" + } + }, + "catppuccin_2": { + "flake": false, + "locked": { + "lastModified": 1690630440, + "narHash": "sha256-MSZcIrV3vvgb5mlMpO5uRlAYoENm2pZyuZbV5Q9Vg58=", + "owner": "catppuccin", + "repo": "nvim", + "rev": "057c34f849cf21059487d849e2f3b3efcd4ee0eb", + "type": "github" + }, + "original": { + "owner": "catppuccin", + "repo": "nvim", + "type": "github" + } + }, "catppuccinifier": { "inputs": { "crane": "crane", - "flake-utils": "flake-utils_2", + "flake-utils": "flake-utils_3", "nixpkgs": [ - "bella-nur", "nixpkgs" ] }, "locked": { - "lastModified": 1692223331, - "narHash": "sha256-CEjdCr7QgyQw+1VmeEyt95R0HKE0lAKZHrwahaxgJoU=", + "lastModified": 1696928114, + "narHash": "sha256-h445Aox0jck7MOCsKxXLKiE4QvptL/54eXUuhQZGF7o=", "owner": "lighttigerXIV", "repo": "catppuccinifier", - "rev": "965f48a28d57eb979a5d932b873fa6e4d1b2497b", + "rev": "ef9c180bb7bbf1486671a1c6df41adaab60a9b41", "type": "github" }, "original": { @@ -100,1208 +183,2704 @@ "type": "github" } }, - "crane": { - "inputs": { - "flake-compat": "flake-compat", - "flake-utils": "flake-utils", - "nixpkgs": [ - "bella-nur", - "catppuccinifier", - "nixpkgs" - ], - "rust-overlay": "rust-overlay" - }, + "ccc": { + "flake": false, "locked": { - "lastModified": 1687310026, - "narHash": "sha256-20RHFbrnC+hsG4Hyeg/58LvQAK7JWfFItTPFAFamu8E=", - "owner": "ipetkov", - "repo": "crane", - "rev": "116b32c30b5ff28e49f4fcbeeb1bbe3544593204", + "lastModified": 1686587775, + "narHash": "sha256-T1ryyTdbU/335MpD184PSnBLgj4S2Kzf9hZnwc9to+I=", + "owner": "uga-rosa", + "repo": "ccc.nvim", + "rev": "4a0ddaf787cc82796e84ab8a7f70d086f250aeb6", "type": "github" }, "original": { - "owner": "ipetkov", - "repo": "crane", + "owner": "uga-rosa", + "repo": "ccc.nvim", "type": "github" } }, - "crane_2": { - "inputs": { - "flake-compat": [ - "lanzaboote", - "flake-compat" - ], - "flake-utils": [ - "lanzaboote", - "flake-utils" - ], - "nixpkgs": [ - "lanzaboote", - "nixpkgs" - ], - "rust-overlay": [ - "lanzaboote", - "rust-overlay" - ] - }, + "cellular-automaton": { + "flake": false, "locked": { - "lastModified": 1688772518, - "narHash": "sha256-ol7gZxwvgLnxNSZwFTDJJ49xVY5teaSvF7lzlo3YQfM=", - "owner": "ipetkov", - "repo": "crane", - "rev": "8b08e96c9af8c6e3a2b69af5a7fa168750fcf88e", + "lastModified": 1674679594, + "narHash": "sha256-h4KQCf8+GbxWSyZzDny07YFZm7j+aSSfm51lsaK0Ers=", + "owner": "Eandrju", + "repo": "cellular-automaton.nvim", + "rev": "679943b8e1e5ef79aaeeaf4b00782c52eb4e928f", "type": "github" }, "original": { - "owner": "ipetkov", - "repo": "crane", + "owner": "Eandrju", + "repo": "cellular-automaton.nvim", "type": "github" } }, - "crane_3": { - "inputs": { - "flake-compat": [ - "nekowinston-nur" - ], - "flake-utils": [ - "nekowinston-nur", - "flake-utils" - ], - "nixpkgs": [ - "nekowinston-nur", - "nixpkgs" - ], - "rust-overlay": [ - "nekowinston-nur", - "rust-overlay" - ] + "cheatsheet-nvim": { + "flake": false, + "locked": { + "lastModified": 1640255456, + "narHash": "sha256-TYkGB7cON2t4GwMaR9H1MDG2j3btBv2AR37ade8kqTY=", + "owner": "sudormrfbin", + "repo": "cheatsheet.nvim", + "rev": "9716f9aaa94dd1fd6ce59b5aae0e5f25e2a463ef", + "type": "github" }, + "original": { + "owner": "sudormrfbin", + "repo": "cheatsheet.nvim", + "type": "github" + } + }, + "cinnamon-nvim": { + "flake": false, "locked": { - "lastModified": 1686108916, - "narHash": "sha256-looLH5MdY4erLiJw0XwQohGdr0fJL9y6TJY3898RA2U=", - "owner": "ipetkov", - "repo": "crane", - "rev": "8ab1a49432695bd80ff4b7f6c6515da0e926d922", + "lastModified": 1670143364, + "narHash": "sha256-JglXQhoPgN9sQ3yuv0+VQxmKMvoQTu5lbGLSRaQkytI=", + "owner": "declancm", + "repo": "cinnamon.nvim", + "rev": "c406ffda3a0302f32c23b24ab756ea20467d6578", "type": "github" }, "original": { - "owner": "ipetkov", - "ref": "v0.12.2", - "repo": "crane", + "owner": "declancm", + "repo": "cinnamon.nvim", "type": "github" } }, - "devshell": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ], - "systems": "systems_3" + "cmp-buffer": { + "flake": false, + "locked": { + "lastModified": 1660101488, + "narHash": "sha256-dG4U7MtnXThoa/PD+qFtCt76MQ14V1wX8GMYcvxEnbM=", + "owner": "hrsh7th", + "repo": "cmp-buffer", + "rev": "3022dbc9166796b644a841a02de8dd1cc1d311fa", + "type": "github" }, + "original": { + "owner": "hrsh7th", + "repo": "cmp-buffer", + "type": "github" + } + }, + "cmp-nvim-lsp": { + "flake": false, "locked": { - "lastModified": 1692793255, - "narHash": "sha256-yVyj0AE280JkccDHuG1XO9oGxN6bW8ksr/xttXcXzK0=", - "owner": "numtide", - "repo": "devshell", - "rev": "2aa26972b951bc05c3632d4e5ae683cb6771a7c6", + "lastModified": 1687494203, + "narHash": "sha256-mU0soCz79erJXMMqD/FyrJZ0mu2n6fE0deymPzQlxts=", + "owner": "hrsh7th", + "repo": "cmp-nvim-lsp", + "rev": "44b16d11215dce86f253ce0c30949813c0a90765", "type": "github" }, "original": { - "owner": "numtide", - "repo": "devshell", + "owner": "hrsh7th", + "repo": "cmp-nvim-lsp", "type": "github" } }, - "dongsu8142-nur": { - "inputs": { - "nixpkgs": [ - "bella-nur", - "ags", - "nixpkgs" - ] + "cmp-path": { + "flake": false, + "locked": { + "lastModified": 1664784283, + "narHash": "sha256-thppiiV3wjIaZnAXmsh7j3DUc6ceSCvGzviwFUnoPaI=", + "owner": "hrsh7th", + "repo": "cmp-path", + "rev": "91ff86cd9c29299a64f968ebb45846c485725f23", + "type": "github" }, + "original": { + "owner": "hrsh7th", + "repo": "cmp-path", + "type": "github" + } + }, + "cmp-treesitter": { + "flake": false, "locked": { - "lastModified": 1690083492, - "narHash": "sha256-UoIG+sl44U38FTmM2+m4X2Qi5aivjITcUxAkVHouZl4=", - "owner": "dongsu8142", - "repo": "nur", - "rev": "7f5c7067a482e96fe3787e07a54e21041a4d15c0", + "lastModified": 1680745848, + "narHash": "sha256-WOcg6w4M20gpMCZjZ3DpPIA55SGLjV75fhckefiVfU0=", + "owner": "ray-x", + "repo": "cmp-treesitter", + "rev": "389eadd48c27aa6dc0e6b992644704f026802a2e", "type": "github" }, "original": { - "owner": "dongsu8142", - "repo": "nur", + "owner": "ray-x", + "repo": "cmp-treesitter", "type": "github" } }, - "flake-compat": { + "cmp-vsnip": { "flake": false, "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "lastModified": 1669100283, + "narHash": "sha256-2mkN03noOr5vBvRbSb35xZKorSH+8savQNZtgM9+QcM=", + "owner": "hrsh7th", + "repo": "cmp-vsnip", + "rev": "989a8a73c44e926199bfd05fa7a516d51f2d2752", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "hrsh7th", + "repo": "cmp-vsnip", "type": "github" } }, - "flake-compat_2": { + "codewindow-nvim": { "flake": false, "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "lastModified": 1690128662, + "narHash": "sha256-7ntC06PhxfuKnGyXpiW4juP3fWR97DH3Gygwvscv3OY=", + "owner": "gorbit99", + "repo": "codewindow.nvim", + "rev": "11fb5520898d22a563fe6a124a61c0d2887f3d3f", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "gorbit99", + "repo": "codewindow.nvim", "type": "github" } }, - "flake-compat_3": { + "comment-nvim": { "flake": false, "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "lastModified": 1686546603, + "narHash": "sha256-XM9yhp+SGxfAOdN/eDunzM0TMoCJhVth3wpFKNCGf3g=", + "owner": "numToStr", + "repo": "Comment.nvim", + "rev": "176e85eeb63f1a5970d6b88f1725039d85ca0055", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "numToStr", + "repo": "Comment.nvim", "type": "github" } }, - "flake-compat_4": { + "copilot-cmp": { + "flake": false, "locked": { - "lastModified": 1688025799, - "narHash": "sha256-ktpB4dRtnksm9F5WawoIkEneh1nrEvuxb5lJFt1iOyw=", - "owner": "nix-community", - "repo": "flake-compat", - "rev": "8bf105319d44f6b9f0d764efa4fdef9f1cc9ba1c", + "lastModified": 1683831407, + "narHash": "sha256-+MzEGnhlrYRvAfskOwmw69OC1CsPXt7s3z+xPe9XPqs=", + "owner": "zbirenbaum", + "repo": "copilot-cmp", + "rev": "c2cdb3c0f5078b0619055af192295830a7987790", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "flake-compat", + "owner": "zbirenbaum", + "repo": "copilot-cmp", "type": "github" } }, - "flake-compat_5": { + "copilot-lua": { "flake": false, "locked": { - "lastModified": 1668681692, - "narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "009399224d5e398d03b22badca40a37ac85412a1", + "lastModified": 1688190439, + "narHash": "sha256-lD9FdbKKZ6d/BjIfqp0Ust2hqSYNLpCFWxuaKUO9qLs=", + "owner": "zbirenbaum", + "repo": "copilot.lua", + "rev": "e48bd7020a98be217d85c006a298656294fd6210", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", + "owner": "zbirenbaum", + "repo": "copilot.lua", "type": "github" } }, - "flake-parts": { + "crane": { "inputs": { - "nixpkgs-lib": [ + "flake-compat": "flake-compat_2", + "flake-utils": "flake-utils_2", + "nixpkgs": [ + "catppuccinifier", "nixpkgs" - ] + ], + "rust-overlay": "rust-overlay_2" }, "locked": { - "lastModified": 1690933134, - "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", + "lastModified": 1687310026, + "narHash": "sha256-20RHFbrnC+hsG4Hyeg/58LvQAK7JWfFItTPFAFamu8E=", + "owner": "ipetkov", + "repo": "crane", + "rev": "116b32c30b5ff28e49f4fcbeeb1bbe3544593204", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "flake-parts", + "owner": "ipetkov", + "repo": "crane", "type": "github" } }, - "flake-parts_2": { + "crane_2": { "inputs": { - "nixpkgs-lib": [ + "nixpkgs": [ "lanzaboote", "nixpkgs" ] }, "locked": { - "lastModified": 1688466019, - "narHash": "sha256-VeM2akYrBYMsb4W/MmBo1zmaMfgbL4cH3Pu8PGyIwJ0=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "8e8d955c22df93dbe24f19ea04f47a74adbdc5ec", + "lastModified": 1697840921, + "narHash": "sha256-zXHwu104SQOxogkMgg+w22c3+zI/FvK83TAkfLmeKw0=", + "owner": "ipetkov", + "repo": "crane", + "rev": "758ae442227103fa501276e8225609a11c99718e", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "flake-parts", + "owner": "ipetkov", + "repo": "crane", "type": "github" } }, - "flake-parts_3": { - "inputs": { - "nixpkgs-lib": "nixpkgs-lib" - }, + "crates-nvim": { + "flake": false, "locked": { - "lastModified": 1688466019, - "narHash": "sha256-VeM2akYrBYMsb4W/MmBo1zmaMfgbL4cH3Pu8PGyIwJ0=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "8e8d955c22df93dbe24f19ea04f47a74adbdc5ec", + "lastModified": 1688295570, + "narHash": "sha256-ah+fTmzkZn+xuL3sG2RxlCtDiFsRv3SY1iJzYKMIaMg=", + "owner": "Saecki", + "repo": "crates.nvim", + "rev": "4ce7c51b881e58f1e2f8f437f30e4e583cbac319", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "flake-parts", + "owner": "Saecki", + "repo": "crates.nvim", "type": "github" } }, - "flake-parts_4": { - "inputs": { - "nixpkgs-lib": "nixpkgs-lib_2" - }, + "dashboard-nvim": { + "flake": false, "locked": { - "lastModified": 1690933134, - "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", + "lastModified": 1690351087, + "narHash": "sha256-aVMugjgA9lnORUVDBpa8G800Ev86htP4hDGrBq6Sw6s=", + "owner": "glepnir", + "repo": "dashboard-nvim", + "rev": "c17d3210b3dec8798b4fc82a11c542989251f85d", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "flake-parts", + "owner": "glepnir", + "repo": "dashboard-nvim", "type": "github" } }, - "flake-parts_5": { + "devshell": { "inputs": { - "nixpkgs-lib": [ - "nixpkgs-wayland", - "nix-eval-jobs", + "nixpkgs": [ "nixpkgs" - ] + ], + "systems": "systems_4" }, "locked": { - "lastModified": 1690933134, - "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", + "lastModified": 1695973661, + "narHash": "sha256-BP2H4c42GThPIhERtTpV1yCtwQHYHEKdRu7pjrmQAwo=", + "owner": "numtide", + "repo": "devshell", + "rev": "cd4e2fda3150dd2f689caeac07b7f47df5197c31", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "flake-parts", + "owner": "numtide", + "repo": "devshell", "type": "github" } }, - "flake-parts_6": { - "inputs": { - "nixpkgs-lib": [ - "schizofox", - "nixpak", - "hercules-ci-effects", - "hercules-ci-agent", - "nixpkgs" - ] + "diffview-nvim": { + "flake": false, + "locked": { + "lastModified": 1689788060, + "narHash": "sha256-0tsgwI/qZm8Gj3NyN9CA+YHf3qim7vGXI+vbEcFBKbQ=", + "owner": "sindrets", + "repo": "diffview.nvim", + "rev": "e91110d2a7f8e2f667666aba6ea089ff823f8748", + "type": "github" }, + "original": { + "owner": "sindrets", + "repo": "diffview.nvim", + "type": "github" + } + }, + "dirt-samples-src": { + "flake": false, "locked": { - "lastModified": 1688466019, - "narHash": "sha256-VeM2akYrBYMsb4W/MmBo1zmaMfgbL4cH3Pu8PGyIwJ0=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "8e8d955c22df93dbe24f19ea04f47a74adbdc5ec", + "lastModified": 1588278411, + "narHash": "sha256-h8vQxRym6QzNLOTZU7A43VCHuG0H77l+BFwXnC0L1CE=", + "owner": "tidalcycles", + "repo": "dirt-samples", + "rev": "66d432418c9a7d82cf049d9246adfa62f46df2a6", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "flake-parts", + "owner": "tidalcycles", + "ref": "master", + "repo": "dirt-samples", "type": "github" } }, - "flake-utils": { - "inputs": { - "systems": "systems" + "dracula": { + "flake": false, + "locked": { + "lastModified": 1690594744, + "narHash": "sha256-gblqxRTphGBpEOx57/4oU/B50O0OguIm1bFtd4LXuQ4=", + "owner": "Mofiqul", + "repo": "dracula.nvim", + "rev": "9fe831e685a76e1a1898a694623b33247c4d036c", + "type": "github" }, + "original": { + "owner": "Mofiqul", + "repo": "dracula.nvim", + "type": "github" + } + }, + "dressing-nvim": { + "flake": false, "locked": { - "lastModified": 1685518550, - "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "lastModified": 1690648598, + "narHash": "sha256-hndRErSXhX1BHM90nuhiZkgHwkclLEMv5vtF+GDzUP4=", + "owner": "stevearc", + "repo": "dressing.nvim", + "rev": "829bc80400651aea31b03d8fc9a99135512fe67a", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "stevearc", + "repo": "dressing.nvim", "type": "github" } }, - "flake-utils_2": { - "inputs": { - "systems": "systems_2" + "elixir-ls": { + "flake": false, + "locked": { + "lastModified": 1690526097, + "narHash": "sha256-lR1xsOJhz0W/Z3E2EUWujpUvpgUkLLDr0E6Ao31zi8s=", + "owner": "elixir-lsp", + "repo": "elixir-ls", + "rev": "216ff0e2969c2bbe45d324c4d6a5f08e6b681f5e", + "type": "github" }, + "original": { + "owner": "elixir-lsp", + "repo": "elixir-ls", + "type": "github" + } + }, + "elixir-tools": { + "flake": false, "locked": { - "lastModified": 1687171271, - "narHash": "sha256-BJlq+ozK2B1sJDQXS3tzJM5a+oVZmi1q0FlBK/Xqv7M=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "abfb11bd1aec8ced1c9bb9adfe68018230f4fb3c", + "lastModified": 1690555653, + "narHash": "sha256-7wDEChXTUGp8ONT6jufIJp05vawzo4AXg35ELNLvysA=", + "owner": "elixir-tools", + "repo": "elixir-tools.nvim", + "rev": "883933b57c9150c71ad2b99a4080685d83e095b8", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "elixir-tools", + "repo": "elixir-tools.nvim", "type": "github" } }, - "flake-utils_3": { - "inputs": { - "systems": "systems_5" + "fidget-nvim": { + "flake": false, + "locked": { + "lastModified": 1686378433, + "narHash": "sha256-N3O/AvsD6Ckd62kDEN4z/K5A3SZNR15DnQeZhH6/Rr0=", + "owner": "j-hui", + "repo": "fidget.nvim", + "rev": "90c22e47be057562ee9566bad313ad42d622c1d3", + "type": "github" }, + "original": { + "owner": "j-hui", + "ref": "legacy", + "repo": "fidget.nvim", + "type": "github" + } + }, + "flake-compat": { + "flake": false, "locked": { - "lastModified": 1689068808, - "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "flake-utils_4": { - "inputs": { - "systems": "systems_6" + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_3": { + "flake": false, "locked": { - "lastModified": 1689068808, - "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "flake-utils_5": { - "inputs": { - "systems": "systems_7" + "flake-compat_4": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_5": { + "flake": false, "locked": { - "lastModified": 1687709756, - "narHash": "sha256-Y5wKlQSkgEK2weWdOu4J3riRd+kV/VCgHsqLNTTWQ/0=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "dbabf0ca0c0c4bce6ea5eaf65af5cb694d2082c7", + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "flake-utils_6": { - "inputs": { - "systems": "systems_8" + "flake-compat_6": { + "locked": { + "lastModified": 1688025799, + "narHash": "sha256-ktpB4dRtnksm9F5WawoIkEneh1nrEvuxb5lJFt1iOyw=", + "owner": "nix-community", + "repo": "flake-compat", + "rev": "8bf105319d44f6b9f0d764efa4fdef9f1cc9ba1c", + "type": "github" }, + "original": { + "owner": "nix-community", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_7": { + "flake": false, "locked": { - "lastModified": 1692799911, - "narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44", + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "flake-utils_7": { - "inputs": { - "systems": "systems_9" + "flake-compat_8": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_9": { + "flake": false, "locked": { - "lastModified": 1681202837, - "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "lastModified": 1668681692, + "narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "009399224d5e398d03b22badca40a37ac85412a1", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "flake-utils_8": { + "flake-parts": { "inputs": { - "systems": "systems_10" + "nixpkgs-lib": [ + "nixpkgs" + ] }, "locked": { - "lastModified": 1681202837, - "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "lastModified": 1696343447, + "narHash": "sha256-B2xAZKLkkeRFG5XcHHSXXcP7To9Xzr59KXeZiRf4vdQ=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "c9afaba3dfa4085dbd2ccb38dfade5141e33d9d4", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "flake-parts", "type": "github" } }, - "gitignore": { + "flake-parts_2": { "inputs": { - "nixpkgs": [ + "nixpkgs-lib": [ "lanzaboote", - "pre-commit-hooks-nix", "nixpkgs" ] }, "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "lastModified": 1696343447, + "narHash": "sha256-B2xAZKLkkeRFG5XcHHSXXcP7To9Xzr59KXeZiRf4vdQ=", "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "repo": "flake-parts", + "rev": "c9afaba3dfa4085dbd2ccb38dfade5141e33d9d4", "type": "github" }, "original": { "owner": "hercules-ci", - "repo": "gitignore.nix", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_3": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1693611461, + "narHash": "sha256-aPODl8vAgGQ0ZYFIRisxYG5MOGSkIczvu2Cd8Gb9+1Y=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "7f53fdb7bdc5bb237da7fefef12d099e4fd611ca", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_4": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_2" + }, + "locked": { + "lastModified": 1696343447, + "narHash": "sha256-B2xAZKLkkeRFG5XcHHSXXcP7To9Xzr59KXeZiRf4vdQ=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "c9afaba3dfa4085dbd2ccb38dfade5141e33d9d4", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_5": { + "inputs": { + "nixpkgs-lib": [ + "nixpkgs-wayland", + "nix-eval-jobs", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1696343447, + "narHash": "sha256-B2xAZKLkkeRFG5XcHHSXXcP7To9Xzr59KXeZiRf4vdQ=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "c9afaba3dfa4085dbd2ccb38dfade5141e33d9d4", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_6": { + "inputs": { + "nixpkgs-lib": [ + "schizofox", + "nixpak", + "hercules-ci-effects", + "hercules-ci-agent", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688466019, + "narHash": "sha256-VeM2akYrBYMsb4W/MmBo1zmaMfgbL4cH3Pu8PGyIwJ0=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "8e8d955c22df93dbe24f19ea04f47a74adbdc5ec", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-schemas": { + "locked": { + "lastModified": 1697467827, + "narHash": "sha256-j8SR19V1SRysyJwpOBF4TLuAvAjF5t+gMiboN4gYQDU=", + "owner": "DeterminateSystems", + "repo": "flake-schemas", + "rev": "764932025c817d4e500a8d2a4d8c565563923d29", + "type": "github" + }, + "original": { + "owner": "DeterminateSystems", + "repo": "flake-schemas", + "type": "github" + } + }, + "flake-schemas_2": { + "locked": { + "lastModified": 1693392497, + "narHash": "sha256-/fuUqkWIfRHaZb9cFTWWVHqSxpq/n6NlAvXqBuFTJqs=", + "owner": "DeterminateSystems", + "repo": "flake-schemas", + "rev": "9af39734fcd4813be17cadef98fc47285eaf7888", + "type": "github" + }, + "original": { + "owner": "DeterminateSystems", + "repo": "flake-schemas", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_10": { + "inputs": { + "systems": "systems_12" + }, + "locked": { + "lastModified": 1681202837, + "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1685518550, + "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1687171271, + "narHash": "sha256-BJlq+ozK2B1sJDQXS3tzJM5a+oVZmi1q0FlBK/Xqv7M=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "abfb11bd1aec8ced1c9bb9adfe68018230f4fb3c", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "inputs": { + "systems": "systems_5" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_5": { + "inputs": { + "systems": "systems_7" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_6": { + "locked": { + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_7": { + "inputs": { + "systems": "systems_9" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_8": { + "inputs": { + "systems": "systems_10" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_9": { + "inputs": { + "systems": "systems_11" + }, + "locked": { + "lastModified": 1681202837, + "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flutter-tools": { + "flake": false, + "locked": { + "lastModified": 1690188839, + "narHash": "sha256-h8s5g6KU7dMesDqiwzv2MmUGk6jlU5lBnuVA3LaoI1g=", + "owner": "akinsho", + "repo": "flutter-tools.nvim", + "rev": "561d85b16d8ca2938820a9c26b2fe74096d89c81", + "type": "github" + }, + "original": { + "owner": "akinsho", + "repo": "flutter-tools.nvim", + "type": "github" + } + }, + "gesture-nvim": { + "flake": false, + "locked": { + "lastModified": 1687655077, + "narHash": "sha256-ps/dAKIga2ZVunwj+KU/Iej4PGZbBvm5ZzcK30EiKMc=", + "owner": "notomo", + "repo": "gesture.nvim", + "rev": "aa273e7982943ac6ccf6b864f3fd40ad287a9fe2", + "type": "github" + }, + "original": { + "owner": "notomo", + "repo": "gesture.nvim", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "lanzaboote", + "pre-commit-hooks-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_2": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitsigns-nvim": { + "flake": false, + "locked": { + "lastModified": 1690463120, + "narHash": "sha256-kraK0GP5aLGbh1eVZCm41D6BztjFxthSXGnE5CxhrZs=", + "owner": "lewis6991", + "repo": "gitsigns.nvim", + "rev": "5d73da785a3c05fd63ac31769079db05169a6ec7", + "type": "github" + }, + "original": { + "owner": "lewis6991", + "repo": "gitsigns.nvim", + "type": "github" + } + }, + "glow-nvim": { + "flake": false, + "locked": { + "lastModified": 1690579937, + "narHash": "sha256-ZDlQfSJHq9CbOpTDgmIoMq4gDzHxoUslFfN5XKtrDtM=", + "owner": "ellisonleao", + "repo": "glow.nvim", + "rev": "8942dfb05794f436af4fbc90a34393f1fd36f361", + "type": "github" + }, + "original": { + "owner": "ellisonleao", + "repo": "glow.nvim", + "type": "github" + } + }, + "haskell-flake": { + "locked": { + "lastModified": 1684780604, + "narHash": "sha256-2uMZsewmRn7rRtAnnQNw1lj0uZBMh4m6Cs/7dV5YF08=", + "owner": "srid", + "repo": "haskell-flake", + "rev": "74210fa80a49f1b6f67223debdbf1494596ff9f2", + "type": "github" + }, + "original": { + "owner": "srid", + "ref": "0.3.0", + "repo": "haskell-flake", + "type": "github" + } + }, + "hercules-ci-agent": { + "inputs": { + "flake-parts": "flake-parts_6", + "haskell-flake": "haskell-flake", + "nixpkgs": "nixpkgs_11" + }, + "locked": { + "lastModified": 1688568579, + "narHash": "sha256-ON0M56wtY/TIIGPkXDlJboAmuYwc73Hi8X9iJGtxOhM=", + "owner": "hercules-ci", + "repo": "hercules-ci-agent", + "rev": "367dd8cd649b57009a6502e878005a1e54ad78c5", + "type": "github" + }, + "original": { + "id": "hercules-ci-agent", + "type": "indirect" + } + }, + "hercules-ci-effects": { + "inputs": { + "flake-parts": [ + "schizofox", + "nixpak", + "flake-parts" + ], + "hercules-ci-agent": "hercules-ci-agent", + "nixpkgs": [ + "schizofox", + "nixpak", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1697031886, + "narHash": "sha256-oTMPX8dGC7yxSwrbF4NuPNQsUEcHB1dusW2yEbFD5zg=", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "rev": "178b36dc3a75c96efc25477d45eafc37ba1fafc3", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "type": "github" + } + }, + "highlight-undo": { + "flake": false, + "locked": { + "lastModified": 1695227852, + "narHash": "sha256-I1AwVYqpJNA3K1AwGy/VgPnbrYvX19qfI9bQFZNu1SU=", + "owner": "tzachar", + "repo": "highlight-undo.nvim", + "rev": "50a6884a8476be04ecce8f1c4ed692c5000ef0a1", + "type": "github" + }, + "original": { + "owner": "tzachar", + "repo": "highlight-undo.nvim", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1698162493, + "narHash": "sha256-Zehw3cWiTXGGlDDjzTgIX1BhWG+049D/RcSMAiypAcM=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "14b54157201fd574b0fa1b3ce7394c9d3a87fbc1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_2": { + "inputs": { + "nixpkgs": [ + "schizofox", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1697662575, + "narHash": "sha256-fVtd4Le9edB831xyGWu0aqSfg6YVbkCNMX/IE3SUIdk=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "3433206e51766b4164dad368a81325efbf343fbe", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "hop-nvim": { + "flake": false, + "locked": { + "lastModified": 1684332066, + "narHash": "sha256-xdjFbdp0+S3pVdwcOFmad8PMUU033WeDzswOSdxSQjg=", + "owner": "phaazon", + "repo": "hop.nvim", + "rev": "03f0434869f1f38868618198b5f4f2ab6d39aef2", + "type": "github" + }, + "original": { + "owner": "phaazon", + "repo": "hop.nvim", + "type": "github" + } + }, + "hyprland": { + "inputs": { + "hyprland-protocols": "hyprland-protocols", + "nixpkgs": "nixpkgs_4", + "systems": "systems_6", + "wlroots": "wlroots", + "xdph": "xdph" + }, + "locked": { + "lastModified": 1698190104, + "narHash": "sha256-40TEEIjlIb0hJE/yRsjLBwjkRYkj/4QRTkN1Op86umw=", + "owner": "hyprwm", + "repo": "Hyprland", + "rev": "a1b138a6258b00787cea43bddc48b7caa8cca3a0", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "Hyprland", + "type": "github" + } + }, + "hyprland-protocols": { + "inputs": { + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1691753796, + "narHash": "sha256-zOEwiWoXk3j3+EoF3ySUJmberFewWlagvewDRuWYAso=", + "owner": "hyprwm", + "repo": "hyprland-protocols", + "rev": "0c2ce70625cb30aef199cb388f99e19a61a6ce03", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprland-protocols", + "type": "github" + } + }, + "hyprland-protocols_2": { + "inputs": { + "nixpkgs": [ + "xdg-portal-hyprland", + "nixpkgs" + ], + "systems": [ + "xdg-portal-hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1691753796, + "narHash": "sha256-zOEwiWoXk3j3+EoF3ySUJmberFewWlagvewDRuWYAso=", + "owner": "hyprwm", + "repo": "hyprland-protocols", + "rev": "0c2ce70625cb30aef199cb388f99e19a61a6ce03", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprland-protocols", + "type": "github" + } + }, + "hyprpicker": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1697019850, + "narHash": "sha256-o5YxKQjs2SGMCt7I7U+CFleAVzXjoXAWRicMNATQQ94=", + "owner": "hyprwm", + "repo": "hyprpicker", + "rev": "94010d6b9afae7d9dfde910cf18b81d148374426", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprpicker", + "type": "github" + } + }, + "icon-picker-nvim": { + "flake": false, + "locked": { + "lastModified": 1683205244, + "narHash": "sha256-/oi2Kj7GDXzN3ccPoxyxXtQTYSxtZndgELZa2XgZ3U8=", + "owner": "ziontee113", + "repo": "icon-picker.nvim", + "rev": "e6dca182518eeb7a51470c13605a5bce08a816e4", + "type": "github" + }, + "original": { + "owner": "ziontee113", + "repo": "icon-picker.nvim", + "type": "github" + } + }, + "indent-blankline": { + "flake": false, + "locked": { + "lastModified": 1688727830, + "narHash": "sha256-efMRkxjbr6o7kSKAEn0Kaw8lsDubRmc1N0Kd1BZ3A7k=", + "owner": "lukas-reineke", + "repo": "indent-blankline.nvim", + "rev": "4541d690816cb99a7fc248f1486aa87f3abce91c", + "type": "github" + }, + "original": { + "owner": "lukas-reineke", + "repo": "indent-blankline.nvim", + "type": "github" + } + }, + "kommentary": { + "flake": false, + "locked": { + "lastModified": 1672983049, + "narHash": "sha256-N4n5tjNB1yX/QxH+t5aG0VxNwZhUJejv0b5V62WEKDU=", + "owner": "b3nj5m1n", + "repo": "kommentary", + "rev": "3a80117148c6798972bb69414423311ab151d368", + "type": "github" + }, + "original": { + "owner": "b3nj5m1n", + "repo": "kommentary", + "type": "github" + } + }, + "lanzaboote": { + "inputs": { + "crane": "crane_2", + "flake-compat": "flake-compat_3", + "flake-parts": "flake-parts_2", + "flake-utils": "flake-utils_5", + "nixpkgs": [ + "nixpkgs" + ], + "pre-commit-hooks-nix": "pre-commit-hooks-nix", + "rust-overlay": "rust-overlay_3" + }, + "locked": { + "lastModified": 1698100456, + "narHash": "sha256-Hx9ZVZYARVbzJB0fFNe/lPE9a4oP1dDGJnl3siRtBJ0=", + "owner": "nix-community", + "repo": "lanzaboote", + "rev": "bb380e19488ec6105d07b57c23ac518be51bf901", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "lanzaboote", + "type": "github" + } + }, + "leap-nvim": { + "flake": false, + "locked": { + "lastModified": 1690120911, + "narHash": "sha256-9GFZ5CuR92kFGwh/ouqSSp14eOLZLpzpoFTEuYL7biQ=", + "owner": "ggandor", + "repo": "leap.nvim", + "rev": "5efe985cf68fac3b6a6dfe7a75fbfaca8db2af9c", + "type": "github" + }, + "original": { + "owner": "ggandor", + "repo": "leap.nvim", + "type": "github" + } + }, + "lib-aggregate": { + "inputs": { + "flake-utils": "flake-utils_8", + "nixpkgs-lib": "nixpkgs-lib_3" + }, + "locked": { + "lastModified": 1697976504, + "narHash": "sha256-sU8q83TEaafIe5d7L6Dc2alRhWT898aB0+6EXcfao1I=", + "owner": "nix-community", + "repo": "lib-aggregate", + "rev": "2e96d2f9d80f80bd22cd7c603985f2b03cf186fc", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "lib-aggregate", + "type": "github" + } + }, + "lowdown-src": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "lsp-lines": { + "flake": false, + "locked": { + "lastModified": 1684163755, + "narHash": "sha256-Zhf2xitLWtE+dWqhvWtLM1K1WdtBvkqqoRLSYIO42oY=", + "owner": "~whynothugo", + "repo": "lsp_lines.nvim", + "rev": "f53af96d4789eef39a082dbcce078d2bfc384ece", + "type": "sourcehut" + }, + "original": { + "owner": "~whynothugo", + "repo": "lsp_lines.nvim", + "type": "sourcehut" + } + }, + "lsp-signature": { + "flake": false, + "locked": { + "lastModified": 1690267930, + "narHash": "sha256-qvcs0KuO2/NdtiTZIxJ2vrwV0I5PjzjMvoAePPasaJM=", + "owner": "ray-x", + "repo": "lsp_signature.nvim", + "rev": "58d4e810801da74c29313da86075d6aea537501f", + "type": "github" + }, + "original": { + "owner": "ray-x", + "repo": "lsp_signature.nvim", + "type": "github" + } + }, + "lspkind": { + "flake": false, + "locked": { + "lastModified": 1683275543, + "narHash": "sha256-S+qZm51hw/cRujIfHV/1x1fYyCKI4XQ0utSL8uy4l6I=", + "owner": "onsails", + "repo": "lspkind-nvim", + "rev": "57610d5ab560c073c465d6faf0c19f200cb67e6e", + "type": "github" + }, + "original": { + "owner": "onsails", + "repo": "lspkind-nvim", + "type": "github" + } + }, + "lspsaga": { + "flake": false, + "locked": { + "lastModified": 1670360222, + "narHash": "sha256-7ENInq3LAPPTdm0Fb7klOc630j8m4LRj1kLZZFYLh68=", + "owner": "tami5", + "repo": "lspsaga.nvim", + "rev": "5faeec9f2508d2d49a66c0ac0d191096b4e3fa81", + "type": "github" + }, + "original": { + "owner": "tami5", + "repo": "lspsaga.nvim", + "type": "github" + } + }, + "lualine": { + "flake": false, + "locked": { + "lastModified": 1683213422, + "narHash": "sha256-ltHE8UIquGo07BSlFGM1l3wmTNN43i8kx6QY7Fj2CNo=", + "owner": "hoob3rt", + "repo": "lualine.nvim", + "rev": "05d78e9fd0cdfb4545974a5aa14b1be95a86e9c9", + "type": "github" + }, + "original": { + "owner": "hoob3rt", + "repo": "lualine.nvim", + "type": "github" + } + }, + "mind-nvim": { + "flake": false, + "locked": { + "lastModified": 1679526071, + "narHash": "sha256-JIhAhQYGLLRucwlhzfckQYU5qjqbHtNH52JlGS5a79w=", + "owner": "phaazon", + "repo": "mind.nvim", + "rev": "002137dd7cf97865ebd01b6a260209d2daf2da66", + "type": "github" + }, + "original": { + "owner": "phaazon", + "repo": "mind.nvim", + "type": "github" + } + }, + "minimap-vim": { + "flake": false, + "locked": { + "lastModified": 1690301768, + "narHash": "sha256-yRWZH9caSxrWjUXlM84fU90tZjNfX97m0m491ZsIHxA=", + "owner": "wfxr", + "repo": "minimap.vim", + "rev": "74573b63b9ef0583262b6bf6ef209eb7f3b06b94", + "type": "github" + }, + "original": { + "owner": "wfxr", + "repo": "minimap.vim", + "type": "github" + } + }, + "modes-nvim": { + "flake": false, + "locked": { + "lastModified": 1682778003, + "narHash": "sha256-qrGgraBdAvIc6AXqMMWESlOV29lM5zC1du1r5L2kpQQ=", + "owner": "mvllow", + "repo": "modes.nvim", + "rev": "4d97a51ebbdb649b85f6d79da0009fddd7081a6b", + "type": "github" + }, + "original": { + "owner": "mvllow", + "repo": "modes.nvim", + "type": "github" + } + }, + "naersk": { + "inputs": { + "nixpkgs": [ + "neovim-flake", + "rnix-lsp", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1655042882, + "narHash": "sha256-9BX8Fuez5YJlN7cdPO63InoyBy7dm3VlJkkmTt6fS1A=", + "owner": "nix-community", + "repo": "naersk", + "rev": "cddffb5aa211f50c4b8750adbec0bbbdfb26bb9f", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "naersk", + "type": "github" + } + }, + "neodev-nvim": { + "flake": false, + "locked": { + "lastModified": 1695449121, + "narHash": "sha256-WisbNLKEz0IgO7gLDA2quNzK69hJaHzmvWkZSUPQb6k=", + "owner": "folke", + "repo": "neodev.nvim", + "rev": "c8e126393a34939fb448d48eeddb510971739e3a", + "type": "github" + }, + "original": { + "owner": "folke", + "repo": "neodev.nvim", + "type": "github" + } + }, + "neovim-flake": { + "inputs": { + "alpha-nvim": "alpha-nvim", + "bufdelete-nvim": "bufdelete-nvim", + "catppuccin": "catppuccin_2", + "ccc": "ccc", + "cellular-automaton": "cellular-automaton", + "cheatsheet-nvim": "cheatsheet-nvim", + "cinnamon-nvim": "cinnamon-nvim", + "cmp-buffer": "cmp-buffer", + "cmp-nvim-lsp": "cmp-nvim-lsp", + "cmp-path": "cmp-path", + "cmp-treesitter": "cmp-treesitter", + "cmp-vsnip": "cmp-vsnip", + "codewindow-nvim": "codewindow-nvim", + "comment-nvim": "comment-nvim", + "copilot-cmp": "copilot-cmp", + "copilot-lua": "copilot-lua", + "crates-nvim": "crates-nvim", + "dashboard-nvim": "dashboard-nvim", + "diffview-nvim": "diffview-nvim", + "dracula": "dracula", + "dressing-nvim": "dressing-nvim", + "elixir-ls": "elixir-ls", + "elixir-tools": "elixir-tools", + "fidget-nvim": "fidget-nvim", + "flake-parts": [ + "flake-parts" + ], + "flake-utils": [ + "flake-utils" + ], + "flutter-tools": "flutter-tools", + "gesture-nvim": "gesture-nvim", + "gitsigns-nvim": "gitsigns-nvim", + "glow-nvim": "glow-nvim", + "highlight-undo": "highlight-undo", + "hop-nvim": "hop-nvim", + "icon-picker-nvim": "icon-picker-nvim", + "indent-blankline": "indent-blankline", + "kommentary": "kommentary", + "leap-nvim": "leap-nvim", + "lsp-lines": "lsp-lines", + "lsp-signature": "lsp-signature", + "lspkind": "lspkind", + "lspsaga": "lspsaga", + "lualine": "lualine", + "mind-nvim": "mind-nvim", + "minimap-vim": "minimap-vim", + "modes-nvim": "modes-nvim", + "neodev-nvim": "neodev-nvim", + "nil": [ + "nil" + ], + "nixpkgs": [ + "nixpkgs" + ], + "nmd": "nmd", + "noice-nvim": "noice-nvim", + "none-ls": "none-ls", + "nui-nvim": "nui-nvim", + "nvim-autopairs": "nvim-autopairs", + "nvim-bufferline-lua": "nvim-bufferline-lua", + "nvim-cmp": "nvim-cmp", + "nvim-code-action-menu": "nvim-code-action-menu", + "nvim-colorizer-lua": "nvim-colorizer-lua", + "nvim-compe": "nvim-compe", + "nvim-cursorline": "nvim-cursorline", + "nvim-dap": "nvim-dap", + "nvim-dap-ui": "nvim-dap-ui", + "nvim-lightbulb": "nvim-lightbulb", + "nvim-lspconfig": "nvim-lspconfig", + "nvim-navbuddy": "nvim-navbuddy", + "nvim-navic": "nvim-navic", + "nvim-neoclip": "nvim-neoclip", + "nvim-notify": "nvim-notify", + "nvim-session-manager": "nvim-session-manager", + "nvim-surround": "nvim-surround", + "nvim-tree-lua": "nvim-tree-lua", + "nvim-treesitter-context": "nvim-treesitter-context", + "nvim-ts-autotag": "nvim-ts-autotag", + "nvim-web-devicons": "nvim-web-devicons", + "obsidian-nvim": "obsidian-nvim", + "onedark": "onedark", + "orgmode-nvim": "orgmode-nvim", + "oxocarbon": "oxocarbon", + "plenary-nvim": "plenary-nvim", + "presence-nvim": "presence-nvim", + "project-nvim": "project-nvim", + "registers": "registers", + "rnix-lsp": "rnix-lsp", + "rust-tools": "rust-tools", + "scrollbar-nvim": "scrollbar-nvim", + "smartcolumn": "smartcolumn", + "sqls-nvim": "sqls-nvim", + "systems": "systems_8", + "tabular": "tabular", + "telescope": "telescope", + "tidalcycles": "tidalcycles", + "todo-comments": "todo-comments", + "toggleterm-nvim": "toggleterm-nvim", + "tokyonight": "tokyonight", + "trouble": "trouble", + "vim-dirtytalk": "vim-dirtytalk", + "vim-illuminate": "vim-illuminate", + "vim-markdown": "vim-markdown", + "vim-repeat": "vim-repeat", + "vim-startify": "vim-startify", + "vim-vsnip": "vim-vsnip", + "which-key": "which-key", + "zig": "zig" + }, + "locked": { + "lastModified": 1698081721, + "narHash": "sha256-V5WhcZbPIod8jE493Cnvzciy7ChShb6LCESw1eMUWlQ=", + "owner": "NotAShelf", + "repo": "neovim-flake", + "rev": "2b48b6d8443e3780636e8a71eb075f00aedcfd94", + "type": "github" + }, + "original": { + "owner": "NotAShelf", + "repo": "neovim-flake", + "type": "github" + } + }, + "nh": { + "inputs": { + "flake-parts": "flake-parts_3", + "nix-filter": "nix-filter", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1698045010, + "narHash": "sha256-jqGzR+REGYKYrpgTlVZeKqcpBSmQxrapkcWxCBh/Ebs=", + "owner": "viperML", + "repo": "nh", + "rev": "385e537de3c833dc4cc2ee7522b1852b030cbe06", + "type": "github" + }, + "original": { + "owner": "viperML", + "repo": "nh", + "type": "github" + } + }, + "nil": { + "inputs": { + "flake-utils": "flake-utils_7", + "nixpkgs": [ + "nixpkgs" + ], + "rust-overlay": [ + "rust-overlay" + ] + }, + "locked": { + "lastModified": 1697710615, + "narHash": "sha256-YL63eoy3C/WeDxwctbv9dJBjqBabx8cO7lVTlVn3FVI=", + "owner": "oxalica", + "repo": "nil", + "rev": "bd93024db616a528473a7210d2756c7118155de9", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "nil", + "type": "github" + } + }, + "nix-eval-jobs": { + "inputs": { + "flake-parts": "flake-parts_5", + "nixpkgs": "nixpkgs_10", + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1697679370, + "narHash": "sha256-E4iEs004owoShYK0MBDD6uRXCgZdxl//hYijvSakg0k=", + "owner": "nix-community", + "repo": "nix-eval-jobs", + "rev": "01a606e119963957eefaf1b22ef92b69b90f5b85", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-eval-jobs", + "type": "github" + } + }, + "nix-filter": { + "locked": { + "lastModified": 1694857738, + "narHash": "sha256-bxxNyLHjhu0N8T3REINXQ2ZkJco0ABFPn6PIe2QUfqo=", + "owner": "numtide", + "repo": "nix-filter", + "rev": "41fd48e00c22b4ced525af521ead8792402de0ea", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "nix-filter", + "type": "github" + } + }, + "nix-gaming": { + "inputs": { + "flake-parts": "flake-parts_4", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1698109854, + "narHash": "sha256-Vg+LytTlOpgO0dWZoS/CsYCNQllG0p0I+XLWrkRrU8E=", + "owner": "fufexan", + "repo": "nix-gaming", + "rev": "5e8f1c9ae134b459475705a2eb9b81e6dc667e43", + "type": "github" + }, + "original": { + "owner": "fufexan", + "repo": "nix-gaming", + "type": "github" + } + }, + "nix-index-db": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1697946153, + "narHash": "sha256-7k7qIwWLaYPgQ4fxmEdew3yCffhK6rM4I4Jo3X/79DA=", + "owner": "nix-community", + "repo": "nix-index-database", + "rev": "5a2006282caaf32663cdcd582c5b18809c7d7d8d", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-index-database", + "type": "github" + } + }, + "nix-ld": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1686849676, + "narHash": "sha256-+z9t7BLugZO1WhyYEq6FI38TMh2EwfgfAv3RDFSjwtc=", + "owner": "Mic92", + "repo": "nix-ld", + "rev": "3abd605e56b5b34ec630bb10ba85f98c93cc05b2", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "nix-ld", + "type": "github" + } + }, + "nixSchemas": { + "inputs": { + "flake-compat": "flake-compat_5", + "flake-schemas": "flake-schemas_2", + "lowdown-src": "lowdown-src", + "nixpkgs": "nixpkgs_8", + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "lastModified": 1697822067, + "narHash": "sha256-7HCcrF6GqIAreKvzt74do1/Urvp+b901Hckf5+WgR9M=", + "owner": "DeterminateSystems", + "repo": "nix", + "rev": "84867fa212fe08feeb27b668c4c78bc9eaf74e17", + "type": "github" + }, + "original": { + "owner": "DeterminateSystems", + "ref": "flake-schemas", + "repo": "nix", + "type": "github" + } + }, + "nixpak": { + "inputs": { + "flake-parts": [ + "schizofox", + "flake-parts" + ], + "hercules-ci-effects": "hercules-ci-effects", + "nixpkgs": [ + "schizofox", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1697667112, + "narHash": "sha256-/Mo2rCALFjplsA+e/H+V3QfpZ4BFUwoWFVXQqBLnClM=", + "owner": "nixpak", + "repo": "nixpak", + "rev": "a7640d51f24a462dee71f5dfe22f24c000dc5bdf", + "type": "github" + }, + "original": { + "owner": "nixpak", + "repo": "nixpak", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1687379288, + "narHash": "sha256-cSuwfiqYfeVyqzCRkU9AvLTysmEuSal8nh6CYr+xWog=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ef0bc3976340dab9a4e087a0bcff661a8b2e87f3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-22_11": { + "locked": { + "lastModified": 1669558522, + "narHash": "sha256-yqxn+wOiPqe6cxzOo4leeJOp1bXE/fjPEi/3F/bBHv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ce5fe99df1f15a09a91a86be9738d68fadfbad82", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-22.11", + "type": "indirect" + } + }, + "nixpkgs-23_05": { + "locked": { + "lastModified": 1684782344, + "narHash": "sha256-SHN8hPYYSX0thDrMLMWPWYulK3YFgASOrCsIL3AJ78g=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "8966c43feba2c701ed624302b6a935f97bcbdf88", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-23.05", + "type": "indirect" + } + }, + "nixpkgs-lib": { + "locked": { + "dir": "lib", + "lastModified": 1693471703, + "narHash": "sha256-0l03ZBL8P1P6z8MaSDS/MvuU8E75rVxe5eE1N6gxeTo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3e52e76b70d5508f3cec70b882a29199f4d1ee85", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib_2": { + "locked": { + "dir": "lib", + "lastModified": 1696019113, + "narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib_3": { + "locked": { + "lastModified": 1697935651, + "narHash": "sha256-qOfWjQ2JQSQL15KLh6D7xQhx0qgZlYZTYlcEiRuAMMw=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "e1e11fdbb01113d85c7f41cada9d2847660e3902", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1685801374, + "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_2": { + "locked": { + "lastModified": 1685801374, + "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-wayland": { + "inputs": { + "flake-compat": "flake-compat_6", + "lib-aggregate": "lib-aggregate", + "nix-eval-jobs": "nix-eval-jobs", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1698156831, + "narHash": "sha256-1NnPsQO2d0glJyA2dOsCvf7R7H/IEr5B6xRRUTblDI0=", + "owner": "nix-community", + "repo": "nixpkgs-wayland", + "rev": "ec64882e7238818dd914734ba7fe18945950ec71", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs-wayland", + "type": "github" + } + }, + "nixpkgs_10": { + "locked": { + "lastModified": 1697677194, + "narHash": "sha256-lN2eJCsOzjhxrvTQsNcW7r0E9hMJ7ABrKDQWpmYFRkM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "18e505d654892d057f308c817d220faf962dbf23", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_11": { + "locked": { + "lastModified": 1688322751, + "narHash": "sha256-eW62dC5f33oKZL7VWlomttbUnOTHrAbte9yNUNW8rbk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0fbe93c5a7cac99f90b60bdf5f149383daaa615f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_12": { + "locked": { + "lastModified": 1670751203, + "narHash": "sha256-XdoH1v3shKDGlrwjgrNX/EN8s3c+kQV7xY6cLCE8vcI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "64e0bf055f9d25928c31fb12924e59ff8ce71e60", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1685655444, + "narHash": "sha256-6EujQNAeaUkWvpEZZcVF8qSfQrNVWFNNGbUJxv/A5a8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e635192892f5abbc2289eaac3a73cdb249abaefd", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1697723726, + "narHash": "sha256-SaTWPkI8a5xSHX/rrKzUe+/uVNy6zCGMXgoeMb7T9rg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7c9cc5a6e5d38010801741ac830a3f8fd667a7a0", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, - "haskell-flake": { + "nixpkgs_4": { "locked": { - "lastModified": 1684780604, - "narHash": "sha256-2uMZsewmRn7rRtAnnQNw1lj0uZBMh4m6Cs/7dV5YF08=", - "owner": "srid", - "repo": "haskell-flake", - "rev": "74210fa80a49f1b6f67223debdbf1494596ff9f2", + "lastModified": 1697723726, + "narHash": "sha256-SaTWPkI8a5xSHX/rrKzUe+/uVNy6zCGMXgoeMb7T9rg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7c9cc5a6e5d38010801741ac830a3f8fd667a7a0", "type": "github" }, "original": { - "owner": "srid", - "ref": "0.3.0", - "repo": "haskell-flake", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, - "hercules-ci-agent": { - "inputs": { - "flake-parts": "flake-parts_6", - "haskell-flake": "haskell-flake", - "nixpkgs": "nixpkgs_7" - }, + "nixpkgs_5": { "locked": { - "lastModified": 1688568579, - "narHash": "sha256-ON0M56wtY/TIIGPkXDlJboAmuYwc73Hi8X9iJGtxOhM=", - "owner": "hercules-ci", - "repo": "hercules-ci-agent", - "rev": "367dd8cd649b57009a6502e878005a1e54ad78c5", + "lastModified": 1656753965, + "narHash": "sha256-BCrB3l0qpJokOnIVc3g2lHiGhnjUi0MoXiw6t1o8H1E=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "0ea7a8f1b939d74e5df8af9a8f7342097cdf69eb", "type": "github" }, "original": { - "id": "hercules-ci-agent", - "type": "indirect" + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" } }, - "hercules-ci-effects": { - "inputs": { - "flake-parts": [ - "schizofox", - "nixpak", - "flake-parts" - ], - "hercules-ci-agent": "hercules-ci-agent", - "nixpkgs": [ - "schizofox", - "nixpak", - "nixpkgs" - ] - }, + "nixpkgs_6": { "locked": { - "lastModified": 1689397210, - "narHash": "sha256-fVxZnqxMbsDkB4GzGAs/B41K0wt/e+B/fLxmTFF/S20=", - "owner": "hercules-ci", - "repo": "hercules-ci-effects", - "rev": "0a63bfa3f00a3775ea3a6722b247880f1ffe91ce", + "lastModified": 1655400192, + "narHash": "sha256-49OBVVRgb9H/PSmNT9W61+NRdDbuSJVuDDflwXlaUKU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3d7435c638baffaa826b85459df0fff47f12317d", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "hercules-ci-effects", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, - "home-manager": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, + "nixpkgs_7": { "locked": { - "lastModified": 1692763155, - "narHash": "sha256-qMrGKZ8c/q/mHO3ZdrcBPwiVVXPLLgXjY98Ejqb5kAA=", - "owner": "nix-community", - "repo": "home-manager", - "rev": "6a20e40acaebf067da682661aa67da8b36812606", + "lastModified": 1689088367, + "narHash": "sha256-Y2tl2TlKCWEHrOeM9ivjCLlRAKH3qoPUE/emhZECU14=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "5c9ddb86679c400d6b7360797b8a22167c2053f8", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "home-manager", + "owner": "NixOS", + "ref": "release-23.05", + "repo": "nixpkgs", "type": "github" } }, - "hyprland": { - "inputs": { - "hyprland-protocols": "hyprland-protocols", - "nixpkgs": "nixpkgs_3", - "systems": "systems_4", - "wlroots": "wlroots", - "xdph": "xdph" - }, + "nixpkgs_8": { "locked": { - "lastModified": 1692988931, - "narHash": "sha256-biA+vhcRS2lT3zTnV8QyT0FoxEIdQ6N+JnaWsr7F+8M=", - "owner": "hyprwm", - "repo": "Hyprland", - "rev": "ae69b9a2fa559d869f4e9c61ddf24e152d97df2f", + "lastModified": 1670461440, + "narHash": "sha256-jy1LB8HOMKGJEGXgzFRLDU1CBGL0/LlkolgnqIsF0D8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "04a75b2eecc0acf6239acf9dd04485ff8d14f425", "type": "github" }, "original": { - "owner": "hyprwm", - "repo": "Hyprland", + "owner": "NixOS", + "ref": "nixos-22.11-small", + "repo": "nixpkgs", "type": "github" } }, - "hyprland-protocols": { - "inputs": { - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, + "nixpkgs_9": { "locked": { - "lastModified": 1691753796, - "narHash": "sha256-zOEwiWoXk3j3+EoF3ySUJmberFewWlagvewDRuWYAso=", - "owner": "hyprwm", - "repo": "hyprland-protocols", - "rev": "0c2ce70625cb30aef199cb388f99e19a61a6ce03", + "lastModified": 1697723726, + "narHash": "sha256-SaTWPkI8a5xSHX/rrKzUe+/uVNy6zCGMXgoeMb7T9rg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7c9cc5a6e5d38010801741ac830a3f8fd667a7a0", "type": "github" }, "original": { - "owner": "hyprwm", - "repo": "hyprland-protocols", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } }, - "hyprland-protocols_2": { - "inputs": { - "nixpkgs": [ - "xdg-portal-hyprland", - "nixpkgs" - ], - "systems": [ - "xdg-portal-hyprland", - "systems" - ] - }, + "nmd": { + "flake": false, "locked": { - "lastModified": 1691753796, - "narHash": "sha256-zOEwiWoXk3j3+EoF3ySUJmberFewWlagvewDRuWYAso=", - "owner": "hyprwm", - "repo": "hyprland-protocols", - "rev": "0c2ce70625cb30aef199cb388f99e19a61a6ce03", + "lastModified": 1696846470, + "narHash": "sha256-S/6s3nRcg+xZfsO7aLe01W+EMAKFVyieHa4eFvOKOLk=", + "owner": "horriblename", + "repo": "nmd", + "rev": "bcf805ce85b9e938f7e027b3311137ffbd995794", "type": "github" }, "original": { - "owner": "hyprwm", - "repo": "hyprland-protocols", + "owner": "horriblename", + "repo": "nmd", "type": "github" } }, - "hyprpicker": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] + "nmd_2": { + "flake": false, + "locked": { + "lastModified": 1687627428, + "narHash": "sha256-7zGfXuNS5RHqhpEdz2fwrtqvF86JRo5U1hrxZSYgcm8=", + "owner": "~rycee", + "repo": "nmd", + "rev": "824a380546b5d0d0eb701ff8cd5dbafb360750ff", + "type": "sourcehut" }, + "original": { + "owner": "~rycee", + "repo": "nmd", + "type": "sourcehut" + } + }, + "noice-nvim": { + "flake": false, "locked": { - "lastModified": 1691427524, - "narHash": "sha256-3n0HJgo+3YCuo56a+efzcrh5UsfXi5jPU4tjqzJVm7g=", - "owner": "hyprwm", - "repo": "hyprpicker", - "rev": "5ba32686943f839d072426d9ffd172decaee0e3e", + "lastModified": 1690306450, + "narHash": "sha256-Zca6meJkfF4fl17Y+6s77GYrqnhkkzIYW73vAhKg7e4=", + "owner": "folke", + "repo": "noice.nvim", + "rev": "894db25ec726d32047799d4d0a982b701bec453b", "type": "github" }, "original": { - "owner": "hyprwm", - "repo": "hyprpicker", + "owner": "folke", + "repo": "noice.nvim", "type": "github" } }, - "isabel-nvim": { + "none-ls": { "flake": false, "locked": { - "lastModified": 1691575884, - "narHash": "sha256-42VQOHkvdqlqqs4Of0wXbrVyvvaIZIgQZx1pj3QMKY8=", - "ref": "refs/heads/main", - "rev": "1489357a98c4226122fff4c9574d85fdc9c84d49", - "revCount": 11, - "submodules": false, - "type": "git", - "url": "https://github.com/isabelroses/nvim" + "lastModified": 1697600654, + "narHash": "sha256-dDMZEgT5uG31bEsLiX9r6MJlOJUdQyeTPJAeRcY2z7s=", + "owner": "nvimtools", + "repo": "none-ls.nvim", + "rev": "dc9b7e28f5573a1a2225ffb33893d23d3e052ed6", + "type": "github" }, "original": { - "submodules": false, - "type": "git", - "url": "https://github.com/isabelroses/nvim" + "owner": "nvimtools", + "repo": "none-ls.nvim", + "type": "github" } }, - "lanzaboote": { - "inputs": { - "crane": "crane_2", - "flake-compat": "flake-compat_3", - "flake-parts": "flake-parts_2", - "flake-utils": "flake-utils_3", - "nixpkgs": [ - "nixpkgs" - ], - "pre-commit-hooks-nix": "pre-commit-hooks-nix", - "rust-overlay": "rust-overlay_2" - }, + "nui-nvim": { + "flake": false, "locked": { - "lastModified": 1692972892, - "narHash": "sha256-ifDTnczs4c/v73LKQdmoGYO81JmysKTlR5ZUH5cr+cE=", - "owner": "nix-community", - "repo": "lanzaboote", - "rev": "6d6cdf59b9d1ca6a2732c57e40f7cbd0f1eb1755", + "lastModified": 1689828309, + "narHash": "sha256-nSUs9zAX7hQ3PuFrH4zQblMfTY6ALDNggmqaQnkbR5E=", + "owner": "MunifTanjim", + "repo": "nui.nvim", + "rev": "9e3916e784660f55f47daa6f26053ad044db5d6a", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "lanzaboote", + "owner": "MunifTanjim", + "repo": "nui.nvim", "type": "github" } }, - "lib-aggregate": { - "inputs": { - "flake-utils": "flake-utils_6", - "nixpkgs-lib": "nixpkgs-lib_3" - }, + "nvim-autopairs": { + "flake": false, "locked": { - "lastModified": 1692878963, - "narHash": "sha256-/pv2E36Su112vPMk5dgUED0j2v7n/Mh0p99sXdJ9cH4=", - "owner": "nix-community", - "repo": "lib-aggregate", - "rev": "e74fab6aff10cd2f4241c4bf646e53f5b3203349", + "lastModified": 1689332359, + "narHash": "sha256-bu+WpW5Wfk3pS74mzVvehl7dVMHgrttmV4ZSlfwbai4=", + "owner": "windwp", + "repo": "nvim-autopairs", + "rev": "ae5b41ce880a6d850055e262d6dfebd362bb276e", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "lib-aggregate", + "owner": "windwp", + "repo": "nvim-autopairs", "type": "github" } }, - "nekowinston-nur": { - "inputs": { - "crane": "crane_3", - "flake-utils": "flake-utils_4", - "nixpkgs": "nixpkgs_4", - "rust-overlay": "rust-overlay_3" - }, + "nvim-bufferline-lua": { + "flake": false, "locked": { - "lastModified": 1692342174, - "narHash": "sha256-AaIfb/Ecu5tai6rJLfXxQL0MGUbLYxpiIewXP4zgFC0=", - "owner": "nekowinston", - "repo": "nur", - "rev": "c994b2a594cab20bedf7697351ae7353ef74a54e", + "lastModified": 1690184232, + "narHash": "sha256-MiQsYeLgADCaUf1x88q/7gO17F992HMlt1pu9dYEmp0=", + "owner": "akinsho", + "repo": "nvim-bufferline.lua", + "rev": "99f0932365b34e22549ff58e1bea388465d15e99", "type": "github" }, "original": { - "owner": "nekowinston", - "repo": "nur", + "owner": "akinsho", + "repo": "nvim-bufferline.lua", "type": "github" } }, - "nh": { - "inputs": { - "flake-parts": "flake-parts_3", - "nix-filter": "nix-filter", - "nixpkgs": [ - "nixpkgs" - ] - }, + "nvim-cmp": { + "flake": false, "locked": { - "lastModified": 1691768450, - "narHash": "sha256-NbHI+0WrHxGj34AAzS6V3bj5EJK/YBKlmvbrkwkCxhs=", - "owner": "viperML", - "repo": "nh", - "rev": "6dcca8fc2a8873161ad60300d8ecad13326176d8", + "lastModified": 1688965049, + "narHash": "sha256-Hq6YUfMQo1rHoay3/NieGCne7U/f06GwUPhN2HO0PdQ=", + "owner": "hrsh7th", + "repo": "nvim-cmp", + "rev": "c4e491a87eeacf0408902c32f031d802c7eafce8", "type": "github" }, "original": { - "owner": "viperML", - "repo": "nh", + "owner": "hrsh7th", + "repo": "nvim-cmp", "type": "github" } }, - "nil": { - "inputs": { - "flake-utils": "flake-utils_5", - "nixpkgs": [ - "nixpkgs" - ], - "rust-overlay": [ - "rust-overlay" - ] - }, + "nvim-code-action-menu": { + "flake": false, "locked": { - "lastModified": 1691372739, - "narHash": "sha256-fZ8KfBMcIFO/R7xaWtB85SFeuUjb9SCH8fxYBnY8068=", - "owner": "oxalica", - "repo": "nil", - "rev": "97abe7d3d48721d4e0fcc1876eea83bb4247825b", + "lastModified": 1671523188, + "narHash": "sha256-7szx+Me6WhrANbmfQ6C6gfSVB2owd02b3iZYhz7K6wY=", + "owner": "weilbith", + "repo": "nvim-code-action-menu", + "rev": "e4399dbaf6eabff998d3d5f1cbcd8d9933710027", "type": "github" }, "original": { - "owner": "oxalica", - "repo": "nil", + "owner": "weilbith", + "repo": "nvim-code-action-menu", "type": "github" } }, - "nix-eval-jobs": { - "inputs": { - "flake-parts": "flake-parts_5", - "nixpkgs": "nixpkgs_6", - "treefmt-nix": "treefmt-nix" - }, + "nvim-colorizer-lua": { + "flake": false, "locked": { - "lastModified": 1692841356, - "narHash": "sha256-ppV8EdbH6s4+E9YeHhF1+MrEO/R36PeFE/6zjHS4Pn8=", - "owner": "nix-community", - "repo": "nix-eval-jobs", - "rev": "3681d5930d1479898758b752f2d77be0c8e0f90f", + "lastModified": 1591879145, + "narHash": "sha256-6YrnItxExL2C8pNIdLd+hXCjsB2MbZANwWkah6dreD8=", + "owner": "norcalli", + "repo": "nvim-colorizer.lua", + "rev": "36c610a9717cc9ec426a07c8e6bf3b3abcb139d6", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nix-eval-jobs", + "owner": "norcalli", + "repo": "nvim-colorizer.lua", "type": "github" } }, - "nix-filter": { + "nvim-compe": { + "flake": false, "locked": { - "lastModified": 1687178632, - "narHash": "sha256-HS7YR5erss0JCaUijPeyg2XrisEb959FIct3n2TMGbE=", - "owner": "numtide", - "repo": "nix-filter", - "rev": "d90c75e8319d0dd9be67d933d8eb9d0894ec9174", + "lastModified": 1633188506, + "narHash": "sha256-Y2oqvsuAKM3qjmmtJVD9z34682eCRF25kPL+rxhhg7I=", + "owner": "hrsh7th", + "repo": "nvim-compe", + "rev": "d186d739c54823e0b010feb205c6f97792322c08", "type": "github" }, "original": { - "owner": "numtide", - "repo": "nix-filter", + "owner": "hrsh7th", + "repo": "nvim-compe", "type": "github" } }, - "nix-gaming": { - "inputs": { - "flake-parts": "flake-parts_4", - "nixpkgs": [ - "nixpkgs" - ] - }, + "nvim-cursorline": { + "flake": false, "locked": { - "lastModified": 1692977085, - "narHash": "sha256-eFq6bcDirufyYO1qsh4KlxLSRWlNDZG/ZFeVcikoJ4E=", - "owner": "fufexan", - "repo": "nix-gaming", - "rev": "bc33c7297e8299e074f3a238bac52dc9e84b13e4", + "lastModified": 1650034925, + "narHash": "sha256-Uhw65p1KBjs8KsVOmTzuiu3XKclxBob8AVdWEt30C/8=", + "owner": "yamatsum", + "repo": "nvim-cursorline", + "rev": "804f0023692653b2b2368462d67d2a87056947f9", "type": "github" }, "original": { - "owner": "fufexan", - "repo": "nix-gaming", + "owner": "yamatsum", + "repo": "nvim-cursorline", "type": "github" } }, - "nix-ld": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, + "nvim-dap": { + "flake": false, "locked": { - "lastModified": 1686849676, - "narHash": "sha256-+z9t7BLugZO1WhyYEq6FI38TMh2EwfgfAv3RDFSjwtc=", - "owner": "Mic92", - "repo": "nix-ld", - "rev": "3abd605e56b5b34ec630bb10ba85f98c93cc05b2", + "lastModified": 1690444190, + "narHash": "sha256-OSJA+K8eGj87RWo2tE0kT6bAItGkMMtuR0HB8WEXZ4k=", + "owner": "mfussenegger", + "repo": "nvim-dap", + "rev": "2f28ea843bcdb378b171a66ddcd568516e431d55", "type": "github" }, "original": { - "owner": "Mic92", - "repo": "nix-ld", + "owner": "mfussenegger", + "repo": "nvim-dap", "type": "github" } }, - "nixpak": { - "inputs": { - "flake-parts": [ - "schizofox", - "flake-parts" - ], - "hercules-ci-effects": "hercules-ci-effects", - "nixpkgs": [ - "schizofox", - "nixpkgs" - ] - }, + "nvim-dap-ui": { + "flake": false, "locked": { - "lastModified": 1692831528, - "narHash": "sha256-EG/hn6KpDCfQSVHoKoxU+4MgMs8gJzrrHtpo2atTvWo=", - "owner": "nixpak", - "repo": "nixpak", - "rev": "8b331d0e2f46c72731303311f65f3690b1917816", + "lastModified": 1689371609, + "narHash": "sha256-z6TFe7+r/g2tfgdXr6PCPri5lSboi66zZmsdyWTI1BM=", + "owner": "rcarriga", + "repo": "nvim-dap-ui", + "rev": "85b16ac2309d85c88577cd8ee1733ce52be8227e", "type": "github" }, "original": { - "owner": "nixpak", - "repo": "nixpak", + "owner": "rcarriga", + "repo": "nvim-dap-ui", "type": "github" } }, - "nixpkgs": { + "nvim-lightbulb": { + "flake": false, "locked": { - "lastModified": 1692808169, - "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", + "lastModified": 1689887436, + "narHash": "sha256-Meoop66jINllnxN6aohuPmU7DEjn64FMq/b8zuy9FEQ=", + "owner": "kosayoda", + "repo": "nvim-lightbulb", + "rev": "8f00b89dd1b1dbde16872bee5fbcee2e58c9b8e9", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", + "owner": "kosayoda", + "repo": "nvim-lightbulb", "type": "github" } }, - "nixpkgs-22_11": { + "nvim-lspconfig": { + "flake": false, "locked": { - "lastModified": 1669558522, - "narHash": "sha256-yqxn+wOiPqe6cxzOo4leeJOp1bXE/fjPEi/3F/bBHv8=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "ce5fe99df1f15a09a91a86be9738d68fadfbad82", + "lastModified": 1690356683, + "narHash": "sha256-Ama9nLC/T1wJWal6bKvgY0ywUUiJ5VLuIxoY1xbJKtY=", + "owner": "neovim", + "repo": "nvim-lspconfig", + "rev": "b6091272422bb0fbd729f7f5d17a56d37499c54f", "type": "github" }, "original": { - "id": "nixpkgs", - "ref": "nixos-22.11", - "type": "indirect" + "owner": "neovim", + "repo": "nvim-lspconfig", + "type": "github" } }, - "nixpkgs-23_05": { + "nvim-navbuddy": { + "flake": false, "locked": { - "lastModified": 1684782344, - "narHash": "sha256-SHN8hPYYSX0thDrMLMWPWYulK3YFgASOrCsIL3AJ78g=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "8966c43feba2c701ed624302b6a935f97bcbdf88", + "lastModified": 1688569844, + "narHash": "sha256-011RT/wnQdBR1vMrXFwxbicBAgdcd4eQYPbok/o3CIE=", + "owner": "SmiteshP", + "repo": "nvim-navbuddy", + "rev": "244a4cded6f2b568403684131d148048efe4e8af", "type": "github" }, "original": { - "id": "nixpkgs", - "ref": "nixos-23.05", - "type": "indirect" + "owner": "SmiteshP", + "repo": "nvim-navbuddy", + "type": "github" } }, - "nixpkgs-lib": { + "nvim-navic": { + "flake": false, "locked": { - "dir": "lib", - "lastModified": 1688049487, - "narHash": "sha256-100g4iaKC9MalDjUW9iN6Jl/OocTDtXdeAj7pEGIRh4=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "4bc72cae107788bf3f24f30db2e2f685c9298dc9", + "lastModified": 1689944100, + "narHash": "sha256-M7BT1C9xHyLgr22JI3b+wyD+bYs6FgKc6PIqMrXnNr4=", + "owner": "SmiteshP", + "repo": "nvim-navic", + "rev": "9c89730da6a05acfeb6a197e212dfadf5aa60ca0", "type": "github" }, "original": { - "dir": "lib", - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", + "owner": "SmiteshP", + "repo": "nvim-navic", "type": "github" } }, - "nixpkgs-lib_2": { + "nvim-neoclip": { + "flake": false, "locked": { - "dir": "lib", - "lastModified": 1690881714, - "narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "9e1960bc196baf6881340d53dccb203a951745a2", + "lastModified": 1684196333, + "narHash": "sha256-96AwMgyC7PTDEPS5tXwDT3WfK8jJJuIYGE+q+j6U5Uc=", + "owner": "AckslD", + "repo": "nvim-neoclip.lua", + "rev": "4e406ae0f759262518731538f2585abb9d269bac", "type": "github" }, "original": { - "dir": "lib", - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", + "owner": "AckslD", + "repo": "nvim-neoclip.lua", "type": "github" } }, - "nixpkgs-lib_3": { + "nvim-notify": { + "flake": false, "locked": { - "lastModified": 1692492218, - "narHash": "sha256-sBj4dllTXEuBzVUaXGvWrQt3iwr64wlnVP26ZcaND0E=", - "owner": "nix-community", - "repo": "nixpkgs.lib", - "rev": "2a3f8763738dca95b14705619c5e489912b7f36a", + "lastModified": 1685978736, + "narHash": "sha256-Rr2tzuEr06M9ZbvQbC07qcxkyjFJFYdABwRpYelKBFI=", + "owner": "rcarriga", + "repo": "nvim-notify", + "rev": "ea9c8ce7a37f2238f934e087c255758659948e0f", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixpkgs.lib", + "owner": "rcarriga", + "repo": "nvim-notify", "type": "github" } }, - "nixpkgs-stable": { + "nvim-session-manager": { + "flake": false, "locked": { - "lastModified": 1685801374, - "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "lastModified": 1689976511, + "narHash": "sha256-04GL+0JdtD2hEOSrRJUh3Wdpoy2igjHt95Nf3WioFU4=", + "owner": "Shatur", + "repo": "neovim-session-manager", + "rev": "4883372b1ef2bdcf4cbdac44c98d68c216914462", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixos-23.05", - "repo": "nixpkgs", + "owner": "Shatur", + "repo": "neovim-session-manager", "type": "github" } }, - "nixpkgs-wayland": { - "inputs": { - "flake-compat": "flake-compat_4", - "lib-aggregate": "lib-aggregate", - "nix-eval-jobs": "nix-eval-jobs", - "nixpkgs": [ - "nixpkgs" - ], - "nixpkgs_sirula": "nixpkgs_sirula" - }, + "nvim-surround": { + "flake": false, "locked": { - "lastModified": 1692995783, - "narHash": "sha256-0/QfEw4sDMNxBxJiHsyP+2xgf0P9/J5y1OiKsdU4yoA=", - "owner": "nix-community", - "repo": "nixpkgs-wayland", - "rev": "98d723cc5ab8a10f584f39fcf7505d3f7193247a", + "lastModified": 1685464327, + "narHash": "sha256-r3D5WTqEnIL1T3p7cmkRmBY8qgwFFJptM7BKNNsCT8k=", + "owner": "kylechui", + "repo": "nvim-surround", + "rev": "10b20ca7d9da1ac8df8339e140ffef94f9ab3b18", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nixpkgs-wayland", + "owner": "kylechui", + "repo": "nvim-surround", "type": "github" } }, - "nixpkgs_2": { + "nvim-tree-lua": { + "flake": false, "locked": { - "lastModified": 1685655444, - "narHash": "sha256-6EujQNAeaUkWvpEZZcVF8qSfQrNVWFNNGbUJxv/A5a8=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "e635192892f5abbc2289eaac3a73cdb249abaefd", + "lastModified": 1690616703, + "narHash": "sha256-kTbYvT21wLfiwEpQAgGZtep2GP4F9e7e6XGVpr4D1hY=", + "owner": "nvim-tree", + "repo": "nvim-tree.lua", + "rev": "4bd30f0137e44dcf3e74cc1164efb568f78f2b02", "type": "github" }, "original": { - "id": "nixpkgs", - "ref": "nixos-unstable", - "type": "indirect" + "owner": "nvim-tree", + "repo": "nvim-tree.lua", + "type": "github" } }, - "nixpkgs_3": { + "nvim-treesitter-context": { + "flake": false, "locked": { - "lastModified": 1692638711, - "narHash": "sha256-J0LgSFgJVGCC1+j5R2QndadWI1oumusg6hCtYAzLID4=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "91a22f76cd1716f9d0149e8a5c68424bb691de15", + "lastModified": 1689239188, + "narHash": "sha256-AJamiDezFK7l0bqb/VFm+pzBKugQNCmQ6JAWKmjH76g=", + "owner": "nvim-treesitter", + "repo": "nvim-treesitter-context", + "rev": "6f8f788738b968f24a108ee599c5be0031f94f06", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", + "owner": "nvim-treesitter", + "repo": "nvim-treesitter-context", "type": "github" } }, - "nixpkgs_4": { + "nvim-ts-autotag": { + "flake": false, "locked": { - "lastModified": 1691654369, - "narHash": "sha256-gSILTEx1jRaJjwZxRlnu3ZwMn1FVNk80qlwiCX8kmpo=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "ce5e4a6ef2e59d89a971bc434ca8ca222b9c7f5e", + "lastModified": 1686883732, + "narHash": "sha256-4qTtXYA5HyG1sADV0wsiccO/G89qEoYPmlg8tTx7h8g=", + "owner": "windwp", + "repo": "nvim-ts-autotag", + "rev": "6be1192965df35f94b8ea6d323354f7dc7a557e4", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", + "owner": "windwp", + "repo": "nvim-ts-autotag", "type": "github" } }, - "nixpkgs_5": { + "nvim-web-devicons": { + "flake": false, "locked": { - "lastModified": 1692913444, - "narHash": "sha256-1SvMQm2DwofNxXVtNWWtIcTh7GctEVrS/Xel/mdc6iY=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "18324978d632ffc55ef1d928e81630c620f4f447", + "lastModified": 1689474464, + "narHash": "sha256-FtEJBhqvs+c/Rvy4qXf3iyoMTTKrDBvQw5g63n4KEYo=", + "owner": "nvim-tree", + "repo": "nvim-web-devicons", + "rev": "efbfed0567ef4bfac3ce630524a0f6c8451c5534", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", + "owner": "nvim-tree", + "repo": "nvim-web-devicons", "type": "github" } }, - "nixpkgs_6": { + "obsidian-nvim": { + "flake": false, "locked": { - "lastModified": 1692838642, - "narHash": "sha256-Y47k7ckDN2nlH+A2hdfgNulXqKkTX8WdWCfd6l0ys0Y=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "6408fedbfacd0d323edc2512f6033dbce818672a", + "lastModified": 1690662423, + "narHash": "sha256-qemlp11QSp4BnWadN3+3ndv47e+1yS+w91GumbzQric=", + "owner": "epwalsh", + "repo": "obsidian.nvim", + "rev": "f81ddfa56b87fda158d3a56625a8040a7cf23fef", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "master", - "repo": "nixpkgs", + "owner": "epwalsh", + "repo": "obsidian.nvim", "type": "github" } }, - "nixpkgs_7": { + "onedark": { + "flake": false, "locked": { - "lastModified": 1688322751, - "narHash": "sha256-eW62dC5f33oKZL7VWlomttbUnOTHrAbte9yNUNW8rbk=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "0fbe93c5a7cac99f90b60bdf5f149383daaa615f", + "lastModified": 1689269544, + "narHash": "sha256-HfyYEppo9NFswYlPKnHNOZO5eiTQSORQhWAkzCmM2m4=", + "owner": "navarasu", + "repo": "onedark.nvim", + "rev": "cae5fdf035ee92c407a29ee2ccfcff503d2be7f1", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", + "owner": "navarasu", + "repo": "onedark.nvim", "type": "github" } }, - "nixpkgs_8": { + "orgmode-nvim": { + "flake": false, "locked": { - "lastModified": 1670751203, - "narHash": "sha256-XdoH1v3shKDGlrwjgrNX/EN8s3c+kQV7xY6cLCE8vcI=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "64e0bf055f9d25928c31fb12924e59ff8ce71e60", + "lastModified": 1690291768, + "narHash": "sha256-jc89zEAtHBh8785gNW/UZ9jkgTee/XYMm4+jyW7G2Oo=", + "owner": "nvim-orgmode", + "repo": "orgmode", + "rev": "6b6eb8eabbed4d95568fd1f5374a3dff7ed51a3b", "type": "github" }, "original": { - "id": "nixpkgs", - "ref": "nixos-unstable", - "type": "indirect" + "owner": "nvim-orgmode", + "repo": "orgmode", + "type": "github" } }, - "nixpkgs_sirula": { + "oxocarbon": { + "flake": false, "locked": { - "lastModified": 1682879489, - "narHash": "sha256-sASwo8gBt7JDnOOstnps90K1wxmVfyhsTPPNTGBPjjg=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "da45bf6ec7bbcc5d1e14d3795c025199f28e0de0", + "lastModified": 1687168305, + "narHash": "sha256-2o++5aRDULfI35d+7psa6bk0eSXH2HwfuGjGtYGjR4w=", + "owner": "glyh", + "repo": "oxocarbon.nvim", + "rev": "7591d2e18df05374d612acba2b2573c7ff44dce4", "type": "github" }, "original": { - "owner": "nixos", - "repo": "nixpkgs", - "rev": "da45bf6ec7bbcc5d1e14d3795c025199f28e0de0", + "owner": "glyh", + "ref": "lualine-support", + "repo": "oxocarbon.nvim", "type": "github" } }, - "nu_scripts": { + "plenary-nvim": { "flake": false, "locked": { - "lastModified": 1692875499, - "narHash": "sha256-kpE+vgobYsQuh8sS3gK/yg68nQykquwteeuecjLtIrE=", - "ref": "refs/heads/main", - "rev": "45c051dad0e243a63608c8274b7fddd5f0b74941", - "revCount": 729, - "submodules": true, - "type": "git", - "url": "https://github.com/nushell/nu_scripts" + "lastModified": 1689589150, + "narHash": "sha256-oRtNcURQzrIRS3D88tWAl3HuFHxVJr8m/zzL7xoa/II=", + "owner": "nvim-lua", + "repo": "plenary.nvim", + "rev": "267282a9ce242bbb0c5dc31445b6d353bed978bb", + "type": "github" }, "original": { - "submodules": true, - "type": "git", - "url": "https://github.com/nushell/nu_scripts" + "owner": "nvim-lua", + "repo": "plenary.nvim", + "type": "github" } }, - "nur": { + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat_7", + "flake-utils": [ + "flake-utils" + ], + "gitignore": "gitignore_2", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_2" + }, "locked": { - "lastModified": 1692996347, - "narHash": "sha256-0gMI45VgTgQBonFr/utWkUyDJ7Tt+TA0pbqJXMIFU0g=", - "owner": "nix-community", - "repo": "nur", - "rev": "f050fc284b58af8989b996f2e17950e55bae1332", + "lastModified": 1697746376, + "narHash": "sha256-gu77VkgdfaHgNCVufeb6WP9oqFLjwK4jHcoPZmBVF3E=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "8cc349bfd082da8782b989cad2158c9ad5bd70fd", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "nur", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", "type": "github" } }, @@ -1323,11 +2902,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1689668210, - "narHash": "sha256-XAATwDkaUxH958yXLs1lcEOmU6pSEIkatY3qjqk8X0E=", + "lastModified": 1697746376, + "narHash": "sha256-gu77VkgdfaHgNCVufeb6WP9oqFLjwK4jHcoPZmBVF3E=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "eb433bff05b285258be76513add6f6c57b441775", + "rev": "8cc349bfd082da8782b989cad2158c9ad5bd70fd", "type": "github" }, "original": { @@ -1336,26 +2915,100 @@ "type": "github" } }, + "presence-nvim": { + "flake": false, + "locked": { + "lastModified": 1674984077, + "narHash": "sha256-ZpsunLsn//zYgUtmAm5FqKVueVd/Pa1r55ZDqxCimBk=", + "owner": "andweeb", + "repo": "presence.nvim", + "rev": "87c857a56b7703f976d3a5ef15967d80508df6e6", + "type": "github" + }, + "original": { + "owner": "andweeb", + "repo": "presence.nvim", + "type": "github" + } + }, + "project-nvim": { + "flake": false, + "locked": { + "lastModified": 1680567592, + "narHash": "sha256-avV3wMiDbraxW4mqlEsKy0oeewaRj9Q33K8NzWoaptU=", + "owner": "ahmedkhalf", + "repo": "project.nvim", + "rev": "8c6bad7d22eef1b71144b401c9f74ed01526a4fb", + "type": "github" + }, + "original": { + "owner": "ahmedkhalf", + "repo": "project.nvim", + "type": "github" + } + }, + "registers": { + "flake": false, + "locked": { + "lastModified": 1680595111, + "narHash": "sha256-MeBlcF5LLk6bhIofYuG+0Z2xwc0BVqP85yNCvjH66fw=", + "owner": "tversteeg", + "repo": "registers.nvim", + "rev": "2ab8372bb837f05fae6b43091f10a0b725d113ca", + "type": "github" + }, + "original": { + "owner": "tversteeg", + "repo": "registers.nvim", + "type": "github" + } + }, + "rnix-lsp": { + "inputs": { + "naersk": "naersk", + "nixpkgs": "nixpkgs_5", + "utils": "utils" + }, + "locked": { + "lastModified": 1669555118, + "narHash": "sha256-F0s0m62S5bHNVWNHLZD6SeHiLrsDx98VQbRjDyIu+qQ=", + "owner": "nix-community", + "repo": "rnix-lsp", + "rev": "95d40673fe43642e2e1144341e86d0036abd95d9", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "rnix-lsp", + "type": "github" + } + }, "root": { "inputs": { - "bella-nur": "bella-nur", + "ags": "ags", + "auto-cpufreq": "auto-cpufreq", + "bellado": "bellado", "catppuccin": "catppuccin", + "catppuccin-toolbox": "catppuccin-toolbox", + "catppuccinifier": "catppuccinifier", "devshell": "devshell", "flake-parts": "flake-parts", + "flake-schemas": "flake-schemas", + "flake-utils": "flake-utils_4", "home-manager": "home-manager", "hyprland": "hyprland", "hyprpicker": "hyprpicker", - "isabel-nvim": "isabel-nvim", "lanzaboote": "lanzaboote", - "nekowinston-nur": "nekowinston-nur", + "neovim-flake": "neovim-flake", "nh": "nh", "nil": "nil", "nix-gaming": "nix-gaming", + "nix-index-db": "nix-index-db", "nix-ld": "nix-ld", - "nixpkgs": "nixpkgs_5", + "nixSchemas": "nixSchemas", + "nixpkgs": "nixpkgs_9", "nixpkgs-wayland": "nixpkgs-wayland", - "nu_scripts": "nu_scripts", - "nur": "nur", + "pre-commit-hooks": "pre-commit-hooks", "rust-overlay": "rust-overlay_4", "schizofox": "schizofox", "simple-nixos-mailserver": "simple-nixos-mailserver", @@ -1368,24 +3021,20 @@ "rust-overlay": { "inputs": { "flake-utils": [ - "bella-nur", - "catppuccinifier", - "crane", + "catppuccin-toolbox", "flake-utils" ], "nixpkgs": [ - "bella-nur", - "catppuccinifier", - "crane", + "catppuccin-toolbox", "nixpkgs" ] }, "locked": { - "lastModified": 1685759304, - "narHash": "sha256-I3YBH6MS3G5kGzNuc1G0f9uYfTcNY9NYoRc3QsykLk4=", + "lastModified": 1697940838, + "narHash": "sha256-eyk92QqAoRNC0V99KOcKcBZjLPixxNBS0PRc4KlSQVs=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "c535b4f3327910c96dcf21851bbdd074d0760290", + "rev": "a3e829c06eadf848f13d109c7648570ce37ebccd", "type": "github" }, "original": { @@ -1397,20 +3046,22 @@ "rust-overlay_2": { "inputs": { "flake-utils": [ - "lanzaboote", + "catppuccinifier", + "crane", "flake-utils" ], "nixpkgs": [ - "lanzaboote", + "catppuccinifier", + "crane", "nixpkgs" ] }, "locked": { - "lastModified": 1689906077, - "narHash": "sha256-2tjLXKoSK7O0LYHlA6GCWL0gy2kZZno4krg+KZpDh6U=", + "lastModified": 1685759304, + "narHash": "sha256-I3YBH6MS3G5kGzNuc1G0f9uYfTcNY9NYoRc3QsykLk4=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "c88b28944129eeff5e819bdc21248dc07eb0625d", + "rev": "c535b4f3327910c96dcf21851bbdd074d0760290", "type": "github" }, "original": { @@ -1422,20 +3073,20 @@ "rust-overlay_3": { "inputs": { "flake-utils": [ - "nekowinston-nur", + "lanzaboote", "flake-utils" ], "nixpkgs": [ - "nekowinston-nur", + "lanzaboote", "nixpkgs" ] }, "locked": { - "lastModified": 1691892594, - "narHash": "sha256-Lt9/WUnI/ZqBYnHOC3n6Lg5jTfd/ZI+39jZx5HmolSQ=", + "lastModified": 1697940838, + "narHash": "sha256-eyk92QqAoRNC0V99KOcKcBZjLPixxNBS0PRc4KlSQVs=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "c638e10caf94caaa97fb1df74e3bb467dc9b92db", + "rev": "a3e829c06eadf848f13d109c7648570ce37ebccd", "type": "github" }, "original": { @@ -1446,17 +3097,17 @@ }, "rust-overlay_4": { "inputs": { - "flake-utils": "flake-utils_7", + "flake-utils": "flake-utils_9", "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1692929460, - "narHash": "sha256-zdN6UVtEml7t0WQHVy0avsE+TWJLklXnqJyiPaOa8u0=", + "lastModified": 1697940838, + "narHash": "sha256-eyk92QqAoRNC0V99KOcKcBZjLPixxNBS0PRc4KlSQVs=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "673e2d3d2a3951adc6f5e3351c9fce6ad130baed", + "rev": "a3e829c06eadf848f13d109c7648570ce37ebccd", "type": "github" }, "original": { @@ -1465,45 +3116,80 @@ "type": "github" } }, + "rust-tools": { + "flake": false, + "locked": { + "lastModified": 1689033186, + "narHash": "sha256-jtfyDxifchznUupLSao6nmpVqaX1yO0xN+NhqS9fgxg=", + "owner": "simrat39", + "repo": "rust-tools.nvim", + "rev": "0cc8adab23117783a0292a0c8a2fbed1005dc645", + "type": "github" + }, + "original": { + "owner": "simrat39", + "repo": "rust-tools.nvim", + "type": "github" + } + }, "schizofox": { "inputs": { + "flake-compat": "flake-compat_8", "flake-parts": [ "flake-parts" ], + "home-manager": "home-manager_2", "nixpak": "nixpak", "nixpkgs": [ "nixpkgs" - ] + ], + "nmd": "nmd_2" + }, + "locked": { + "lastModified": 1697945806, + "narHash": "sha256-2lTAyh/0J6r7og8gW8PRbJapFKD+2JuR7q84+hcHahE=", + "owner": "schizofox", + "repo": "schizofox", + "rev": "a4c72ef30acbd9dfbf3c14e65a385540053229c5", + "type": "github" }, + "original": { + "owner": "schizofox", + "repo": "schizofox", + "type": "github" + } + }, + "scrollbar-nvim": { + "flake": false, "locked": { - "lastModified": 1692915203, - "narHash": "sha256-NmLV78gGKTuZcUryWH6Ohp1In3epKqhy0zs9w/t48fQ=", - "owner": "schizofox", - "repo": "schizofox", - "rev": "95ae463dc4360d5c8e88b4fff1a413528ea4d2f2", + "lastModified": 1684886154, + "narHash": "sha256-zLBexSxQCn9HPY04a9w/UCJP1F5ShI2X12I9xE9H0cM=", + "owner": "petertriho", + "repo": "nvim-scrollbar", + "rev": "35f99d559041c7c0eff3a41f9093581ceea534e8", "type": "github" }, "original": { - "owner": "schizofox", - "repo": "schizofox", + "owner": "petertriho", + "repo": "nvim-scrollbar", "type": "github" } }, "simple-nixos-mailserver": { "inputs": { "blobs": "blobs", - "flake-compat": "flake-compat_5", - "nixpkgs": "nixpkgs_8", + "flake-compat": "flake-compat_9", + "nixpkgs": "nixpkgs_12", "nixpkgs-22_11": "nixpkgs-22_11", "nixpkgs-23_05": "nixpkgs-23_05", - "utils": "utils" + "utils": "utils_3" }, "locked": { - "lastModified": 1689976554, - "narHash": "sha256-uWJq3sIhkqfzPmfB2RWd5XFVooGFfSuJH9ER/r302xQ=", + "lastModified": 1695910380, + "narHash": "sha256-CyzeiXQGm8ceEOSK1dffBCfO7JNp8XhQeNkUiJ5HxgY=", "owner": "simple-nixos-mailserver", "repo": "nixos-mailserver", - "rev": "c63f6e7b053c18325194ff0e274dba44e8d2271e", + "rev": "84783b661ecf33927c534b6476beb74ea3308968", "type": "gitlab" }, "original": { @@ -1513,6 +3199,22 @@ "type": "gitlab" } }, + "smartcolumn": { + "flake": false, + "locked": { + "lastModified": 1679417638, + "narHash": "sha256-DjPWBOLbzdfOQAx+6xgV1CD5NKuP1N6An2lmHNHd39Q=", + "owner": "m4xshen", + "repo": "smartcolumn.nvim", + "rev": "0c572e3eae48874f25b74394a486f38cadb5c958", + "type": "github" + }, + "original": { + "owner": "m4xshen", + "repo": "smartcolumn.nvim", + "type": "github" + } + }, "sops": { "inputs": { "nixpkgs": [ @@ -1523,11 +3225,11 @@ ] }, "locked": { - "lastModified": 1692728678, - "narHash": "sha256-02MjG7Sb9k7eOi86CcC4GNWVOjT6gjmXFSqkRjZ8Xyk=", + "lastModified": 1697943852, + "narHash": "sha256-DaBxUPaZhQ3yLCmAATshYB7qo7NwcMvSFWz9T3bjYYY=", "owner": "Mic92", "repo": "sops-nix", - "rev": "1b7b3a32d65dbcd69c217d7735fdf0a6b2184f45", + "rev": "30a0ba4a20703b4bfe047fe5def1fc24978e322c", "type": "github" }, "original": { @@ -1536,6 +3238,39 @@ "type": "github" } }, + "sqls-nvim": { + "flake": false, + "locked": { + "lastModified": 1684697500, + "narHash": "sha256-jKFut6NZAf/eIeIkY7/2EsjsIhvZQKCKAJzeQ6XSr0s=", + "owner": "nanotee", + "repo": "sqls.nvim", + "rev": "4b1274b5b44c48ce784aac23747192f5d9d26207", + "type": "github" + }, + "original": { + "owner": "nanotee", + "repo": "sqls.nvim", + "type": "github" + } + }, + "superdirt-src": { + "flake": false, + "locked": { + "lastModified": 1611740180, + "narHash": "sha256-GtnqZeMFqFkVhgx2Exu0wY687cHa7mNnVCgjQd6fiIA=", + "owner": "musikinformatik", + "repo": "superdirt", + "rev": "7abb62e89649daa1232b9cbd6427241868abd30e", + "type": "github" + }, + "original": { + "owner": "musikinformatik", + "ref": "master", + "repo": "superdirt", + "type": "github" + } + }, "systems": { "locked": { "lastModified": 1681028828, @@ -1567,6 +3302,36 @@ } }, "systems_11": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_12": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_13": { "locked": { "lastModified": 1689347949, "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", @@ -1613,16 +3378,16 @@ }, "systems_4": { "locked": { - "lastModified": 1689347949, - "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", "owner": "nix-systems", - "repo": "default-linux", - "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "type": "github" }, "original": { "owner": "nix-systems", - "repo": "default-linux", + "repo": "default", "type": "github" } }, @@ -1643,16 +3408,16 @@ }, "systems_6": { "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", "type": "github" }, "original": { "owner": "nix-systems", - "repo": "default", + "repo": "default-linux", "type": "github" } }, @@ -1701,6 +3466,127 @@ "type": "github" } }, + "tabular": { + "flake": false, + "locked": { + "lastModified": 1550598128, + "narHash": "sha256-irolBA/m3YIaezl+90h5G+xUOpad+3u44uJqDs4JCUs=", + "owner": "godlygeek", + "repo": "tabular", + "rev": "339091ac4dd1f17e225fe7d57b48aff55f99b23a", + "type": "github" + }, + "original": { + "owner": "godlygeek", + "repo": "tabular", + "type": "github" + } + }, + "telescope": { + "flake": false, + "locked": { + "lastModified": 1690663693, + "narHash": "sha256-okyOr5t0e+oV3mY7Yq1ad/7f6qEEDS/ZQrqJcjktYRI=", + "owner": "nvim-telescope", + "repo": "telescope.nvim", + "rev": "b6fccfb0f7589a87587875206786daccba62acc3", + "type": "github" + }, + "original": { + "owner": "nvim-telescope", + "repo": "telescope.nvim", + "type": "github" + } + }, + "tidal-src": { + "flake": false, + "locked": { + "lastModified": 1654350756, + "narHash": "sha256-tONM5SYYBca0orTLH1EUOilSC1FCluWrFt8AetUx+YQ=", + "owner": "tidalcycles", + "repo": "tidal", + "rev": "fda9c1ecb3722698935245e5409ef8ccdfca16c8", + "type": "github" + }, + "original": { + "owner": "tidalcycles", + "ref": "main", + "repo": "tidal", + "type": "github" + } + }, + "tidalcycles": { + "inputs": { + "dirt-samples-src": "dirt-samples-src", + "nixpkgs": "nixpkgs_6", + "superdirt-src": "superdirt-src", + "tidal-src": "tidal-src", + "utils": "utils_2", + "vim-tidal-src": "vim-tidal-src", + "vowel-src": "vowel-src" + }, + "locked": { + "lastModified": 1664760044, + "narHash": "sha256-e5LGk/tDnphory1mYhADgPnVtShofY2w/3xY09jEE2A=", + "owner": "mitchmindtree", + "repo": "tidalcycles.nix", + "rev": "3f3a820cd43709077d15a24fa6062de7d623a6bf", + "type": "github" + }, + "original": { + "owner": "mitchmindtree", + "repo": "tidalcycles.nix", + "type": "github" + } + }, + "todo-comments": { + "flake": false, + "locked": { + "lastModified": 1690569591, + "narHash": "sha256-Qm8AJ8omU5eCfjLt91DVxLS0R3QHbfW55ZTegB1JvWI=", + "owner": "folke", + "repo": "todo-comments.nvim", + "rev": "3094ead8edfa9040de2421deddec55d3762f64d1", + "type": "github" + }, + "original": { + "owner": "folke", + "repo": "todo-comments.nvim", + "type": "github" + } + }, + "toggleterm-nvim": { + "flake": false, + "locked": { + "lastModified": 1689602083, + "narHash": "sha256-/sUulN93nRHa3Je+tXr8/i1cgCrd/wtrvMPkjG5Ofzs=", + "owner": "akinsho", + "repo": "toggleterm.nvim", + "rev": "00c13dccc78c09fa5da4c5edda990a363e75035e", + "type": "github" + }, + "original": { + "owner": "akinsho", + "repo": "toggleterm.nvim", + "type": "github" + } + }, + "tokyonight": { + "flake": false, + "locked": { + "lastModified": 1689285710, + "narHash": "sha256-x26qLaZzg7sJIc1d/5Q/DJ/YvRSc3s87PwPHTPTl+Xk=", + "owner": "folke", + "repo": "tokyonight.nvim", + "rev": "1ee11019f8a81dac989ae1db1a013e3d582e2033", + "type": "github" + }, + "original": { + "owner": "folke", + "repo": "tokyonight.nvim", + "type": "github" + } + }, "treefmt-nix": { "inputs": { "nixpkgs": [ @@ -1710,11 +3596,11 @@ ] }, "locked": { - "lastModified": 1692792358, - "narHash": "sha256-yqKPLUvl9lFTy43+GvVRwT39k1qu7Yd0HNktZjRbUP4=", + "lastModified": 1697388351, + "narHash": "sha256-63N2eBpKaziIy4R44vjpUu8Nz5fCJY7okKrkixvDQmY=", "owner": "numtide", "repo": "treefmt-nix", - "rev": "b070c28bf9d7d3ef93084aa47c01b4b6c16cdce4", + "rev": "aae39f64f5ecbe89792d05eacea5cb241891292a", "type": "github" }, "original": { @@ -1730,11 +3616,11 @@ ] }, "locked": { - "lastModified": 1692972530, - "narHash": "sha256-LG+M7TjlLJ1lx2qbD1yaexvue1VAatpVandtHVEN5Lc=", + "lastModified": 1697388351, + "narHash": "sha256-63N2eBpKaziIy4R44vjpUu8Nz5fCJY7okKrkixvDQmY=", "owner": "numtide", "repo": "treefmt-nix", - "rev": "843e1e1b01ac7c9e858368fffd1692cbbdbe4a0e", + "rev": "aae39f64f5ecbe89792d05eacea5cb241891292a", "type": "github" }, "original": { @@ -1743,7 +3629,53 @@ "type": "github" } }, + "trouble": { + "flake": false, + "locked": { + "lastModified": 1690614197, + "narHash": "sha256-Ee0AM8S/A8DU0hyOnZoKC1hkW0fvk0A+c3WGvPqmKcU=", + "owner": "folke", + "repo": "trouble.nvim", + "rev": "40aad004f53ae1d1ba91bcc5c29d59f07c5f01d3", + "type": "github" + }, + "original": { + "owner": "folke", + "repo": "trouble.nvim", + "type": "github" + } + }, "utils": { + "locked": { + "lastModified": 1656928814, + "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_2": { + "locked": { + "lastModified": 1653893745, + "narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_3": { "locked": { "lastModified": 1605370193, "narHash": "sha256-YyMTf3URDL/otKdKgtoMChu4vfVL3vCMkRqpGifhUn0=", @@ -1758,9 +3690,139 @@ "type": "github" } }, + "vim-dirtytalk": { + "flake": false, + "locked": { + "lastModified": 1690722430, + "narHash": "sha256-kjyLwkAk6mqK7u4+zAr+Yh+zbSiukNKtXwb7t39LUco=", + "owner": "psliwka", + "repo": "vim-dirtytalk", + "rev": "a49251dce1852875951d95f7013979ece5caebf0", + "type": "github" + }, + "original": { + "owner": "psliwka", + "repo": "vim-dirtytalk", + "type": "github" + } + }, + "vim-illuminate": { + "flake": false, + "locked": { + "lastModified": 1679187974, + "narHash": "sha256-8dL3cBjQ2iY4D4gTxKVVmOGhxcSSRuDBvmEwwFIbWsQ=", + "owner": "RRethy", + "repo": "vim-illuminate", + "rev": "a2907275a6899c570d16e95b9db5fd921c167502", + "type": "github" + }, + "original": { + "owner": "RRethy", + "repo": "vim-illuminate", + "type": "github" + } + }, + "vim-markdown": { + "flake": false, + "locked": { + "lastModified": 1680951012, + "narHash": "sha256-B00rad/Bbp+kJBN/fYliOaGiUe0AfBng6gs/fVBve9A=", + "owner": "preservim", + "repo": "vim-markdown", + "rev": "cc82d88e2a791f54d2b6e2b26e41f743351ac947", + "type": "github" + }, + "original": { + "owner": "preservim", + "repo": "vim-markdown", + "type": "github" + } + }, + "vim-repeat": { + "flake": false, + "locked": { + "lastModified": 1611544268, + "narHash": "sha256-8rfZa3uKXB3TRCqaDHZ6DfzNbm7WaYnLvmTNzYtnKHg=", + "owner": "tpope", + "repo": "vim-repeat", + "rev": "24afe922e6a05891756ecf331f39a1f6743d3d5a", + "type": "github" + }, + "original": { + "owner": "tpope", + "repo": "vim-repeat", + "type": "github" + } + }, + "vim-startify": { + "flake": false, + "locked": { + "lastModified": 1620487920, + "narHash": "sha256-//3bzFTe1WKqvQ3uYrDbk5Zu5BKq2hXQGeBhmhKIHvk=", + "owner": "mhinz", + "repo": "vim-startify", + "rev": "81e36c352a8deea54df5ec1e2f4348685569bed2", + "type": "github" + }, + "original": { + "owner": "mhinz", + "repo": "vim-startify", + "type": "github" + } + }, + "vim-tidal-src": { + "flake": false, + "locked": { + "lastModified": 1685703852, + "narHash": "sha256-8gyk17YLeKpLpz3LRtxiwbpsIbZka9bb63nK5/9IUoA=", + "owner": "tidalcycles", + "repo": "vim-tidal", + "rev": "e440fe5bdfe07f805e21e6872099685d38e8b761", + "type": "github" + }, + "original": { + "owner": "tidalcycles", + "ref": "master", + "repo": "vim-tidal", + "type": "github" + } + }, + "vim-vsnip": { + "flake": false, + "locked": { + "lastModified": 1678609126, + "narHash": "sha256-ehPnvGle7YrECn76YlSY/2V7Zeq56JGlmZPlwgz2FdE=", + "owner": "hrsh7th", + "repo": "vim-vsnip", + "rev": "7753ba9c10429c29d25abfd11b4c60b76718c438", + "type": "github" + }, + "original": { + "owner": "hrsh7th", + "repo": "vim-vsnip", + "type": "github" + } + }, + "vowel-src": { + "flake": false, + "locked": { + "lastModified": 1641306144, + "narHash": "sha256-zfF6cvAGDNYWYsE8dOIo38b+dIymd17Pexg0HiPFbxM=", + "owner": "supercollider-quarks", + "repo": "vowel", + "rev": "ab59caa870201ecf2604b3efdd2196e21a8b5446", + "type": "github" + }, + "original": { + "owner": "supercollider-quarks", + "ref": "master", + "repo": "vowel", + "type": "github" + } + }, "vscode-server": { "inputs": { - "flake-utils": "flake-utils_8", + "flake-utils": "flake-utils_10", "nixpkgs": [ "nixpkgs" ] @@ -1779,22 +3841,38 @@ "type": "github" } }, + "which-key": { + "flake": false, + "locked": { + "lastModified": 1690570286, + "narHash": "sha256-B1+EHd2eH/EbD5Kip9PfhdPyyGfIkD6rsx0Z3rXvb5w=", + "owner": "folke", + "repo": "which-key.nvim", + "rev": "7ccf476ebe0445a741b64e36c78a682c1c6118b7", + "type": "github" + }, + "original": { + "owner": "folke", + "repo": "which-key.nvim", + "type": "github" + } + }, "wlroots": { "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1691073628, - "narHash": "sha256-LlxE3o3UzRY7APYVLGNKM30DBMcDifCRIQiMVSbYLIc=", + "lastModified": 1697909146, + "narHash": "sha256-jU0I6FoCKnj4zIBL4daosFWh81U1fM719Z6cae8PxSY=", "owner": "wlroots", "repo": "wlroots", - "rev": "c74f89d4f84bfed0284d3908aee5d207698c70c5", + "rev": "47bf87ade2bd32395615a385ebde1fefbcdf79a2", "type": "gitlab" }, "original": { "host": "gitlab.freedesktop.org", "owner": "wlroots", "repo": "wlroots", - "rev": "c74f89d4f84bfed0284d3908aee5d207698c70c5", + "rev": "47bf87ade2bd32395615a385ebde1fefbcdf79a2", "type": "gitlab" } }, @@ -1804,14 +3882,14 @@ "nixpkgs": [ "nixpkgs" ], - "systems": "systems_11" + "systems": "systems_13" }, "locked": { - "lastModified": 1691841170, - "narHash": "sha256-RCTm1/MVWYPnReMgyp7tr2ogGYo/pvw38jZaFwemgPU=", + "lastModified": 1697981233, + "narHash": "sha256-y8q4XUwx+gVK7i2eLjfR32lVo7TYvEslyzrmzYEaPZU=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "57a3a41ba6b358109e4fc25c6a4706b5f7d93c6b", + "rev": "22e7a65ff9633e1dedfa5317fdffc49f68de2ff2", "type": "github" }, "original": { @@ -1836,11 +3914,11 @@ ] }, "locked": { - "lastModified": 1691841170, - "narHash": "sha256-RCTm1/MVWYPnReMgyp7tr2ogGYo/pvw38jZaFwemgPU=", + "lastModified": 1697981233, + "narHash": "sha256-y8q4XUwx+gVK7i2eLjfR32lVo7TYvEslyzrmzYEaPZU=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "57a3a41ba6b358109e4fc25c6a4706b5f7d93c6b", + "rev": "22e7a65ff9633e1dedfa5317fdffc49f68de2ff2", "type": "github" }, "original": { @@ -1848,6 +3926,26 @@ "repo": "xdg-desktop-portal-hyprland", "type": "github" } + }, + "zig": { + "inputs": { + "flake-compat": "flake-compat_4", + "flake-utils": "flake-utils_6", + "nixpkgs": "nixpkgs_7" + }, + "locked": { + "lastModified": 1690718829, + "narHash": "sha256-GN19SrCqWxIJN+rnbv+pIkF/yynh6FG2y7jY6PZRiYw=", + "owner": "mitchellh", + "repo": "zig-overlay", + "rev": "92e485cc7887f57be4d2921ed077f467912b7d33", + "type": "github" + }, + "original": { + "owner": "mitchellh", + "repo": "zig-overlay", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 14c81df49..7cb657e76 100755 --- a/flake.nix +++ b/flake.nix @@ -8,6 +8,7 @@ ... } @ inputs: flake-parts.lib.mkFlake {inherit inputs;} ({withSystem, ...}: { + # The system archtecitures, more can be added as needed systems = [ "x86_64-linux" "aarch64-linux" @@ -19,89 +20,95 @@ inputs.flake-parts.flakeModules.easyOverlay inputs.treefmt-nix.flakeModule - ./parts/makeSys # args that is passsed to the flake, moved away from the main file + # flake parts + ./flake/makeSys.nix # args that is passsed to the flake, moved away from the main file + #./flake/checks.nix # checks for the flake + + # flake part programs + ./flake/programs/pre-commit.nix # pre-commit hooks + ./flake/programs/treefmt.nix # treefmt configuration + + ./flake/pkgs # packages exposed to the flake + ./flake/overlays # overlays that make the system that bit cleaner + ./flake/templates # programing templates for the quick setup of new programing enviorments + ./flake/schemas # nix schemas. whenever they actually work + ./flake/modules # nixos and home-manager modules ]; flake = let - # extended nixpkgs lib, contains my custom functions + # extended nixpkgs lib, with additonal features lib = import ./lib {inherit nixpkgs inputs;}; in { - # entry-point for nixos configurations nixosConfigurations = import ./hosts {inherit nixpkgs self lib withSystem;}; - nixosModules = { - # extends the steam module from nixpkgs/nixos to add a STEAM_COMPAT_TOOLS option - steam-compat = ./modules/extra/shared/nixos/steam; - - # we do not want to provide a default module - default = null; - }; - - homeManagerModules = { - gtklock = ./modules/extra/shared/home-manager/gtklock; - - default = null; - }; - # build with `nix build .#images.` + # alternatively hosts can be built with `nix build .#nixosConfigurations.hostName.config.system.build.isoImage` images = import ./hosts/images.nix {inherit inputs self lib;}; }; perSystem = { config, - inputs', pkgs, ... }: { imports = [{_module.args.pkgs = config.legacyPackages;}]; - # provide the formatter for nix fmt + # formatter for nix fmt formatter = pkgs.alejandra; - devShells.default = let - extra = import ./parts/devShell; - in - inputs'.devshell.legacyPackages.mkShell { - name = "setup"; - commands = extra.shellCommands; - env = extra.shellEnv; - packages = with pkgs; [ - config.treefmt.build.wrapper # treewide formatter - nil # nix ls - alejandra # nix formatter - git # flakes require git, and so do I - glow # markdown viewer - statix # lints and suggestions - deadnix # clean up unused nix code - ]; - }; - - # configure treefmt - treefmt = { - projectRootFile = "flake.nix"; - - programs = { - alejandra.enable = true; - deadnix.enable = false; - shellcheck.enable = true; - shfmt = { - enable = true; - # https://flake.parts/options/treefmt-nix.html#opt-perSystem.treefmt.programs.shfmt.indent_size - # 0 causes shfmt to use tabs - indent_size = 0; - }; - }; + devShells.default = pkgs.mkShell { + name = "dotfiles"; + meta.description = "Devlopment shell for this configuration"; + + shellHook = '' + ${config.pre-commit.installationScript} + ''; + + # tell direnv to shut up + DIRENV_LOG_FORMAT = ""; + + packages = with pkgs; [ + config.treefmt.build.wrapper # treewide formatter + nil # nix language server + alejandra # nix formatter + git # flakes require git + glow # fancy markdown viewer + statix # lints and suggestions + deadnix # clean up unused nix code + (pkgs.writeShellApplication { + name = "update"; + text = '' + ${pkgs.runtimeShell} + nix flake update && git commit flake.lock -m "flake: bump inputs" + ''; + }) + ]; + + inputsFrom = [ + config.treefmt.build.devShell + ]; }; }; }); inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-parts = { url = "github:hercules-ci/flake-parts"; inputs.nixpkgs-lib.follows = "nixpkgs"; }; - nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + + # too hard to explain + pre-commit-hooks = { + url = "github:cachix/pre-commit-hooks.nix"; + inputs = { + nixpkgs.follows = "nixpkgs"; + flake-utils.follows = "flake-utils"; + }; + }; # Nix helper nh = { @@ -109,11 +116,17 @@ inputs.nixpkgs.follows = "nixpkgs"; }; + # Run unpatched dynamic binaries on NixOS nix-ld = { url = "github:Mic92/nix-ld"; inputs.nixpkgs.follows = "nixpkgs"; }; + nix-index-db = { + url = "github:nix-community/nix-index-database"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + # a tree-wide formatter treefmt-nix = { url = "github:numtide/treefmt-nix"; @@ -132,13 +145,12 @@ inputs.nixpkgs.follows = "nixpkgs"; }; - # Automated, pre-built packages for Wayland + # Packages for Wayland nixpkgs-wayland = { url = "github:nix-community/nixpkgs-wayland"; inputs.nixpkgs.follows = "nixpkgs"; }; - # Nix gaming packages nix-gaming = { url = "github:fufexan/nix-gaming"; inputs.nixpkgs.follows = "nixpkgs"; @@ -163,10 +175,11 @@ inputs.rust-overlay.follows = "rust-overlay"; }; - # Amazing themeing + # Amazing themeing & tools catppuccin.url = "github:isabelroses/ctp-nix"; + catppuccin-toolbox.url = "github:catppuccin/toolbox"; - # Secrets + # Secrets, shhh sops = { url = "github:Mic92/sops-nix"; inputs.nixpkgs.follows = "nixpkgs"; @@ -186,6 +199,12 @@ inputs.nixpkgs.follows = "nixpkgs"; }; + # More up to date auto-cpufreq + auto-cpufreq = { + url = "github:AdnanHodzic/auto-cpufreq"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + # Firefox but really locked down and air tight schizofox = { url = "github:schizofox/schizofox"; @@ -195,6 +214,21 @@ }; }; + # cool bars + ags = { + url = "github:Aylur/ags"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + # lovely app + bellado.url = "github:isabelroses/bellado"; + + # cool wallpaper maker + catppuccinifier = { + url = "github:lighttigerXIV/catppuccinifier"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + # secure-boot on nixos lanzaboote = { url = "github:nix-community/lanzaboote"; @@ -204,28 +238,27 @@ # mailserver on nixos simple-nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/master"; - # nushell scripts - nu_scripts = { - type = "git"; - url = "https://github.com/nushell/nu_scripts"; - submodules = true; - flake = false; - }; - - # my nvim conf - isabel-nvim = { - type = "git"; - url = "https://github.com/isabelroses/nvim"; - submodules = false; - flake = false; + # Highly customisable nixos neovim flake + neovim-flake = { + url = "github:NotAShelf/neovim-flake"; + inputs = { + nixpkgs.follows = "nixpkgs"; + nil.follows = "nil"; + flake-utils.follows = "flake-utils"; + flake-parts.follows = "flake-parts"; + }; }; # nur's - nur.url = "github:nix-community/nur"; - bella-nur.url = "github:isabelroses/nur"; - nekowinston-nur.url = "github:nekowinston/nur"; + # nur.url = "github:nix-community/nur"; + # nekowinston-nur.url = "github:nekowinston/nur"; + + # Schemas + flake-schemas.url = "github:DeterminateSystems/flake-schemas"; + nixSchemas.url = "github:DeterminateSystems/nix/flake-schemas"; }; + # This allows for the gathering of prebuilt binaries, making building much faster nixConfig = { extra-substituters = [ "https://nix-community.cachix.org" diff --git a/flake/checks.nix b/flake/checks.nix new file mode 100644 index 000000000..f15c7b721 --- /dev/null +++ b/flake/checks.nix @@ -0,0 +1,14 @@ +{inputs, ...}: { + imports = [inputs.pre-commit-hooks.flakeModule]; + + perSystem = {system, ...}: { + checks.${system} = { + pre-commit = inputs.pre-commit-hooks.lib.${system}.run { + src = ./.; + hooks = { + alejandra.enable = true; + }; + }; + }; + }; +} diff --git a/parts/makeSys/default.nix b/flake/makeSys.nix similarity index 100% rename from parts/makeSys/default.nix rename to flake/makeSys.nix diff --git a/flake/modules/default.nix b/flake/modules/default.nix new file mode 100644 index 000000000..4c5079d94 --- /dev/null +++ b/flake/modules/default.nix @@ -0,0 +1,19 @@ +{self, ...}: let + mkModule = path: + if builtins.isPath path + then self + path + else builtins.throw "${path} does not exist"; +in { + flake = { + nixosModules = { + # i do not provide a default module, so throw an error + default = builtins.throw "There is no default module."; + }; + + homeManagerModules = { + gtklock = mkModule /modules/extra/shared/home-manager/gtklock; + + default = builtins.throw "There is no default module."; + }; + }; +} diff --git a/flake/overlays/btop.nix b/flake/overlays/btop.nix new file mode 100644 index 000000000..b2a5b244b --- /dev/null +++ b/flake/overlays/btop.nix @@ -0,0 +1,14 @@ +_: prev: { + btop = + if prev.stdenv.isLinux + then + prev.symlinkJoin { + inherit (prev.btop) passthru; + name = "btop-nodesktop"; + paths = [prev.btop]; + postBuild = '' + rm $out/share/applications/btop.desktop + ''; + } + else prev.btop; +} diff --git a/flake/overlays/default.nix b/flake/overlays/default.nix new file mode 100644 index 000000000..0d4bfde12 --- /dev/null +++ b/flake/overlays/default.nix @@ -0,0 +1,8 @@ +{lib, ...}: { + flake.overlays.default = lib.composeManyExtensions [ + (import ./btop.nix) + (import ./fish.nix) + (import ./neovim.nix) + (import ./ranger.nix) + ]; +} diff --git a/flake/overlays/fish.nix b/flake/overlays/fish.nix new file mode 100644 index 000000000..4e7fffc90 --- /dev/null +++ b/flake/overlays/fish.nix @@ -0,0 +1,14 @@ +_: prev: { + fish = + if prev.stdenv.isLinux + then + prev.symlinkJoin { + inherit (prev.fish) passthru; + name = "fish-nodesktop"; + paths = [prev.fish]; + postBuild = '' + rm $out/share/applications/fish.desktop + ''; + } + else prev.fish; +} diff --git a/flake/overlays/neovim.nix b/flake/overlays/neovim.nix new file mode 100644 index 000000000..61b5c4438 --- /dev/null +++ b/flake/overlays/neovim.nix @@ -0,0 +1,14 @@ +_: prev: { + neovim = + if prev.stdenv.isLinux + then + prev.symlinkJoin { + inherit (prev.neovim) passthru; + name = "neovim-nodesktop"; + paths = [prev.neovim]; + postBuild = '' + rm $out/share/applications/*.desktop + ''; + } + else prev.neovim; +} diff --git a/flake/overlays/ranger.nix b/flake/overlays/ranger.nix new file mode 100644 index 000000000..a85c6c47f --- /dev/null +++ b/flake/overlays/ranger.nix @@ -0,0 +1,14 @@ +_: prev: { + btop = + if prev.stdenv.isLinux + then + prev.symlinkJoin { + inherit (prev.ranger) passthru; + name = "btop-nodesktop"; + paths = [prev.ranger]; + postBuild = '' + rm $out/share/applications/ranger.desktop + ''; + } + else prev.btop; +} diff --git a/flake/pkgs/cyberchef.nix b/flake/pkgs/cyberchef.nix new file mode 100644 index 000000000..6238fdfe8 --- /dev/null +++ b/flake/pkgs/cyberchef.nix @@ -0,0 +1,35 @@ +{ + pkgs ? import {}, + stdenv ? pkgs.stdenv, + lib ? pkgs.lib, + ... +}: +stdenv.mkDerivation rec { + pname = "cyberchef"; + version = "10.4.0"; + + src = pkgs.fetchzip { + url = "https://github.com/gchq/CyberChef/releases/download/v${version}/CyberChef_v${version}.zip"; + sha256 = "sha256-BjdeOTVZUMitmInL/kE6a/aw/lH4YwKNWxdi0B51xzc="; + stripRoot = false; + }; + + nativeBuildInputs = [ + pkgs.unzip + ]; + + phases = ["installPhase"]; + + installPhase = '' + mkdir $out + cp -r ${src}/* $out + cp -r $out/CyberChef_v${version}.html $out/index.html + ''; + + meta = with lib; { + description = " The Cyber Swiss Army Knife - a web app for encryption, encoding, compression and data analysis"; + homepage = "https://gchq.github.io/CyberChef"; + license = licenses.mit; + maintainers = with maintainers; [isabelroses]; + }; +} diff --git a/flake/pkgs/default.nix b/flake/pkgs/default.nix new file mode 100644 index 000000000..9dad5506c --- /dev/null +++ b/flake/pkgs/default.nix @@ -0,0 +1,24 @@ +_: { + systems = [ + "x86_64-linux" + "aarch64-linux" + ]; + + perSystem = { + pkgs, + inputs', + ... + }: { + packages = { + cybershef = pkgs.callPackage ./cyberchef.nix {}; + # https://github.com/NixOS/nixpkgs/issues/195512 + lutgen-rs = pkgs.callPackage ./lutgen-rs.nix {}; + patched-gjs = pkgs.callPackage ./patched-gjs.nix {}; + plymouth-theme-catppuccin = pkgs.callPackage ./plymouth-theme-catppuccin.nix {}; + + bellado = inputs'.bellado.packages.default; + catppuccinifier-cli = inputs'.catppuccinifier.packages.cli; + ags = inputs'.ags.packages.default; + }; + }; +} diff --git a/flake/pkgs/lutgen-rs.nix b/flake/pkgs/lutgen-rs.nix new file mode 100644 index 000000000..776bd6de7 --- /dev/null +++ b/flake/pkgs/lutgen-rs.nix @@ -0,0 +1,28 @@ +{ + fetchFromGitHub, + lib, + rustPlatform, +}: let + commit = "76b728a876741ac724cfb8eaaac1fd467c2d5d0e"; +in + rustPlatform.buildRustPackage rec { + pname = "lutgen-rs"; + version = builtins.substring 0 7 commit; + + src = fetchFromGitHub { + owner = "ozwaldorf"; + repo = pname; + rev = commit; + sha256 = "ntKNWvVP9m+GQPct9grY/1AfXGdHpLuYzTwiV1FY6vY="; + }; + + cargoSha256 = "sha256-StVgZBZ36fTneTtZAg5rlpqG0JVFlEDYFeBpk+8Hg+o="; + + meta = with lib; { + description = "A blazingly fast interpolated LUT generator and applicator for arbitrary and popular color palettes. Theme any image to your dekstop colorscheme!"; + homepage = "https://github.com/ozwaldorf/lutgen-rs"; + license = licenses.mit; + maintainers = with maintainers; [isabelroses]; + platforms = platforms.linux; + }; + } diff --git a/flake/pkgs/patched-gjs.nix b/flake/pkgs/patched-gjs.nix new file mode 100644 index 000000000..40c3abb71 --- /dev/null +++ b/flake/pkgs/patched-gjs.nix @@ -0,0 +1,171 @@ +{ + fetchurl, + lib, + stdenv, + meson, + mesonEmulatorHook, + ninja, + pkg-config, + gnome, + gtk3, + atk, + gobject-introspection, + spidermonkey_102, + pango, + cairo, + readline, + libsysprof-capture, + glib, + libxml2, + dbus, + gdk-pixbuf, + networkmanager, + harfbuzz, + makeWrapper, + wrapGAppsHook, + which, + xvfb-run, + nixosTests, + upower, + glib-networking, + gtk-layer-shell, +}: let + testDeps = [ + gtk3 + atk + pango.out + gdk-pixbuf + harfbuzz + ]; +in + stdenv.mkDerivation rec { + pname = "gjs"; + version = "1.76.2"; + + outputs = ["out" "dev" "installedTests"]; + + src = fetchurl { + url = "mirror://gnome/sources/gjs/${lib.versions.majorMinor version}/${pname}-${version}.tar.xz"; + sha256 = "sha256-99jJ1lPqb9eK/kpQcg4EaqK/wHj9pjXdEwZ90ZnGJdQ="; + }; + + patches = [ + # Hard-code various paths + ./patches/gjs-fix-paths.patch + + # Allow installing installed tests to a separate output. + ./patches/gjs-installed-tests-path.patch + ]; + + nativeBuildInputs = + [ + meson + ninja + pkg-config + makeWrapper + wrapGAppsHook + which # for locale detection + libxml2 # for xml-stripblanks + dbus # for dbus-run-session + gobject-introspection + ] + ++ lib.optionals (!stdenv.buildPlatform.canExecute stdenv.hostPlatform) [ + mesonEmulatorHook + ]; + + buildInputs = [ + cairo + upower + gnome.gnome-bluetooth + glib-networking + gtk-layer-shell + networkmanager + readline + libsysprof-capture + spidermonkey_102 + ]; + + nativeCheckInputs = + [ + xvfb-run + ] + ++ testDeps; + + propagatedBuildInputs = [ + glib + ]; + + mesonFlags = + [ + "-Dinstalled_test_prefix=${placeholder "installedTests"}" + ] + ++ lib.optionals (!stdenv.isLinux || stdenv.hostPlatform.isMusl) [ + "-Dprofiler=disabled" + ]; + + doCheck = !stdenv.isDarwin; + + postPatch = + '' + patchShebangs build/choose-tests-locale.sh + substituteInPlace installed-tests/debugger-test.sh --subst-var-by gjsConsole $out/bin/gjs-console + '' + + lib.optionalString stdenv.hostPlatform.isMusl '' + substituteInPlace installed-tests/js/meson.build \ + --replace "'Encoding'," "#'Encoding'," + ''; + + preCheck = '' + # Our gobject-introspection patches make the shared library paths absolute + # in the GIR files. When running tests, the library is not yet installed, + # though, so we need to replace the absolute path with a local one during build. + # We are using a symlink that will be overridden during installation. + mkdir -p $out/lib $installedTests/libexec/installed-tests/gjs + ln -s $PWD/libgjs.so.0 $out/lib/libgjs.so.0 + ln -s $PWD/installed-tests/js/libgimarshallingtests.so $installedTests/libexec/installed-tests/gjs/libgimarshallingtests.so + ln -s $PWD/installed-tests/js/libgjstesttools/libgjstesttools.so $installedTests/libexec/installed-tests/gjs/libgjstesttools.so + ln -s $PWD/installed-tests/js/libregress.so $installedTests/libexec/installed-tests/gjs/libregress.so + ln -s $PWD/installed-tests/js/libwarnlib.so $installedTests/libexec/installed-tests/gjs/libwarnlib.so + ''; + + postInstall = '' + # TODO: make the glib setup hook handle moving the schemas in other outputs. + installedTestsSchemaDatadir="$installedTests/share/gsettings-schemas/${pname}-${version}" + mkdir -p "$installedTestsSchemaDatadir" + mv "$installedTests/share/glib-2.0" "$installedTestsSchemaDatadir" + ''; + + postFixup = '' + wrapProgram "$installedTests/libexec/installed-tests/gjs/minijasmine" \ + --prefix XDG_DATA_DIRS : "$installedTestsSchemaDatadir" \ + --prefix GI_TYPELIB_PATH : "${lib.makeSearchPath "lib/girepository-1.0" testDeps}" + ''; + + checkPhase = '' + runHook preCheck + xvfb-run -s '-screen 0 800x600x24' \ + meson test --print-errorlogs + runHook postCheck + ''; + + separateDebugInfo = stdenv.isLinux; + + passthru = { + tests = { + installed-tests = nixosTests.installed-tests.gjs; + }; + + updateScript = gnome.updateScript { + packageName = "gjs"; + versionPolicy = "odd-unstable"; + }; + }; + + meta = with lib; { + description = "JavaScript bindings for GNOME"; + homepage = "https://gitlab.gnome.org/GNOME/gjs/blob/master/doc/Home.md"; + license = licenses.lgpl2Plus; + maintainers = teams.gnome.members; + platforms = platforms.unix; + }; + } diff --git a/flake/pkgs/patches/gjs-fix-paths.patch b/flake/pkgs/patches/gjs-fix-paths.patch new file mode 100644 index 000000000..5ca5372ea --- /dev/null +++ b/flake/pkgs/patches/gjs-fix-paths.patch @@ -0,0 +1,13 @@ +diff --git a/installed-tests/debugger-test.sh b/installed-tests/debugger-test.sh +index 0d118490..54c5507e 100755 +--- a/installed-tests/debugger-test.sh ++++ b/installed-tests/debugger-test.sh +@@ -3,7 +3,7 @@ + if test "$GJS_USE_UNINSTALLED_FILES" = "1"; then + gjs="$TOP_BUILDDIR/gjs-console" + else +- gjs=gjs-console ++ gjs=@gjsConsole@ + fi + + echo 1..1 diff --git a/flake/pkgs/patches/gjs-installed-tests-path.patch b/flake/pkgs/patches/gjs-installed-tests-path.patch new file mode 100644 index 000000000..09cd8eaff --- /dev/null +++ b/flake/pkgs/patches/gjs-installed-tests-path.patch @@ -0,0 +1,37 @@ +diff --git a/installed-tests/meson.build b/installed-tests/meson.build +index 04c7910f..9647908c 100644 +--- a/installed-tests/meson.build ++++ b/installed-tests/meson.build +@@ -1,7 +1,7 @@ + ### Installed tests ############################################################ + +-installed_tests_execdir = get_option('prefix') / get_option('libexecdir') / 'installed-tests' / meson.project_name() +-installed_tests_metadir = abs_datadir / 'installed-tests' / meson.project_name() ++installed_tests_execdir = get_option('installed_test_prefix') / 'libexec' / 'installed-tests' / meson.project_name() ++installed_tests_metadir = get_option('installed_test_prefix') / 'share' / 'installed-tests' / meson.project_name() + + # Simple shell script tests # + +diff --git a/meson.build b/meson.build +index 9ab29475..42ffe07f 100644 +--- a/meson.build ++++ b/meson.build +@@ -557,7 +557,7 @@ install_data('installed-tests/extra/lsan.supp', + install_dir: get_option('datadir') / api_name / 'lsan') + + if get_option('installed_tests') +- schemadir = abs_datadir / 'glib-2.0' / 'schemas' ++ schemadir = get_option('installed_test_prefix') / 'share' / 'glib-2.0' / 'schemas' + install_data('installed-tests/js/org.gnome.GjsTest.gschema.xml', install_dir: schemadir) + meson.add_install_script('build/compile-gschemas.py', schemadir) + endif +diff --git a/meson_options.txt b/meson_options.txt +index 825ba77a..21f0323c 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -25,3 +25,5 @@ option('skip_gtk_tests', type: 'boolean', value: false, + description: 'Skip tests that need a display connection') + option('verbose_logs', type: 'boolean', value: false, + description: 'Enable extra log messages that may decrease performance (not allowed in release builds)') ++option('installed_test_prefix', type: 'string', value: '', ++ description: 'Prefix for installed tests') diff --git a/flake/pkgs/plymouth-theme-catppuccin.nix b/flake/pkgs/plymouth-theme-catppuccin.nix new file mode 100644 index 000000000..92ff16b20 --- /dev/null +++ b/flake/pkgs/plymouth-theme-catppuccin.nix @@ -0,0 +1,33 @@ +{ + lib, + pkgs, + stdenvNoCC, +}: +stdenvNoCC.mkDerivation { + pname = "plymouth-theme-catppuccin"; + version = "2022-12-10"; + + src = pkgs.fetchFromGitHub { + owner = "catppuccin"; + repo = "plymouth"; + rev = "d4105cf336599653783c34c4a2d6ca8c93f9281c"; + sha256 = "sha256-quBSH8hx3gD7y1JNWAKQdTk3CmO4t1kVo4cOGbeWlNE="; + }; + + installPhase = '' + mkdir -p "$out/share/plymouth/themes/" + cp -r "themes/"* "$out/share/plymouth/themes/" + + themes=("mocha" "macchiato" "frappe" "latte") + for dir in "''${themes[@]}"; do + cat "themes/catppuccin-''${dir}/catppuccin-''${dir}.plymouth" | sed "s@\/usr\/@''${out}\/@" > "''${out}/share/plymouth/themes/catppuccin-''${dir}/catppuccin-''${dir}.plymouth" + done + ''; + + meta = with lib; { + description = "Soothing pastel theme for Plymouth"; + homepage = "https://github.com/catppuccin/plymouth"; + license = licenses.mit; + platforms = platforms.linux; + }; +} diff --git a/flake/pkgs/sddm.nix b/flake/pkgs/sddm.nix new file mode 100644 index 000000000..5972c259a --- /dev/null +++ b/flake/pkgs/sddm.nix @@ -0,0 +1,31 @@ +{ + pkgs, + lib, +}: let + commit = "7fc67d1027cdb7f4d833c5d23a8c34a0029b0661"; +in + pkgs.stdenv.mkDerivation { + pname = "sddm-catppucin"; + version = builtins.substring 0 7 commit; + + src = pkgs.fetchFromGitHub { + owner = "catppuccin"; + repo = "sddm"; + rev = commit; + sha256 = "sha256-SjYwyUvvx/ageqVH5MmYmHNRKNvvnF3DYMJ/f2/L+Go="; + }; + + dontBuild = true; + installPhase = '' + mkdir -p $out/ + cp -R $src/src/catppuccin-mocha/* $out/ + ''; + + meta = with lib; { + description = "Catppucin for SDDM"; + homepage = "https://github.com/catppuccin/sddm"; + license = licenses.mit; + maintainers = with maintainers; [isabelroses]; + platforms = platforms.linux; + }; + } diff --git a/parts/devShell/default.nix b/flake/programs/devShell/default.nix similarity index 100% rename from parts/devShell/default.nix rename to flake/programs/devShell/default.nix diff --git a/flake/programs/pre-commit.nix b/flake/programs/pre-commit.nix new file mode 100644 index 000000000..8e5be567e --- /dev/null +++ b/flake/programs/pre-commit.nix @@ -0,0 +1,32 @@ +{inputs, ...}: { + imports = [inputs.pre-commit-hooks.flakeModule]; + + perSystem.pre-commit = let + excludes = ["flake.lock" "secrets.yaml"]; + + mkHook = name: prev: + { + inherit excludes; + description = "pre-commit hook for ${name}"; + fail_fast = true; + verbose = true; + } + // prev; + in { + check.enable = true; + + settings = { + inherit excludes; + + hooks = { + alejandra = mkHook "Alejandra" {enable = true;}; + actionlint = mkHook "actionlint" {enable = true;}; + prettier = mkHook "prettier" {enable = true;}; + editorconfig-checker = mkHook "editorconfig" { + enable = false; + always_run = true; + }; + }; + }; + }; +} diff --git a/flake/programs/treefmt.nix b/flake/programs/treefmt.nix new file mode 100644 index 000000000..3f11cad1f --- /dev/null +++ b/flake/programs/treefmt.nix @@ -0,0 +1,31 @@ +_: { + systems = ["x86_64-linux" "aarch64-linux"]; + + perSystem = {pkgs, ...}: { + treefmt = { + projectRootFile = "flake.nix"; + + programs = { + alejandra.enable = true; + deadnix.enable = false; + shellcheck.enable = true; + + prettier = { + enable = true; + package = pkgs.prettierd; + excludes = []; + settings = { + editorconfig = true; + }; + }; + + shfmt = { + enable = true; + # https://flake.parts/options/treefmt-nix.html#opt-perSystem.treefmt.programs.shfmt.indent_size + # 0 causes shfmt to use tabs + indent_size = 2; + }; + }; + }; + }; +} diff --git a/flake/schemas/default.nix b/flake/schemas/default.nix new file mode 100644 index 000000000..e1b62968b --- /dev/null +++ b/flake/schemas/default.nix @@ -0,0 +1,9 @@ +{inputs, ...}: let + schemas = import ./schemas.nix; +in { + flake = { + # extensible flake schemas + # https://github.com/DeterminateSystems/flake-schemas + schemas = inputs.flake-schemas.schemas // schemas; + }; +} diff --git a/flake/schemas/schemas.nix b/flake/schemas/schemas.nix new file mode 100644 index 000000000..eb00c4f2c --- /dev/null +++ b/flake/schemas/schemas.nix @@ -0,0 +1,21 @@ +{ + homeManagerModules = { + version = 1; + doc = "The `homeManagerModules` flake output defines Home-Manager modules exported by the flake."; + inventory = output: let + recurse = attrs: { + children = (name: value: + if builtins.isAttrs value + then { + # Tell `nix flake show` what this is. + what = "exported home-manager module"; + # Make `nix flake check` enforce the camel case naming convention. + evalChecks.camelCase = builtins.match "[a-z]+((\d)|([A-Z0-9][a-z0-9]+))*([A-Z])?" name == []; + } + else throw "unsupported 'homeManagerModules' type") + attrs; + }; + in + recurse output; + }; +} diff --git a/flake/templates/c/.editorconfig b/flake/templates/c/.editorconfig new file mode 100644 index 000000000..f2676050e --- /dev/null +++ b/flake/templates/c/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.c] +ident_style = space +ident_size = 4 + +[Makefile*] +ident_style = tab +ident_size = 4 diff --git a/flake/templates/c/default.nix b/flake/templates/c/default.nix new file mode 100644 index 000000000..f0198681e --- /dev/null +++ b/flake/templates/c/default.nix @@ -0,0 +1,9 @@ +{clangStdenv}: +clangStdenv.mkDerivation { + pname = "sample-c-cpp"; + version = "0.0.1"; + + src = ./.; + + makeFlags = ["PREFIX=$(out)"]; +} diff --git a/flake/templates/c/flake.nix b/flake/templates/c/flake.nix new file mode 100644 index 000000000..2d309391e --- /dev/null +++ b/flake/templates/c/flake.nix @@ -0,0 +1,25 @@ +{ + description = "C/C++ Project Template"; + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs"; + }; + + outputs = { + self, + nixpkgs, + ... + }: let + systems = ["x86_64-linux" "aarch64-linux"]; + forEachSystem = nixpkgs.lib.genAttrs systems; + + pkgsForEach = nixpkgs.legacyPackages; + in { + packages = forEachSystem (system: { + default = pkgsForEach.${system}.callPackage ./default.nix {}; + }); + + devShells = forEachSystem (system: { + default = pkgsForEach.${system}.callPackage ./shell.nix {}; + }); + }; +} diff --git a/flake/templates/c/makefile b/flake/templates/c/makefile new file mode 100644 index 000000000..01a94a964 --- /dev/null +++ b/flake/templates/c/makefile @@ -0,0 +1,42 @@ +PREFIX ?= /usr/local # this is overriden by the derivation makeFlags +BIN_DIR ?= $(PREFIX)/bin + + +TARGET_EXEC ?= foo-bar +BUILD_DIR ?= ./build +SRC_DIRS ?= ./src + +SRCS := $(shell find $(SRC_DIRS) -name *.cpp -or -name *.c) +OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) +DEPS := $(OBJS:.o=.d) + +INC_DIRS := $(shell find $(SRC_DIRS) -type d) +INC_FLAGS := $(addprefix -I,$(INC_DIRS)) + +CPPFLAGS ?= $(INC_FLAGS) -MMD -MP + +$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS) + $(CXX) $(OBJS) -o $@ $(LDFLAGS) + +# c source +$(BUILD_DIR)/%.c.o: %.c + mkdir -p $(dir $@) + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + +# c++ source +$(BUILD_DIR)/%.cpp.o: %.cpp + mkdir -p $(dir $@) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@ + +.PHONY: clean install run + +clean: + rm -r $(BUILD_DIR) + +install: $(BUILD_DIR)/$(TARGET_EXEC) + install -Dt $(BIN_DIR) $< + +run: $(BUILD_DIR)/$(TARGET_EXEC) + ./$< + +-include $(DEPS) diff --git a/flake/templates/c/shell.nix b/flake/templates/c/shell.nix new file mode 100644 index 000000000..7f542b918 --- /dev/null +++ b/flake/templates/c/shell.nix @@ -0,0 +1,19 @@ +{ + callPackage, + clang-tools, + gnumake, + libcxx, + cppcheck, +}: let + mainPkg = callPackage ./default.nix {}; +in + mainPkg.overrideAttrs (oa: { + nativeBuildInputs = + [ + clang-tools # fix headers not found + gnumake # builder + libcxx # stdlib for cpp + cppcheck # static analysis + ] + ++ (oa.nativeBuildInputs or []); + }) diff --git a/flake/templates/c/src/main.cpp b/flake/templates/c/src/main.cpp new file mode 100644 index 000000000..027a27333 --- /dev/null +++ b/flake/templates/c/src/main.cpp @@ -0,0 +1,7 @@ +#include + +int main() { + std::cout << "Hello, World!"; + + return 0; +} diff --git a/flake/templates/default.nix b/flake/templates/default.nix new file mode 100644 index 000000000..9a6a52c2f --- /dev/null +++ b/flake/templates/default.nix @@ -0,0 +1,28 @@ +_: { + flake.templates = { + c = { + path = ./c; # C/C++ + description = "Development environment for C/C++"; + }; + + rust = { + path = ./rust; # Rust + description = "Development environment for Rust"; + }; + + node = { + path = ./node; # NodeJS + description = "Development environment for NodeJS"; + }; + + go = { + path = ./go; # golang + description = "Development environment for Golang"; + }; + + python = { + path = ./python; # Python + description = "Development environment for Python"; + }; + }; +} diff --git a/flake/templates/go/default.nix b/flake/templates/go/default.nix new file mode 100644 index 000000000..69843783c --- /dev/null +++ b/flake/templates/go/default.nix @@ -0,0 +1,11 @@ +{buildGoModule}: +buildGoModule { + pname = "sample-go"; + version = "0.0.1"; + + src = ./.; + + vendorHash = null; + + ldflags = ["-s" "-w"]; +} diff --git a/flake/templates/go/flake.nix b/flake/templates/go/flake.nix new file mode 100644 index 000000000..0a3b2e211 --- /dev/null +++ b/flake/templates/go/flake.nix @@ -0,0 +1,26 @@ +{ + description = "Golang Project Template"; + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs"; + }; + + outputs = { + self, + nixpkgs, + }: let + systems = ["x86_64-linux" "aarch64-linux"]; + forEachSystem = nixpkgs.lib.genAttrs systems; + + pkgsForEach = nixpkgs.legacyPackages; + in rec { + packages = forEachSystem (system: { + default = pkgsForEach.${system}.callPackage ./default.nix {}; + }); + + devShells = forEachSystem (system: { + default = pkgsForEach.${system}.callPackage ./shell.nix {}; + }); + + hydraJobs = packages; + }; +} diff --git a/flake/templates/go/go.mod b/flake/templates/go/go.mod new file mode 100644 index 000000000..51af4705b --- /dev/null +++ b/flake/templates/go/go.mod @@ -0,0 +1,3 @@ +module notashelf.dev/sample + +go 1.20 diff --git a/flake/templates/go/main.go b/flake/templates/go/main.go new file mode 100644 index 000000000..a3dd973f0 --- /dev/null +++ b/flake/templates/go/main.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("Hello, World!") +} diff --git a/flake/templates/go/shell.nix b/flake/templates/go/shell.nix new file mode 100644 index 000000000..57104c6b5 --- /dev/null +++ b/flake/templates/go/shell.nix @@ -0,0 +1,15 @@ +{ + callPackage, + gopls, + go, +}: let + mainPkg = callPackage ./default.nix {}; +in + mainPkg.overrideAttrs (oa: { + nativeBuildInputs = + [ + gopls + go + ] + ++ (oa.nativeBuildInputs or []); + }) diff --git a/flake/templates/node/.gitignore b/flake/templates/node/.gitignore new file mode 100644 index 000000000..d5397511d --- /dev/null +++ b/flake/templates/node/.gitignore @@ -0,0 +1,3 @@ +result +build +node_modules diff --git a/flake/templates/node/default.nix b/flake/templates/node/default.nix new file mode 100644 index 000000000..5bb53bcb9 --- /dev/null +++ b/flake/templates/node/default.nix @@ -0,0 +1,12 @@ +{ + lib, + buildNpmPackage, +}: +buildNpmPackage { + pname = "foo-bar"; + version = "0.1.0"; + + src = ./.; + + npmDepsHash = lib.fakeSha256; +} diff --git a/flake/templates/node/flake.nix b/flake/templates/node/flake.nix new file mode 100644 index 000000000..d12fe4e8b --- /dev/null +++ b/flake/templates/node/flake.nix @@ -0,0 +1,26 @@ +{ + description = "NodeJS Project Template"; + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs"; + }; + + outputs = { + self, + nixpkgs, + }: let + systems = ["x86_64-linux" "aarch64-linux"]; + forEachSystem = nixpkgs.lib.genAttrs systems; + + pkgsForEach = nixpkgs.legacyPackages; + in rec { + packages = forEachSystem (system: { + default = pkgsForEach.${system}.callPackage ./default.nix {}; + }); + + devShells = forEachSystem (system: { + default = pkgsForEach.${system}.callPackage ./shell.nix {}; + }); + + hydraJobs = packages; + }; +} diff --git a/flake/templates/node/package.json b/flake/templates/node/package.json new file mode 100644 index 000000000..d362ca6d7 --- /dev/null +++ b/flake/templates/node/package.json @@ -0,0 +1,19 @@ +{ + "name": "sample-nodejs", + "version": "0.0.1", + "description": "Sample node program", + "bin": { + "sample-node": "build/index.js" + }, + "scripts": { + "build": "tsc", + "start": "npm run build && node build/index.js" + }, + "author": "NotAShelf", + "license": "MIT", + "devDependencies": { + "@types/node": "^20.1.2", + "typescript": "^5.0.4", + "typescript-language-server": "^3.3.2" + } +} diff --git a/flake/templates/node/shell.nix b/flake/templates/node/shell.nix new file mode 100644 index 000000000..58ec4b342 --- /dev/null +++ b/flake/templates/node/shell.nix @@ -0,0 +1,24 @@ +{ + callPackage, + writeShellScriptBin, + eslint_d, + prettierd, +}: let + mainPkg = callPackage ./default.nix {}; + mkNpxAlias = name: writeShellScriptBin name "npx ${name} \"$@\""; +in + mainPkg.overrideAttrs (oa: { + nativeBuildInputs = + [ + eslint_d + prettierd + (mkNpxAlias "tsc") + (mkNpxAlias "tsserver") + ] + ++ (oa.nativeBuildInputs or []); + + shellHook = '' + eslint_d start # start eslint daemon + eslint_d status # inform user about eslint daemon status + ''; + }) diff --git a/flake/templates/node/src/index.ts b/flake/templates/node/src/index.ts new file mode 100644 index 000000000..940a3ff0e --- /dev/null +++ b/flake/templates/node/src/index.ts @@ -0,0 +1 @@ +console.log("Hello world!"); diff --git a/flake/templates/node/tsconfig.json b/flake/templates/node/tsconfig.json new file mode 100644 index 000000000..0e48dd3ac --- /dev/null +++ b/flake/templates/node/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "es2016", + "lib": ["es6"], + "module": "commonjs", + "rootDir": "src", + "resolveJsonModule": true, + "allowJs": true, + "outDir": "build", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitAny": true, + "skipLibCheck": true + } +} diff --git a/flake/templates/python/.envrc b/flake/templates/python/.envrc new file mode 100644 index 000000000..fcffbd531 --- /dev/null +++ b/flake/templates/python/.envrc @@ -0,0 +1 @@ +use flake . --builders "" diff --git a/flake/templates/python/default.nix b/flake/templates/python/default.nix new file mode 100644 index 000000000..b7c031325 --- /dev/null +++ b/flake/templates/python/default.nix @@ -0,0 +1,24 @@ +{ + lib, + python3Packages, + doCheck ? false, + ... +}: +python3Packages.buildPythonApplication { + pname = "sample-python-project"; + version = "0.0.1"; + + src = ./.; + + propagatedBuildInputs = with python3Packages; []; + + nativeCheckInputs = [ + python3Packages.pytest + ]; + + checkPhase = lib.optionals doCheck '' + runHook preCheck + pytest + runHook postCheck + ''; +} diff --git a/flake/templates/python/flake.nix b/flake/templates/python/flake.nix new file mode 100644 index 000000000..47d3b2867 --- /dev/null +++ b/flake/templates/python/flake.nix @@ -0,0 +1,26 @@ +{ + description = "Python Project Template"; + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs"; + }; + + outputs = { + self, + nixpkgs, + }: let + systems = ["x86_64-linux" "aarch64-linux"]; + forEachSystem = nixpkgs.lib.genAttrs systems; + + pkgsForEach = nixpkgs.legacyPackages; + in rec { + packages = forEachSystem (system: { + default = pkgsForEach.${system}.callPackage ./default.nix {}; + }); + + devShells = forEachSystem (system: { + default = pkgsForEach.${system}.callPackage ./shell.nix {}; + }); + + hydraJobs = packages; + }; +} diff --git a/flake/templates/python/shell.nix b/flake/templates/python/shell.nix new file mode 100644 index 000000000..9fa8a1229 --- /dev/null +++ b/flake/templates/python/shell.nix @@ -0,0 +1,13 @@ +{ + callPackage, + mkShellNoCC, + python3, + ... +}: let + defaultPackage = callPackage ./default.nix; +in + mkShellNoCC { + packages = [ + (python3.withPackages defaultPackage.propagatedBuildInputs) + ]; + } diff --git a/flake/templates/rust/Cargo.toml b/flake/templates/rust/Cargo.toml new file mode 100644 index 000000000..c0a1285bd --- /dev/null +++ b/flake/templates/rust/Cargo.toml @@ -0,0 +1,5 @@ +[package] +name = "sample-rust" +version = "0.0.1" +license = "MIT" +edition = "2021" diff --git a/flake/templates/rust/default.nix b/flake/templates/rust/default.nix new file mode 100644 index 000000000..58798a6cc --- /dev/null +++ b/flake/templates/rust/default.nix @@ -0,0 +1,8 @@ +{rustPlatform}: +rustPlatform.buildRustPackage { + pname = "sample-rust"; + version = "0.0.1"; + + src = ./.; + cargoLock.lockFile = ./Cargo.lock; +} diff --git a/flake/templates/rust/flake.nix b/flake/templates/rust/flake.nix new file mode 100644 index 000000000..0b7a0ddf7 --- /dev/null +++ b/flake/templates/rust/flake.nix @@ -0,0 +1,26 @@ +{ + description = "Rust Project Template"; + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs"; + }; + + outputs = { + self, + nixpkgs, + }: let + systems = ["x86_64-linux" "aarch64-linux"]; + forEachSystem = nixpkgs.lib.genAttrs systems; + + pkgsForEach = nixpkgs.legacyPackages; + in rec { + packages = forEachSystem (system: { + default = pkgsForEach.${system}.callPackage ./default.nix {}; + }); + + devShells = forEachSystem (system: { + default = pkgsForEach.${system}.callPackage ./shell.nix {}; + }); + + hydraJobs = packages; + }; +} diff --git a/flake/templates/rust/shell.nix b/flake/templates/rust/shell.nix new file mode 100644 index 000000000..6b184ad26 --- /dev/null +++ b/flake/templates/rust/shell.nix @@ -0,0 +1,18 @@ +{ + callPackage, + rust-analyzer, + rustfmt, + clippy, +}: let + mainPkg = callPackage ./default.nix {}; +in + mainPkg.overrideAttrs (oa: { + nativeBuildInputs = + [ + # Additional rust tooling + rust-analyzer + rustfmt + clippy + ] + ++ (oa.nativeBuildInputs or []); + }) diff --git a/flake/templates/rust/src/main.rs b/flake/templates/rust/src/main.rs new file mode 100644 index 000000000..a30eb952c --- /dev/null +++ b/flake/templates/rust/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/home/default.nix b/home/default.nix index 8d1a3168b..b09ea046b 100644 --- a/home/default.nix +++ b/home/default.nix @@ -7,11 +7,9 @@ lib, ... }: let - inherit (config) modules; - env = modules.usrEnv; - defaults = config.modules.programs.default; + inherit (config.modules.programs) defaults; in { - home-manager = lib.mkIf env.useHomeManager { + home-manager = { verbose = true; useUserPackages = true; useGlobalPkgs = true; diff --git a/home/isabel/default.nix b/home/isabel/default.nix index 9f5d8e04e..6eddd07ca 100644 --- a/home/isabel/default.nix +++ b/home/isabel/default.nix @@ -1,6 +1,5 @@ { inputs, - config, lib, self, ... @@ -12,22 +11,15 @@ in { inputs.catppuccin.homeManagerModules.catppuccin self.homeManagerModules.gtklock - # important system level configurations + # important system enviroment config ./system - - # programs sets + # programs that are used, e.g. GUI apps ./programs - # system services, organized by display protocol ./services - - # declarative system and program themes (qt/gtk) + # Application themeing ./themes - - # dev shells - ./shells - - # other settings that can't be organized as easly + # Other data that can't be organized as easly ./misc ]; config = { @@ -43,7 +35,7 @@ in { }; manual = { - # the docs suck, so we disable them to save space + # I don't use docs, so just disable them html.enable = false; json.enable = false; manpages.enable = false; diff --git a/home/isabel/misc/pfps/avatar b/home/isabel/misc/pfps/avatar index fdddfe2d6..def5e2060 100644 Binary files a/home/isabel/misc/pfps/avatar and b/home/isabel/misc/pfps/avatar differ diff --git a/home/isabel/misc/pfps/avatar2 b/home/isabel/misc/pfps/avatar2 new file mode 100644 index 000000000..fdddfe2d6 Binary files /dev/null and b/home/isabel/misc/pfps/avatar2 differ diff --git a/home/isabel/programs/cli/confs/bat.nix b/home/isabel/programs/cli/confs/bat.nix index 4c18fab7c..5bd9457dc 100644 --- a/home/isabel/programs/cli/confs/bat.nix +++ b/home/isabel/programs/cli/confs/bat.nix @@ -2,14 +2,10 @@ osConfig, lib, ... -}: -with lib; let - programs = osConfig.modules.programs; - device = osConfig.modules.device; - +}: let acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; in { - config = mkIf ((builtins.elem device.type acceptedTypes) && (programs.cli.enable)) { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && lib.isModernShell osConfig) { programs.bat = { enable = true; catppuccin.enable = true; diff --git a/home/isabel/programs/cli/confs/default.nix b/home/isabel/programs/cli/confs/default.nix index 57e65fc11..0eef6963f 100644 --- a/home/isabel/programs/cli/confs/default.nix +++ b/home/isabel/programs/cli/confs/default.nix @@ -1,9 +1,7 @@ _: { imports = [ - ./fish - ./nushell - ./bat.nix + ./eza.nix ./git.nix ./nix-shell.nix ./starship.nix diff --git a/home/isabel/programs/cli/confs/eza.nix b/home/isabel/programs/cli/confs/eza.nix new file mode 100644 index 000000000..8fd34a61f --- /dev/null +++ b/home/isabel/programs/cli/confs/eza.nix @@ -0,0 +1,19 @@ +{ + osConfig, + lib, + ... +}: let + inherit (lib) mkIf isModernShell; +in { + config = mkIf (isModernShell osConfig) { + programs.eza = { + enable = true; + icons = true; + enableAliases = true; + extraOptions = [ + "--group-directories-first" + "--header" + ]; + }; + }; +} diff --git a/home/isabel/programs/cli/confs/fish/default.nix b/home/isabel/programs/cli/confs/fish/default.nix deleted file mode 100644 index ca70ad44f..000000000 --- a/home/isabel/programs/cli/confs/fish/default.nix +++ /dev/null @@ -1,59 +0,0 @@ -{osConfig, ...}: let - sys = osConfig.modules.system; - #symlink = fileName: {recursive ? false}: { - # source = config.lib.file.mkOutOfStoreSymlink "${sys.flakePath}/${fileName}"; - # inherit recursive; - #}; -in { - programs.fish = { - enable = true; - catppuccin.enable = true; - plugins = []; - functions = { - bj = "nohup $argv /dev/null &"; - "." = '' - set -l input $argv[1] - if echo $input | grep -q '^[1-9][0-9]*$' - set -l levels $input - for i in (seq $levels) - cd .. - end - else - echo "Invalid input format. Please use '' to go back a specific number of directories." - end - ''; - }; - shellAliases = { - # ls to exa - ls = "exa -al --color=always --icons --group-directories-first"; - la = "command exa -a --color=always --icons --group-directories-first"; - ll = "exa -abghHliS --icons --group-directories-first"; - lt = "exa -aT --color=always --icons --group-directories-first"; - - mkidr = "mkdir -pv"; # always create pearent directory - df = "df -h"; # human readblity - rs = "sudo reboot"; - sysctl = "sudo systemctl"; - doas = "doas --"; - jctl = "journalctl -p 3 -xb"; # get error messages from journalctl - lg = "lazygit"; - - # nix stuff - ssp = "~/shells/spawnshell.sh"; - rebuild = "sudo nixos-rebuild switch --flake ${sys.flakePath}#${sys.hostname}"; - nixclean = "sudo nix-collect-garbage --delete-older-than 3d && nix-collect-garbage -d"; - nixrepair = "nix-store --verify --check-contents --repair"; - }; - shellAbbrs = {}; - shellInit = '' - starship init fish | source - set -x MANPAGER "sh -c 'col -bx | bat -l man -p'" - set TERM "xterm-256color" - set fish_greeting - set TERMINAL "alacritty" - export "MICRO_TRUECOLOR=1" - export GPG_TTY=$(tty) - ''; - }; - #xdg.configFile."fish/conf.d" = symlink "home/${sys.username}/programs/cli/confs/fish/conf.d" {recursive = true;}; -} diff --git a/home/isabel/programs/cli/confs/git.nix b/home/isabel/programs/cli/confs/git.nix index 66be02234..afe8bb2f1 100644 --- a/home/isabel/programs/cli/confs/git.nix +++ b/home/isabel/programs/cli/confs/git.nix @@ -10,14 +10,14 @@ in { home.packages = with pkgs; [ gist # manage github gists act # local github actions - gitflow + gitflow # Extend git with the Gitflow branching model ]; programs = { # github cli gh = { enable = true; - gitCredentialHelper.enable = false; + gitCredentialHelper.enable = false; # i use sops for this anyways extensions = with pkgs; [ gh-cal # github activity stats in the CLI gh-dash # dashboard with pull requests and issues @@ -39,6 +39,7 @@ in { key = cfg.signingKey; signByDefault = true; }; + lfs.enable = true; ignores = [ "*.bak" "*.swp" @@ -56,7 +57,7 @@ in { "result-*" ]; extraConfig = { - init.defaultBranch = "main"; + init.defaultBranch = "main"; # warning the AUR hates this branch.autosetupmerge = "true"; pull.ff = "only"; @@ -99,21 +100,20 @@ in { "ssh://git@codeberg.org/".pushInsteadOf = "codeberg:"; }; }; - lfs.enable = true; + aliases = { + st = "status"; br = "branch"; c = "commit -m"; ca = "commit -am"; co = "checkout"; d = "diff"; df = "!git hist | peco | awk '{print $2}' | xargs -I {} git diff {}^ {}"; - edit-unmerged = "!f() { git ls-files --unmerged | cut -f2 | sort -u ; }; vim `f`"; fuck = "commit --amend -m"; graph = "log --all --decorate --graph"; ps = "!git push origin $(git rev-parse --abbrev-ref HEAD)"; pl = "!git pull origin $(git rev-parse --abbrev-ref HEAD)"; af = "!git add $(git ls-files -m -o --exclude-standard | fzf -m)"; - st = "status"; hist = '' log --pretty=format:"%Cgreen%h %Creset%cd %Cblue[%cn] %Creset%s%C(yellow)%d%C(reset)" --graph --date=relative --decorate --all ''; diff --git a/home/isabel/programs/cli/confs/nix-shell.nix b/home/isabel/programs/cli/confs/nix-shell.nix index 39928f6d2..0b3ce7dd2 100644 --- a/home/isabel/programs/cli/confs/nix-shell.nix +++ b/home/isabel/programs/cli/confs/nix-shell.nix @@ -3,34 +3,11 @@ lib, pkgs, ... -}: -with lib; let - programs = osConfig.modules.programs; - device = osConfig.modules.device; - - acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; -in { - config = mkIf ((builtins.elem device.type acceptedTypes) && (programs.cli.enable)) { - home = { - packages = with pkgs; [ - alejandra - deadnix - nix-index - nix-tree - statix - nil - ]; - - sessionVariables = { - DIRENV_LOG_FORMAT = ""; - }; - }; - - programs.direnv = { - enable = true; - nix-direnv = { - enable = true; - }; - }; +}: { + config = lib.mkIf osConfig.modules.programs.cli.enable { + home.packages = with pkgs; [ + alejandra + nix-tree + ]; }; } diff --git a/home/isabel/programs/cli/confs/nushell/config.nu b/home/isabel/programs/cli/confs/nushell/config.nu deleted file mode 100644 index 4a5d55d2a..000000000 --- a/home/isabel/programs/cli/confs/nushell/config.nu +++ /dev/null @@ -1,241 +0,0 @@ -let catppuccin = { - latte: { - rosewater: "#dc8a78" - flamingo: "#dd7878" - pink: "#ea76cb" - mauve: "#8839ef" - red: "#d20f39" - maroon: "#e64553" - peach: "#fe640b" - yellow: "#df8e1d" - green: "#40a02b" - teal: "#179299" - sky: "#04a5e5" - sapphire: "#209fb5" - blue: "#1e66f5" - lavender: "#7287fd" - text: "#4c4f69" - subtext1: "#5c5f77" - subtext0: "#6c6f85" - overlay2: "#7c7f93" - overlay1: "#8c8fa1" - overlay0: "#9ca0b0" - surface2: "#acb0be" - surface1: "#bcc0cc" - surface0: "#ccd0da" - crust: "#dce0e8" - mantle: "#e6e9ef" - base: "#eff1f5" - } - frappe: { - rosewater: "#f2d5cf" - flamingo: "#eebebe" - pink: "#f4b8e4" - mauve: "#ca9ee6" - red: "#e78284" - maroon: "#ea999c" - peach: "#ef9f76" - yellow: "#e5c890" - green: "#a6d189" - teal: "#81c8be" - sky: "#99d1db" - sapphire: "#85c1dc" - blue: "#8caaee" - lavender: "#babbf1" - text: "#c6d0f5" - subtext1: "#b5bfe2" - subtext0: "#a5adce" - overlay2: "#949cbb" - overlay1: "#838ba7" - overlay0: "#737994" - surface2: "#626880" - surface1: "#51576d" - surface0: "#414559" - base: "#303446" - mantle: "#292c3c" - crust: "#232634" - } - macchiato: { - rosewater: "#f4dbd6" - flamingo: "#f0c6c6" - pink: "#f5bde6" - mauve: "#c6a0f6" - red: "#ed8796" - maroon: "#ee99a0" - peach: "#f5a97f" - yellow: "#eed49f" - green: "#a6da95" - teal: "#8bd5ca" - sky: "#91d7e3" - sapphire: "#7dc4e4" - blue: "#8aadf4" - lavender: "#b7bdf8" - text: "#cad3f5" - subtext1: "#b8c0e0" - subtext0: "#a5adcb" - overlay2: "#939ab7" - overlay1: "#8087a2" - overlay0: "#6e738d" - surface2: "#5b6078" - surface1: "#494d64" - surface0: "#363a4f" - base: "#24273a" - mantle: "#1e2030" - crust: "#181926" - } - mocha: { - rosewater: "#f5e0dc" - flamingo: "#f2cdcd" - pink: "#f5c2e7" - mauve: "#cba6f7" - red: "#f38ba8" - maroon: "#eba0ac" - peach: "#fab387" - yellow: "#f9e2af" - green: "#a6e3a1" - teal: "#94e2d5" - sky: "#89dceb" - sapphire: "#74c7ec" - blue: "#89b4fa" - lavender: "#b4befe" - text: "#cdd6f4" - subtext1: "#bac2de" - subtext0: "#a6adc8" - overlay2: "#9399b2" - overlay1: "#7f849c" - overlay0: "#6c7086" - surface2: "#585b70" - surface1: "#45475a" - surface0: "#313244" - base: "#1e1e2e" - mantle: "#181825" - crust: "#11111b" - } -} - -let stheme = $catppuccin.mocha - -let theme = { - separator: $stheme.overlay0 - leading_trailing_space_bg: $stheme.overlay0 - header: $stheme.green - date: $stheme.mauve - filesize: $stheme.blue - row_index: $stheme.pink - bool: $stheme.peach - int: $stheme.peach - duration: $stheme.peach - range: $stheme.peach - float: $stheme.peach - string: $stheme.green - nothing: $stheme.peach - binary: $stheme.peach - cellpath: $stheme.peach - hints: dark_gray - - shape_garbage: { fg: $stheme.crust bg: $stheme.red attr: b } - shape_bool: $stheme.blue - shape_int: { fg: $stheme.mauve attr: b} - shape_float: { fg: $stheme.mauve attr: b} - shape_range: { fg: $stheme.yellow attr: b} - shape_internalcall: { fg: $stheme.blue attr: b} - shape_external: { fg: $stheme.blue attr: b} - shape_externalarg: $stheme.text - shape_literal: $stheme.blue - shape_operator: $stheme.yellow - shape_signature: { fg: $stheme.green attr: b} - shape_string: $stheme.green - shape_filepath: $stheme.yellow - shape_globpattern: { fg: $stheme.blue attr: b} - shape_variable: $stheme.text - shape_flag: { fg: $stheme.blue attr: b} - shape_custom: {attr: b} -} - -let-env config = { - show_banner: false - cursor_shape: { - vi_normal: block - vi_insert: line - } - edit_mode: vi - render_right_prompt_on_last_line: true - rm: { - always_trash: true - } - color_config: $theme - keybindings: [ - { - name: completion_menu - modifier: none - keycode: tab - mode: [emacs vi_normal vi_insert] - event: { - until: [ - { send: menu name: completion_menu } - { send: menunext } - ] - } - } - { - name: completion_previous - modifier: shift - keycode: backtab - mode: [emacs, vi_normal, vi_insert] # Note: You can add the same keybinding to all modes by using a list - event: { send: menuprevious } - } - { - name: jump_to_start - keycode: char_h - modifier: shift - mode: [vi_normal] - event: { edit: MoveToLineStart } - } - { - name: jump_to_end - modifier: shift - keycode: char_l - mode: [vi_normal] - event: { edit: MoveToLineEnd } - } - ] - completions: { - algorithm: "fuzzy" - } - hooks: { - pre_prompt: [{ || - let direnv = (direnv export json | from json) - let direnv = if ($direnv | length) == 1 { $direnv } else { {} } - $direnv | load-env - }] - pre_execution: [{ || }] - } -} - -let-env PROMPT_INDICATOR_VI_INSERT = "I " -let-env PROMPT_INDICATOR_VI_NORMAL = "N " - -# Aliases -# ls to exa -#alias ls = exa -al --color=always --icons --group-directories-first -#alias la = exa -a --color=always --icons --group-directories-firt -#alias ll = exa -abghHliS --icons --group-directories-first -#alias lt = exa -aT --color=always --icons --group-directories-first - -alias df = df -h # human readblity -alias rs = sudo reboot -alias sysctl = sudo systemctl -alias doas = doas -- -alias jctl = journalctl -p 3 -xb # get error messages from journalctl -alias lg = lazygit -alias ssp = ~/shells/spawnshell.sh - -use "~/.config/nushell/scripts/custom-completions/nix/nix-completions.nu" * -use "~/.config/nushell/scripts/custom-completions/git/git-completions.nu" * -use "~/.config/nushell/scripts/custom-completions/npm/npm-completions.nu" * -use "~/.config/nushell/scripts/custom-completions/just/just-completions.nu" * -use "~/.config/nushell/scripts/custom-completions/tealdeer/tldr-completions.nu" * -use "~/.config/nushell/scripts/custom-completions/btm/btm-completions.nu" * -use "~/.config/nushell/scripts/custom-completions/make/make-completions.nu" * - -source ~/.cache/starship/init.nu diff --git a/home/isabel/programs/cli/confs/nushell/default.nix b/home/isabel/programs/cli/confs/nushell/default.nix deleted file mode 100644 index e4f12d723..000000000 --- a/home/isabel/programs/cli/confs/nushell/default.nix +++ /dev/null @@ -1,48 +0,0 @@ -{ - config, - lib, - pkgs, - inputs, - osConfig, - ... -}: let - inherit (lib) mkIf; - programs = osConfig.modules.programs; - flakePath = osConfig.modules.system.flakePath; -in { - config = mkIf (programs.cli.enable) { - programs.nushell = { - enable = true; - package = pkgs.nushell; - }; - - home.file = { - "${config.xdg.configHome}/nushell/config.nu" = lib.mkForce { - source = config.lib.file.mkOutOfStoreSymlink "${flakePath}/home/isabel/packages/cli/confs/nushell/config.nu"; - }; - "${config.xdg.configHome}/nushell/env.nu" = lib.mkForce { - source = config.lib.file.mkOutOfStoreSymlink "${flakePath}/home/isabel/packages/cli/confs/nushell/env.nu"; - }; - "${config.xdg.configHome}/nushell/history.txt" = { - source = config.lib.file.mkOutOfStoreSymlink "${config.xdg.dataHome}/history"; - }; - "${config.xdg.configHome}/nushell/env-nix.nu" = with lib; let - environmentVariables = { - EDITOR = "nvim"; - GIT_EDITOR = "nvim"; - VISUAL = "code"; - TERMINAL = "alacritty"; - }; - in { - text = '' - ${concatStringsSep "\n" - (mapAttrsToList (k: v: "let-env ${k} = ${v}") - environmentVariables)} - ''; - }; - "${config.xdg.configHome}/nushell/scripts" = { - source = inputs.nu_scripts; - }; - }; - }; -} diff --git a/home/isabel/programs/cli/confs/nushell/env.nu b/home/isabel/programs/cli/confs/nushell/env.nu deleted file mode 100644 index 6fd23a9b1..000000000 --- a/home/isabel/programs/cli/confs/nushell/env.nu +++ /dev/null @@ -1,44 +0,0 @@ -mkdir ~/.cache/starship -starship init nu | str replace "term size -c" "term size" | save -f ~/.cache/starship/init.nu - -let-env SSH_AGENT_TIMEOUT = 300 -mkdir ~/.cache/ssh-agent/ - -if ("~/.cache/ssh-agent/agent" | path exists) { - let ssh_env = (open ~/.cache/ssh-agent/agent | from json) - - let nc = (do { ^nc -zU $ssh_env.SSH_AUTH_SOCK } | complete) - let sock_exit = $nc.exit_code - - if ($sock_exit == 0) { - $ssh_env | load-env - } else { - print "Starting new ssh agent" - - let ssh_env = (ssh-agent -c -t $env.SSH_AGENT_TIMEOUT - | lines - | first 2 - | parse "setenv {name} {value};" - | transpose -i -r -d) - - $ssh_env | to json | save -f ~/.cache/ssh-agent/agent - $ssh_env | load-env - } -} else { - print "Starting ssh agent" - - let ssh_env = (ssh-agent -c -t $env.SSH_AGENT_TIMEOUT - | lines - | first 2 - | parse "setenv {name} {value};" - | transpose -i -r -d) - - $ssh_env | to json | save ~/.cache/ssh-agent/agent - $ssh_env | load-env -} - -if ("~/.ssh/github" | path exists ) { - do { ssh-add ~/.ssh/github } out> /dev/null -} - -source ~/.config/nushell/env-nix.nu diff --git a/home/isabel/programs/cli/confs/starship.nix b/home/isabel/programs/cli/confs/starship.nix index 980ba5173..b7aff576c 100644 --- a/home/isabel/programs/cli/confs/starship.nix +++ b/home/isabel/programs/cli/confs/starship.nix @@ -2,146 +2,139 @@ osConfig, lib, ... -}: -with lib; let - programs = osConfig.modules.programs; - device = osConfig.modules.device; - - acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; -in { - config = mkIf ((builtins.elem device.type acceptedTypes) && (programs.cli.enable)) { - programs.starship = { - enable = true; - catppuccin.enable = true; - settings = { - add_newline = true; - format = lib.strings.concatStrings [ - "[╭╴](238)$os" - "$all[╰─󰁔](237)$character" - ]; - character = { - success_symbol = ""; - error_symbol = ""; - }; - container = { - symbol = " 󰏖"; - format = "[$symbol ](yellow dimmed)"; - }; - username = { - style_user = "white"; - style_root = "black"; - format = "[$user]($style) "; - show_always = true; - }; - directory = { - truncation_length = 3; - truncation_symbol = "…/"; - home_symbol = "󰋞 ~"; - read_only_style = "197"; - read_only = "  "; - format = "at [$path]($style)[$read_only]($read_only_style) "; - }; - directory.substitutions = { - "documents" = " "; - "downloads" = " "; - "media/music" = " "; - "media/pictures" = " "; - "media/videos" = " "; - "dev" = "󱌢 "; - "skl" = "󰑴 "; - ".setup" = " "; - }; - os = { - disabled = true; - style = "bold white"; - format = "[$symbol]($style)"; - }; - os.symbols = { - Arch = ""; - Artix = ""; - Debian = ""; - # Kali = "󰠥"; - EndeavourOS = ""; - Fedora = ""; - NixOS = ""; - openSUSE = ""; - SUSE = ""; - Ubuntu = ""; - Raspbian = ""; - #elementary = ""; - #Coreos = ""; - Gentoo = ""; - #mageia = "" - CentOS = ""; - #sabayon = ""; - #slackware = ""; - Mint = ""; - Alpine = ""; - #aosc = ""; - #devuan = ""; - Manjaro = ""; - #rhel = ""; - Macos = "󰀵"; - Linux = ""; - Windows = ""; - }; - python = { - symbol = ""; - format = "[$symbol ](yellow)"; - }; - nodejs = { - symbol = " "; - format = "[$symbol ](yellow)"; - }; - lua = { - symbol = "󰢱"; - format = "[$symbol ](blue)"; - }; - rust = { - symbol = ""; - format = "[$symbol ](red)"; - }; - docker_context = { - symbol = ""; - format = "[$symbol ](blue)"; - }; - java = { - symbol = ""; - format = "[$symbol ](red)"; - }; - c = { - symbol = ""; - format = "[$symbol ](blue)"; - }; - golang = { - symbol = ""; - format = "[$symbol ](blue)"; - }; - battery = { - disabled = true; - }; - git_branch = { - symbol = "󰊢 "; - format = "on [$symbol$branch]($style) "; - truncation_length = 4; - truncation_symbol = "…/"; - style = "bold green"; - }; - git_status = { - format = "[($all_status$ahead_behind)]($style) "; - style = "bold green"; - conflicted = "🏳"; - up_to_date = " "; - untracked = " "; - ahead = "⇡$count"; - diverged = "⇕⇡$ahead_count⇣$behind_count"; - behind = "⇣$count"; - stashed = "󰏗 "; - modified = " "; - staged = "[++($count)](green)"; - renamed = "󰖷 "; - deleted = " "; - }; +}: { + programs.starship = { + inherit (osConfig.modules.programs.cli) enable; + catppuccin.enable = true; + settings = { + add_newline = true; + format = lib.strings.concatStrings [ + "[╭╴](238)$os" + "$all[╰─󰁔](237)$character" + ]; + character = { + success_symbol = ""; + error_symbol = ""; + }; + container = { + symbol = " 󰏖"; + format = "[$symbol ](yellow dimmed)"; + }; + username = { + style_user = "white"; + style_root = "black"; + format = "[$user]($style) "; + show_always = true; + }; + directory = { + truncation_length = 3; + truncation_symbol = "…/"; + home_symbol = "󰋞 ~"; + read_only_style = "197"; + read_only = "  "; + format = "at [$path]($style)[$read_only]($read_only_style) "; + }; + directory.substitutions = { + "documents" = " "; + "downloads" = " "; + "media/music" = " "; + "media/pictures" = " "; + "media/videos" = " "; + "dev" = "󱌢 "; + "skl" = "󰑴 "; + ".config" = " "; + }; + os = { + disabled = true; + style = "bold white"; + format = "[$symbol]($style)"; + }; + # If it is commented out it does not exist yet + os.symbols = { + Arch = ""; + Artix = ""; + Debian = ""; + # Kali = "󰠥"; + EndeavourOS = ""; + Fedora = ""; + NixOS = ""; + openSUSE = ""; + SUSE = ""; + Ubuntu = ""; + Raspbian = ""; + #elementary = ""; + #Coreos = ""; + Gentoo = ""; + #mageia = "" + CentOS = ""; + #sabayon = ""; + #slackware = ""; + Mint = ""; + Alpine = ""; + #aosc = ""; + #devuan = ""; + Manjaro = ""; + #rhel = ""; + Macos = "󰀵"; + Linux = ""; + Windows = ""; + }; + python = { + symbol = ""; + format = "[$symbol ](yellow)"; + }; + nodejs = { + symbol = " "; + format = "[$symbol ](yellow)"; + }; + lua = { + symbol = "󰢱"; + format = "[$symbol ](blue)"; + }; + rust = { + symbol = ""; + format = "[$symbol ](red)"; + }; + docker_context = { + symbol = ""; + format = "[$symbol ](blue)"; + }; + java = { + symbol = ""; + format = "[$symbol ](red)"; + }; + c = { + symbol = ""; + format = "[$symbol ](blue)"; + }; + golang = { + symbol = ""; + format = "[$symbol ](blue)"; + }; + battery = { + disabled = true; + }; + git_branch = { + symbol = "󰊢 "; + format = "on [$symbol$branch]($style) "; + truncation_length = 4; + truncation_symbol = "…/"; + style = "bold green"; + }; + git_status = { + format = "[($all_status$ahead_behind)]($style) "; + style = "bold green"; + conflicted = "🏳"; + up_to_date = " "; + untracked = " "; + ahead = "⇡$count"; + diverged = "⇕⇡$ahead_count⇣$behind_count"; + behind = "⇣$count"; + stashed = "󰏗 "; + modified = " "; + staged = "[++($count)](green)"; + renamed = "󰖷 "; + deleted = " "; }; }; }; diff --git a/home/isabel/programs/cli/confs/tealdear.nix b/home/isabel/programs/cli/confs/tealdear.nix index f0ab9b8cd..36e5358c5 100644 --- a/home/isabel/programs/cli/confs/tealdear.nix +++ b/home/isabel/programs/cli/confs/tealdear.nix @@ -2,14 +2,10 @@ osConfig, lib, ... -}: -with lib; let - programs = osConfig.modules.programs; - device = osConfig.modules.device; - +}: let acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; in { - config = mkIf ((builtins.elem device.type acceptedTypes) && (programs.cli.enable)) { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && lib.isModernShell osConfig) { programs.tealdeer = { enable = true; settings = { diff --git a/home/isabel/programs/cli/default.nix b/home/isabel/programs/cli/default.nix index a8cec92d1..42a903758 100644 --- a/home/isabel/programs/cli/default.nix +++ b/home/isabel/programs/cli/default.nix @@ -2,7 +2,6 @@ _: { imports = [ ./confs - ./scripts ./shared.nix ./desktop.nix ./wayland.nix diff --git a/home/isabel/programs/cli/desktop.nix b/home/isabel/programs/cli/desktop.nix index 243309c58..2ac5229dd 100644 --- a/home/isabel/programs/cli/desktop.nix +++ b/home/isabel/programs/cli/desktop.nix @@ -3,21 +3,16 @@ lib, pkgs, ... -}: -with lib; let - programs = osConfig.modules.programs; - device = osConfig.modules.device; - +}: let + inherit (lib) mkIf isAcceptedDevice; acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; in { - config = mkIf ((builtins.elem device.type acceptedTypes) && (programs.cli.enable)) { + config = mkIf ((isAcceptedDevice osConfig acceptedTypes) && osConfig.modules.programs.cli.enable) { home.packages = with pkgs; [ - # CLI - libnotify - imagemagick - bitwarden-cli - trash-cli - brightnessctl + libnotify # needed for some notifcations + bitwarden-cli # bitwarden, my chosen package manager + trash-cli # `rm` skips the "rubish bin", this cli tool uses that + brightnessctl # brightness managed via cli ]; }; } diff --git a/home/isabel/programs/cli/scripts/extract.nix b/home/isabel/programs/cli/scripts/extract.nix deleted file mode 100644 index 8d4156c92..000000000 --- a/home/isabel/programs/cli/scripts/extract.nix +++ /dev/null @@ -1,48 +0,0 @@ -_: '' - SAVEIFS=$IFS - IFS="$(printf '\n\t')" - - function extract { - if [ $# -eq 0 ]; then - # display usage if no parameters given - echo "Usage: extract ." - echo " extract [path/file_name_2.ext] [path/file_name_3.ext]" - fi - for n in "$@"; do - if [ ! -f "$n" ]; then - echo "'$n' - file doesn't exist" - return 1 - fi - - case "''${n%,}" in - *.cbt|*.tar.bz2|*.tar.gz|*.tar.xz|*.tbz2|*.tgz|*.txz|*.tar) - tar zxvf "$n" ;; - *.lzma) unlzma ./"$n" ;; - *.bz2) bunzip2 ./"$n" ;; - *.cbr|*.rar) unrar x -ad ./"$n" ;; - *.gz) gunzip ./"$n" ;; - *.cbz|*.epub|*.zip) unzip ./"$n" ;; - *.z) uncompress ./"$n" ;; - *.7z|*.apk|*.arj|*.cab|*.cb7|*.chm|*.deb|*.iso|*.lzh|*.msi|*.pkg|*.rpm|*.udf|*.wim|*.xar|*.vhd) - 7z x ./"$n" ;; - *.xz) unxz ./"$n" ;; - *.exe) cabextract ./"$n" ;; - *.cpio) cpio -id < ./"$n" ;; - *.cba|*.ace) unace x ./"$n" ;; - *.zpaq) zpaq x ./"$n" ;; - *.arc) arc e ./"$n" ;; - *.cso) ciso 0 ./"$n" ./"$n.iso" && \ - extract "$n.iso" && \rm -f "$n" ;; - *.zlib) zlib-flate -uncompress < ./"$n" > ./"$n.tmp" && \ - mv ./"$n.tmp" ./"''${n%.*zlib}" && rm -f "$n" ;; - *.dmg) - hdiutil mount ./"$n" -mountpoint "./$n.mounted" ;; - *) - echo "extract: '$n' - unknown archive method" - return 1 - ;; - esac - done - } - - IFS=$SAVEIFS'' diff --git a/home/isabel/programs/cli/shared.nix b/home/isabel/programs/cli/shared.nix index 3064a3457..7c7229a14 100644 --- a/home/isabel/programs/cli/shared.nix +++ b/home/isabel/programs/cli/shared.nix @@ -2,27 +2,31 @@ osConfig, lib, pkgs, + inputs', + self', ... -}: -with lib; let - programs = osConfig.modules.programs; +}: let + inherit (lib) mkIf optionals; + cfg = osConfig.modules.programs; in { - config = mkIf (programs.cli.enable) { + config = mkIf cfg.cli.enable { home.packages = with pkgs; [ # CLI packages from nixpkgs unzip - ripgrep rsync fd jq dconf nitch - exa + hyfetch + cached-nix-shell + self'.packages.bellado + self'.packages.catppuccinifier-cli ] - ++ optionals (programs.nur.enable && programs.nur.bella) [ - nur.repos.bella.bellado - nur.repos.bella.catppuccinifier-cli + ++ optionals cfg.cli.modernShell.enable [ + ripgrep + inputs'.catppuccin-toolbox.packages.catwalk ]; }; } diff --git a/home/isabel/programs/cli/wayland.nix b/home/isabel/programs/cli/wayland.nix index d6ae0d9be..3ed5c8c97 100644 --- a/home/isabel/programs/cli/wayland.nix +++ b/home/isabel/programs/cli/wayland.nix @@ -3,14 +3,10 @@ lib, pkgs, ... -}: -with lib; let - device = osConfig.modules.device; - env = osConfig.modules.usrEnv; - sys = osConfig.modules.system; +}: let acceptedTypes = ["laptop" "desktop" "hybrid" "lite"]; in { - config = mkIf ((builtins.elem device.type acceptedTypes) && (env.isWayland && sys.video.enable)) { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && (lib.isWayland osConfig) && osConfig.modules.programs.cli.enable) { home.packages = with pkgs; [ grim slurp diff --git a/home/isabel/programs/default.nix b/home/isabel/programs/default.nix index 0f734b4bd..3c9d1ad8a 100644 --- a/home/isabel/programs/default.nix +++ b/home/isabel/programs/default.nix @@ -1,9 +1,12 @@ _: { imports = [ - ./gui + ./cli # command line applications ./editors # not all editors are GUI so they don't fit into the current catagories - ./cli - ./tui - ./wm + ./gui # graphical applications + ./scripts # useful shell scrips + ./shells # shell configurations + ./tui # terminal interface applications + ./wm # window managers + # TODO DE's ]; } diff --git a/home/isabel/programs/editors/default.nix b/home/isabel/programs/editors/default.nix index 5b7050db0..5a5978923 100644 --- a/home/isabel/programs/editors/default.nix +++ b/home/isabel/programs/editors/default.nix @@ -1,7 +1,10 @@ -_: { +{pkgs, ...}: { imports = [ ./micro - ./nvim + ./nvim # https://github.com/NotAShelf/neovim-flake/ ./vscode ]; + config.home.packages = with pkgs; [ + arduino # need this one for uni + ]; } diff --git a/home/isabel/programs/editors/micro/default.nix b/home/isabel/programs/editors/micro/default.nix index bb073a960..45707721f 100644 --- a/home/isabel/programs/editors/micro/default.nix +++ b/home/isabel/programs/editors/micro/default.nix @@ -3,10 +3,8 @@ config, defaults, ... -}: let - inherit (lib) mkIf; -in { - config = mkIf (defaults.editor == "micro") { +}: { + config = lib.mkIf (defaults.editor == "micro") { programs.micro = { enable = true; catppuccin.enable = true; diff --git a/home/isabel/programs/editors/nvim/default.nix b/home/isabel/programs/editors/nvim/default.nix index 36168c88c..9061f7005 100644 --- a/home/isabel/programs/editors/nvim/default.nix +++ b/home/isabel/programs/editors/nvim/default.nix @@ -1,90 +1,412 @@ { - pkgs, - lib, - config, inputs, - defaults, + pkgs, ... -}: let - inherit (lib) mkIf; -in { - config = mkIf (defaults.editor == "nvim") { - home.file."${config.xdg.configHome}/nvim" = { - source = inputs.isabel-nvim; - }; +}: { + imports = [inputs.neovim-flake.homeManagerModules.default]; - programs.neovim = { - enable = true; - package = pkgs.symlinkJoin { - name = "neovim"; - paths = [pkgs.neovim-unwrapped]; - buildInputs = [pkgs.makeWrapper pkgs.gcc]; - postBuild = "wrapProgram $out/bin/nvim --prefix CC : ${pkgs.lib.getExe pkgs.gcc}"; - }; + # https://notashelf.github.io/neovim-flake/ + programs.neovim-flake = { + enable = true; + settings.vim = { + package = pkgs.neovim-unwrapped; + viAlias = true; vimAlias = true; - viAlias = false; - vimdiffAlias = false; - withRuby = false; - withNodeJs = false; - withPython3 = false; - extraPackages = with pkgs; [ - # external deps - fd - ripgrep - lazygit - - texlab # latex LSP - nil # nix language server - alejandra # nix formatter - shellcheck - - #rust - cargo - rust-analyzer - rustc - rustfmt - - # web dev - nodePackages.alex - - # python - nodePackages.pyright - - # lua - stylua - lua-language-server - ]; - plugins = with pkgs.vimPlugins; [ - (nvim-treesitter.withPlugins (plugins: - with plugins; [ - tree-sitter-python - tree-sitter-c - tree-sitter-nix - tree-sitter-cpp - tree-sitter-rust - tree-sitter-toml - tree-sitter-json - tree-sitter-lua - tree-sitter-go - tree-sitter-java - tree-sitter-typescript - tree-sitter-javascript - tree-sitter-cmake - tree-sitter-comment - tree-sitter-http - tree-sitter-regex - tree-sitter-make - tree-sitter-html - tree-sitter-css - tree-sitter-latex - tree-sitter-bibtex - tree-sitter-php - tree-sitter-sql - tree-sitter-zig - tree-sitter-dockerfile - tree-sitter-markdown - ])) + + enableEditorconfig = true; + preventJunkFiles = true; + enableLuaLoader = true; + useSystemClipboard = true; + + treesitter.grammars = with pkgs.vimPlugins.nvim-treesitter.builtGrammars; [ + regex + markdown + markdown-inline ]; + + extraPlugins = let + inherit (pkgs.vimPlugins) friendly-snippets aerial-nvim nvim-surround undotree harpoon; + in { + friendly-snippets = {package = friendly-snippets;}; + + aerial = { + package = aerial-nvim; + setup = "require('aerial').setup {}"; + }; + + harpoon = { + package = harpoon; + setup = "require('harpoon').setup {}"; + after = ["aerial"]; + }; + + nvim-surround = { + package = nvim-surround; + setup = "require('nvim-surround').setup {}"; + }; + + undotree = { + package = undotree; + setup = '' + vim.g.undotree_ShortIndicators = true + vim.g.undotree_TreeVertShape = '│' + ''; + }; + }; + + spellChecking.enable = true; + + languages = { + enableLSP = true; + enableFormat = true; + enableTreesitter = true; + enableExtraDiagnostics = true; + + nix.enable = true; + html.enable = true; + markdown.enable = true; + sql.enable = false; + ts.enable = true; + go.enable = false; + python.enable = false; + zig.enable = false; + dart.enable = false; + elixir.enable = false; + svelte.enable = false; + php.enable = false; + + lua = { + enable = false; + lsp.neodev.enable = false; + }; + + rust = { + enable = true; + crates.enable = true; + }; + + clang = { + enable = false; + lsp = { + enable = true; + server = "clangd"; + }; + }; + }; + + lsp = { + formatOnSave = true; + lspkind.enable = true; + lsplines.enable = true; + lightbulb.enable = true; + lspsaga.enable = false; + lspSignature.enable = true; + nvimCodeActionMenu.enable = true; + trouble.enable = false; + # nvim-docs-view.enable = true; + }; + + debugMode = { + enable = false; + logFile = "/tmp/nvim.log"; + }; + + debugger.nvim-dap = { + enable = true; + ui.enable = true; + }; + + visuals = { + enable = true; + nvimWebDevicons.enable = true; + scrollBar.enable = false; + smoothScroll.enable = true; + cellularAutomaton.enable = false; + fidget-nvim.enable = true; + + indentBlankline = { + enable = true; + fillChar = null; + eolChar = null; + showCurrContext = true; + }; + + cursorline = { + enable = true; + lineTimeout = 0; + }; + }; + + statusline = { + lualine = { + enable = true; + theme = "catppuccin"; + }; + }; + + theme = { + enable = true; + name = "catppuccin"; + style = "mocha"; + transparent = true; + }; + + autopairs.enable = true; + + autocomplete = { + enable = true; + type = "nvim-cmp"; + + mappings = { + confirm = ""; + next = ""; + previous = ""; + }; + }; + + filetree = { + nvimTree = { + enable = true; + openOnSetup = true; + disableNetrw = true; + + hijackUnnamedBufferWhenOpening = true; + hijackCursor = true; + hijackDirectories = { + enable = true; + autoOpen = true; + }; + + git = { + enable = true; + showOnDirs = false; + timeout = 100; + }; + + view = { + preserveWindowProportions = false; + cursorline = false; + width = 35; + }; + + renderer = { + indentMarkers.enable = true; + rootFolderLabel = false; + + icons = { + modifiedPlacement = "after"; + gitPlacement = "after"; + show.git = true; + show.modified = true; + }; + }; + + filters = { + dotfiles = true; + gitIgnored = true; + }; + + diagnostics.enable = true; + + modified = { + enable = true; + showOnDirs = false; + showOnOpenDirs = true; + }; + + mappings = { + toggle = "e"; + refresh = "er"; + findFile = "ef"; + focus = "et"; + }; + }; + }; + + tabline = { + nvimBufferline.enable = true; + }; + + treesitter = { + fold = true; + context.enable = true; + }; + + binds = { + whichKey.enable = true; + cheatsheet.enable = false; + }; + + telescope = { + enable = true; + + mappings = { + findFiles = ""; + liveGrep = "fs"; + treesitter = "ffs"; + + gitCommits = "fgc"; + gitBufferCommits = "fgbc"; + gitBranches = "fgb"; + gitStatus = "fgs"; + gitStash = " fgx"; + }; + }; + + git = { + enable = true; + gitsigns.enable = true; + gitsigns.codeActions = false; + }; + + minimap = { + minimap-vim.enable = false; + codewindow.enable = false; + }; + + dashboard = { + dashboard-nvim.enable = false; + alpha.enable = false; + startify.enable = false; + }; + + notify = { + nvim-notify.enable = true; + }; + + projects = { + project-nvim = { + enable = true; + manualMode = false; + detectionMethods = ["lsp" "pattern"]; + }; + }; + + utility = { + ccc.enable = false; # color picker + icon-picker.enable = true; + diffview-nvim.enable = true; + surround.enable = true; # quick delimters altering + + # TODO wakatime + + motion = { + hop.enable = true; + leap.enable = false; + }; + }; + + notes = { + todo-comments = { + enable = true; + + mappings = { + quickFix = "tdf"; + telescope = "tds"; + }; + }; + + obsidian = { + enable = true; + dir = "~/documents/obsidian"; + completion.nvim_cmp = true; + }; + }; + + terminal = { + toggleterm = { + mappings.open = ""; + enable = true; + direction = "tab"; + lazygit = { + enable = true; + direction = "tab"; + }; + }; + }; + + ui = { + noice.enable = true; + colorizer.enable = true; + illuminate.enable = true; + + breadcrumbs = { + enable = true; + source = "nvim-navic"; + navbuddy.enable = false; + }; + + smartcolumn = { + enable = true; + columnAt.languages = { + markdown = 80; + nix = 150; + ruby = 110; + java = 120; + go = [130]; + }; + }; + + borders = { + enable = true; + globalStyle = "rounded"; + }; + }; + + assistant = { + copilot = { + enable = true; + cmp.enable = true; + }; + }; + + session = { + nvim-session-manager = { + enable = true; + + mappings = { + deleteSession = "sd"; + loadLastSession = "slt"; + loadSession = "sl"; + saveCurrentSession = "ss"; + }; + }; + }; + + gestures = { + gesture-nvim.enable = false; + }; + + comments = { + comment-nvim.enable = true; + }; + + presence = { + presence-nvim.enable = false; + }; + + maps.normal = { + "qq" = { + action = "qall!"; + silent = true; + desc = "Quit all"; + }; + "" = { + action = ":w"; + silent = true; + desc = "Save"; + }; + "es" = { + action = '' + function () + nvim-tree-api.tree.toggle_hidden_filter() + nvim-tree-api.tree.toggle_gitignore_filter() + end) + ''; + silent = true; + desc = "Show hidden files"; + }; + }; }; }; } diff --git a/home/isabel/programs/editors/vscode/default.nix b/home/isabel/programs/editors/vscode/default.nix index b1e58c2a3..fd59301cb 100644 --- a/home/isabel/programs/editors/vscode/default.nix +++ b/home/isabel/programs/editors/vscode/default.nix @@ -2,33 +2,70 @@ lib, pkgs, osConfig, + config, ... }: let - inherit (lib) mkIf; - inherit (osConfig.modules) device programs; - sys = osConfig.modules.system; acceptedTypes = ["laptop" "desktop" "hybrid"]; + inherit (osConfig.modules.system) flakePath mainUser; in { - config = mkIf (builtins.elem device.type acceptedTypes && programs.gui.enable && sys.video.enable) { - programs.vscode = { - enable = true; - package = pkgs.vscodium; - extensions = with pkgs.vscode-extensions; [ - bradlc.vscode-tailwindcss - catppuccin.catppuccin-vsc-icons - catppuccin.catppuccin-vsc - eamodio.gitlens - github.copilot - github.vscode-pull-request-github - jnoortheen.nix-ide - kamadorueda.alejandra - rust-lang.rust-analyzer - devsense.phptools-vscode - shd101wyy.markdown-preview-enhanced - ms-vscode-remote.remote-ssh - ms-vscode.live-server - ]; - mutableExtensionsDir = true; - }; + programs.vscode = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && osConfig.modules.programs.gui.enable) { + enable = true; + package = pkgs.vscodium; + extensions = with pkgs.vscode-extensions; [ + # THEMEING + catppuccin.catppuccin-vsc-icons + catppuccin.catppuccin-vsc + + # GIT + github.copilot + github.copilot-chat + github.vscode-pull-request-github + github.vscode-github-actions + eamodio.gitlens + + # UTILITIES + ms-vscode-remote.remote-ssh + ms-vscode.live-server + vscodevim.vim #yes i hate myself + + # LANGUAGES BASED EXTENSIONS + ## NIX + jnoortheen.nix-ide + kamadorueda.alejandra + mkhl.direnv + + ## RUST + serayuzgur.crates + rust-lang.rust-analyzer + + ## GO + golang.go + + ## LUA + sumneko.lua + + ## TOML + tamasfe.even-better-toml + + ## WEB DEV + ### GENERAL + bradlc.vscode-tailwindcss + dbaeumer.vscode-eslint + denoland.vscode-deno + + ### PHP + devsense.phptools-vscode + + ### MARKDOWN + shd101wyy.markdown-preview-enhanced + unifiedjs.vscode-mdx + valentjn.vscode-ltex + ]; + mutableExtensionsDir = true; + }; + + xdg.configFile = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && osConfig.modules.programs.gui.enable) { + "VSCodium/User/keybindings.json".source = config.lib.file.mkOutOfStoreSymlink "${flakePath}/home/${mainUser}/programs/editors/vscode/keybindings.json"; + "VSCodium/User/settings.json".source = config.lib.file.mkOutOfStoreSymlink "${flakePath}/home/${mainUser}/programs/editors/vscode/settings.json"; }; } diff --git a/home/isabel/programs/editors/vscode/keybindings.json b/home/isabel/programs/editors/vscode/keybindings.json new file mode 100644 index 000000000..56c50500b --- /dev/null +++ b/home/isabel/programs/editors/vscode/keybindings.json @@ -0,0 +1,16 @@ +[ + { + "key": "ctrl+alt+up", + "command": "-editor.action.copyLinesUpAction", + "when": "editorTextFocus" + }, + { + "key": "ctrl+alt+down", + "command": "-editor.action.copyLinesDownAction", + "when": "editorTextFocus" + }, + { + "key": "ctrl+m", + "command": "-editor.action.toggleTabFocusMode" + } +] diff --git a/home/isabel/programs/editors/vscode/settings.json b/home/isabel/programs/editors/vscode/settings.json new file mode 100644 index 000000000..7e49a2c3e --- /dev/null +++ b/home/isabel/programs/editors/vscode/settings.json @@ -0,0 +1,47 @@ +{ + "workbench.preferredLightColorTheme": "Catppuccin Mocha", + "security.workspace.trust.untrustedFiles": "open", + "editor.suggestSelection": "first", + "editor.formatOnPaste": true, + "explorer.confirmDragAndDrop": false, + "files.autoSave": "onWindowChange", + "editor.multiCursorModifier": "ctrlCmd", + "workbench.editor.untitled.hint": "hidden", + "git.autofetch": true, + "git.confirmSync": false, + "git.ignoreRebaseWarning": true, + "git.enableSmartCommit": true, + "editor.guides.bracketPairs": true, + "editor.guides.bracketPairsHorizontal": true, + "emmet.triggerExpansionOnTab": true, + "editor.inlineSuggest.enabled": true, + "github.copilot.enable": { + "*": true + }, + "editor.accessibilitySupport": "off", + "editor.fontFamily": "JetBrainsMono Nerd Font Mono", + "terminal.integrated.fontSize": 16, + "editor.linkedEditing": true, + "workbench.startupEditor": "none", + "markdown-preview-enhanced.liveUpdate": true, + "editor.formatOnSave": true, + "explorer.confirmDelete": false, + "catppuccin.accentColor": "sapphire", + "catppuccin.workbenchMode": "flat", + "workbench.settings.applyToAllProfiles": [], + "workbench.iconTheme": "catppuccin-mocha", + "workbench.colorTheme": "Catppuccin Mocha", + "window.titleBarStyle": "custom", + "nix.enableLanguageServer": true, + "nix.serverPath": "nil", + // using flakes with `formatter = pkgs.alejandra;` + "nix.formatterPath": ["nix", "fmt", "--", "-"], + "nix.serverSettings": { + // settings for 'nil' LSP + "nil": { + "formatting": { + "command": ["alejandra"] + } + } + } +} diff --git a/home/isabel/programs/gui/confs/bars/ags/config/.gitignore b/home/isabel/programs/gui/confs/bars/ags/config/.gitignore deleted file mode 100644 index 3eb0febcc..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.sass-cache -*.css -scss/generated.scss -scss/.goutputstream-* -settings.json diff --git a/home/isabel/programs/gui/confs/bars/ags/config/config.js b/home/isabel/programs/gui/confs/bars/ags/config/config.js index 3471fb447..b395bddfe 100644 --- a/home/isabel/programs/gui/confs/bars/ags/config/config.js +++ b/home/isabel/programs/gui/confs/bars/ags/config/config.js @@ -1,26 +1,39 @@ -/* exported config */ -import { Theme } from './theme/theme.js'; -import topbar from './layouts/topbar.js'; -import leftbar from './layouts/leftbar.js'; -import * as shared from './layouts/shared.js'; +"use strict"; -const layouts = { - topbar, - leftbar, -}; +import TopBar from "./js/bar/TopBar.js"; +import ScreenCorners from "./js/screencorner/ScreenCorners.js"; +import Dashboard from "./js/dashboard/Dashboard.js"; +import OSD from "./js/osd/OSD.js"; +import Applauncher from "./js/applauncher/Applauncher.js"; +import PowerMenu from "./js/powermenu/PowerMenu.js"; +import Verification from "./js/powermenu/Verification.js"; +import Notifications from "./js/notifications/Notifications.js"; +import QuickSettings from "./js/quicksettings/QuickSettings.js"; +import options from "./js/options.js"; +import * as setup from "./js/utils.js"; +import { forMonitors } from "./js/utils.js"; -const monitors = ags.Service.Hyprland.HyprctlGet('monitors') - .map(mon => mon.id); +setup.warnOnLowBattery(); +setup.scssWatcher(); +setup.globalServices(); +setup.activePlayer(); export default { + maxStreamVolume: 1.05, + cacheNotificationActions: true, closeWindowDelay: { - 'quicksettings': 300, - 'dashboard': 300, + quicksettings: options.windowAnimationDuration, + dashboard: options.windowAnimationDuration, }, windows: [ - ...layouts[Theme.getSetting('layout')](monitors), - shared.ApplauncherPopup(), - shared.PowermenuPopup(), - shared.VerificationPopup(), - ], + forMonitors(TopBar), + forMonitors(ScreenCorners), + forMonitors(OSD), + forMonitors(Notifications), + Applauncher(), + Dashboard(), + QuickSettings(), + PowerMenu(), + Verification(), + ].flat(2), }; diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/applauncher/Applauncher.js b/home/isabel/programs/gui/confs/bars/ags/config/js/applauncher/Applauncher.js new file mode 100644 index 000000000..5d4f88b16 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/applauncher/Applauncher.js @@ -0,0 +1,111 @@ +import { Widget, App, Applications } from "../imports.js"; +import Separator from "../misc/Separator.js"; +import PopupWindow from "../misc/PopupWindow.js"; +import icons from "../icons.js"; +import { launchApp } from "../utils.js"; + +const WINDOW_NAME = "applauncher"; + +const AppItem = (app) => + Widget.Button({ + className: "app", + onClicked: () => { + App.closeWindow(WINDOW_NAME); + launchApp(app); + }, + child: Widget.Box({ + children: [ + Widget.Icon({ + icon: app.iconName, + size: 48, + }), + Widget.Box({ + vertical: true, + children: [ + Widget.Label({ + className: "title", + label: app.name, + xalign: 0, + valign: "center", + ellipsize: 3, + }), + Widget.Label({ + className: "description", + label: app.description || "", + wrap: true, + xalign: 0, + justification: "left", + valign: "center", + }), + ], + }), + ], + }), + }); + +const Applauncher = () => { + const list = Widget.Box({ vertical: true }); + + const placeholder = Widget.Label({ + label: " Couldn't find a match", + className: "placeholder", + }); + + const entry = Widget.Entry({ + hexpand: true, + text: "-", + placeholderText: "Search", + onAccept: ({ text }) => { + const list = Applications.query(text); + if (list[0]) { + App.toggleWindow(WINDOW_NAME); + launchApp(list[0]); + } + }, + onChange: ({ text }) => { + list.children = Applications.query(text) + .map((app) => [Separator(), AppItem(app)]) + .flat(); + list.add(Separator()); + list.show_all(); + + placeholder.visible = list.children.length === 1; + }, + }); + + return Widget.Box({ + className: "applauncher", + properties: [["list", list]], + vertical: true, + children: [ + Widget.Box({ + className: "header", + children: [Widget.Icon(icons.apps.search), entry], + }), + Widget.Scrollable({ + hscroll: "never", + child: Widget.Box({ + vertical: true, + children: [list, placeholder], + }), + }), + ], + connections: [ + [ + App, + (_, name, visible) => { + if (name !== WINDOW_NAME) return; + + entry.set_text(""); + if (visible) entry.grab_focus(); + }, + ], + ], + }); +}; + +export default () => + PopupWindow({ + name: WINDOW_NAME, + content: Applauncher(), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/bar/PanelButton.js b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/PanelButton.js new file mode 100644 index 000000000..e61099810 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/PanelButton.js @@ -0,0 +1,8 @@ +import { Widget } from "../imports.js"; + +export default ({ className, content, ...rest }) => + Widget.Button({ + className: `panel-button ${className}`, + child: Widget.Box({ children: [content] }), + ...rest, + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/bar/TopBar.js b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/TopBar.js new file mode 100644 index 000000000..1ac39f38c --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/TopBar.js @@ -0,0 +1,91 @@ +import ApplauncherButton from "./buttons/ApplauncherButton.js"; +import Workspaces from "./buttons/Workspaces.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 Separator from "../misc/Separator.js"; +import BatteryBar from "./buttons/BatteryBar.js"; +import SubMenu from "./buttons/SubMenu.js"; +import { SystemTray, Widget, Variable } from "../imports.js"; +import { Notifications, Mpris, Battery } from "../imports.js"; + +const submenuItems = Variable(1); +SystemTray.connect("changed", () => { + submenuItems.setValue(SystemTray.items.length + 1); +}); + +const SeparatorDot = (service, condition) => + Separator({ + orientation: "vertical", + valign: "center", + connections: service && [ + [ + service, + (dot) => { + dot.visible = condition(service); + }, + ], + ], + }); + +const Start = () => + Widget.Box({ + className: "start", + children: [ + ApplauncherButton(), + SeparatorDot(), + Workspaces(), + SeparatorDot(), + Widget.Box({ hexpand: true }), + NotificationIndicator(), + SeparatorDot( + Notifications, + (n) => n.notifications.length > 0 || n.dnd, + ), + ], + }); + +const Center = () => + Widget.Box({ + className: "center", + children: [DateButton()], + }); + +const End = () => + Widget.Box({ + className: "end", + children: [ + SeparatorDot(Mpris, (m) => m.players.length > 0), + MediaIndicator(), + Widget.Box({ hexpand: true }), + + SubMenu({ + items: submenuItems, + children: [SysTray(), ColorPicker()], + }), + SeparatorDot(), + SystemIndicators(), + SeparatorDot(Battery, (b) => b.available), + BatteryBar(), + SeparatorDot(), + PowerMenu(), + ], + }); + +export default (monitor) => + Widget.Window({ + name: `bar${monitor}`, + exclusive: true, + monitor, + anchor: ["top", "left", "right"], + child: Widget.CenterBox({ + className: "panel", + startWidget: Start(), + centerWidget: Center(), + endWidget: End(), + }), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/ApplauncherButton.js b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/ApplauncherButton.js new file mode 100644 index 000000000..690fb3eea --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/ApplauncherButton.js @@ -0,0 +1,22 @@ +import PanelButton from "../PanelButton.js"; +import FontIcon from "../../misc/FontIcon.js"; +import { distroIcon } from "../../variables.js"; +import { App } from "../../imports.js"; + +export default () => + PanelButton({ + className: "applauncher", + connections: [ + [ + App, + (btn, win, visible) => { + btn.toggleClassName( + "active", + win === "applauncher" && visible, + ); + }, + ], + ], + onClicked: () => App.toggleWindow("applauncher"), + content: FontIcon(distroIcon), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/BatteryBar.js b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/BatteryBar.js new file mode 100644 index 000000000..2a1e5ae51 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/BatteryBar.js @@ -0,0 +1,70 @@ +import icons from "../../icons.js"; +import FontIcon from "../../misc/FontIcon.js"; +import options from "../../options.js"; +import PanelButton from "../PanelButton.js"; +import Gtk from "gi://Gtk"; +import { Battery, Widget } from "../../imports.js"; + +const Indicator = () => + Widget.Stack({ + items: [ + ["false", Widget.Icon({ binds: [["icon", Battery, "icon-name"]] })], + ["true", FontIcon({ icon: icons.battery.charging })], + ], + connections: [ + [ + Battery, + (stack) => { + stack.shown = `${Battery.charging || Battery.charged}`; + }, + ], + ], + }); + +const PercentLabel = () => + Widget.Revealer({ + transition: "slide_right", + revealChild: options.battaryBar.showPercentage, + child: Widget.Label({ + binds: [["label", Battery, "percent", (p) => `${p}%`]], + }), + }); + +const LevelBar = () => + Widget({ + type: Gtk.LevelBar, + valign: "center", + binds: [["value", Battery, "percent", (p) => p / 100]], + }); + +export default () => { + const revaler = PercentLabel(); + + return PanelButton({ + className: "battery-bar", + onClicked: () => (revaler.revealChild = !revaler.revealChild), + content: Widget.Box({ + binds: [["visible", Battery, "available"]], + connections: [ + [ + Battery, + (w) => { + w.toggleClassName( + "charging", + Battery.charging || Battery.charged, + ); + w.toggleClassName( + "medium", + Battery.percent < options.battaryBar.medium, + ); + w.toggleClassName( + "low", + Battery.percent < options.battaryBar.low, + ); + }, + ], + ], + children: [Indicator(), revaler, LevelBar()], + }), + }); +}; diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/ColorPicker.js b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/ColorPicker.js new file mode 100644 index 000000000..04ec1339a --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/ColorPicker.js @@ -0,0 +1,67 @@ +import PanelButton from "../PanelButton.js"; +import { Notifications, Utils, Widget, Variable } from "../../imports.js"; +import Gdk from "gi://Gdk"; + +const COLORS_CACHE = Utils.CACHE_DIR + "/colorpicker.json"; +const wlCopy = (color) => + Utils.execAsync(["wl-copy", color]).catch(() => + print("no colorpicker cache found"), + ); +const colors = Variable([]); +Utils.readFileAsync(COLORS_CACHE) + .then((out) => colors.setValue(JSON.parse(out || "[]"))) + .catch(() => print("no colorpicker cache found")); + +export default () => + PanelButton({ + className: "panel-button colorpicker", + content: Widget.Icon("color-select-symbolic"), + binds: [["tooltip-text", colors, "value", (v) => `${v.length} colors`]], + onClicked: (btn) => + Utils.execAsync("hyprpicker") + .then((color) => { + if (!color) return; + + wlCopy(color); + const list = colors.value; + if (!list.includes(color)) { + list.push(color); + if (list > 10) list.shift(); + + colors.value = list; + Utils.writeFile( + JSON.stringify(list, null, 2), + COLORS_CACHE, + ).catch((err) => console.error(err)); + } + + btn._id = Notifications.Notify( + "Color Picker", + btn._id || null, + "color-select-symbolic", + color, + "", + [], + {}, + ); + }) + .catch((err) => console.error(err)), + onSecondaryClick: (btn) => + colors.value.length > 0 + ? Widget.Menu({ + className: "colorpicker", + children: colors.value.map((color) => + Widget.MenuItem({ + child: Widget.Label(color), + style: `background-color: ${color}`, + onActivate: () => wlCopy(color), + }), + ), + }).popup_at_widget( + btn, + Gdk.Gravity.SOUTH, + Gdk.Gravity.NORTH, + null, + ) + : false, + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/DateButton.js b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/DateButton.js new file mode 100644 index 000000000..cb8e6deed --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/DateButton.js @@ -0,0 +1,21 @@ +import Clock from "../../misc/Clock.js"; +import PanelButton from "../PanelButton.js"; +import { App } from "../../imports.js"; + +export default ({ format = "%I:%M:%S | %d/%m/%y" } = {}) => + PanelButton({ + className: "dashboard panel-button", + onClicked: () => App.toggleWindow("dashboard"), + connections: [ + [ + App, + (btn, win, visible) => { + btn.toggleClassName( + "active", + win === "dashboard" && visible, + ); + }, + ], + ], + child: Clock({ format }), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/MediaIndicator.js b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/MediaIndicator.js new file mode 100644 index 000000000..7e85fdf85 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/MediaIndicator.js @@ -0,0 +1,71 @@ +import HoverRevealer from "../../misc/HoverRevealer.js"; +import * as mpris from "../../misc/mpris.js"; +import options from "../../options.js"; +import { Widget, Mpris, Utils } from "../../imports.js"; + +export const getPlayer = (name = options.preferredMpris) => + Mpris.getPlayer(name) || Mpris.players[0] || null; + +const Indicator = ({ player, direction = "right" } = {}) => + HoverRevealer({ + className: `media panel-button ${player.name}`, + direction, + onPrimaryClick: () => player.playPause(), + onScrollUp: () => player.next(), + onScrollDown: () => player.previous(), + onSecondaryClick: () => player.playPause(), + indicator: mpris.PlayerIcon(player), + child: Widget.Label({ + vexpand: true, + truncate: "end", + maxWidthChars: 40, + connections: [ + [ + player, + (label) => { + label.label = `${player.trackArtists.join(", ")} - ${ + player.trackTitle + }`; + }, + ], + ], + }), + connections: [ + [ + player, + (revealer) => { + if (revealer._current === player.trackTitle) return; + + revealer._current = player.trackTitle; + revealer.revealChild = true; + Utils.timeout(3000, () => { + revealer.revealChild = false; + }); + }, + ], + ], + }); + +export default ({ direction } = {}) => + Widget.Box({ + connections: [ + [ + Mpris, + (box) => { + const player = getPlayer(); + box.visible = !!player; + + if (!player) { + box._player = null; + return; + } + + if (box._player === player) return; + + box._player = player; + box.children = [Indicator({ player, direction })]; + }, + "notify::players", + ], + ], + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/NotificationIndicator.js b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/NotificationIndicator.js new file mode 100644 index 000000000..f549634ab --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/NotificationIndicator.js @@ -0,0 +1,59 @@ +import icons from "../../icons.js"; +import HoverRevealer from "../../misc/HoverRevealer.js"; +import { Widget, Notifications, Utils, App } from "../../imports.js"; + +export default ({ direction = "left" } = {}) => + HoverRevealer({ + className: "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.revealChild = true; + Utils.timeout(3000, () => { + revealer.revealChild = false; + }); + }, + ], + ], + direction, + indicator: Widget.Icon({ + binds: [ + [ + "icon", + Notifications, + "dnd", + (dnd) => + dnd + ? icons.notifications.silent + : icons.notifications.noisy, + ], + ], + }), + child: Widget.Label({ + truncate: "end", + maxWidthChars: 40, + binds: [ + [ + "label", + Notifications, + "notifications", + (n) => n[0]?.summary || "", + ], + ], + }), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/PowerMenu.js b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/PowerMenu.js new file mode 100644 index 000000000..bc411e712 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/PowerMenu.js @@ -0,0 +1,10 @@ +import icons from "../../icons.js"; +import PanelButton from "../PanelButton.js"; +import { Widget, App } from "../../imports.js"; + +export default () => + PanelButton({ + className: "powermenu", + content: Widget.Icon(icons.powermenu.shutdown), + onClicked: () => App.openWindow("powermenu"), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/SubMenu.js b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/SubMenu.js new file mode 100644 index 000000000..82684a1d7 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/SubMenu.js @@ -0,0 +1,62 @@ +import icons from "../../icons.js"; +import PanelButton from "../PanelButton.js"; +import { Widget, Utils, Variable } from "../../imports.js"; + +const Arrow = (revealer, direction, items) => + PanelButton({ + className: "sub-menu", + connections: [ + [ + items, + (btn) => { + btn.tooltipText = `${items.value} Items`; + }, + ], + ], + onClicked: (button) => { + const icon = button.child; + revealer.revealChild = !revealer.revealChild; + icon._animate(icon); + }, + child: Widget.Icon({ + icon: icons.ui.arrow[direction], + setup: (i) => i._animate(i), + properties: [ + ["deg", 180], + [ + "animate", + (icon) => { + const step = revealer.revealChild ? 10 : -10; + for (let i = 0; i < 18; ++i) { + Utils.timeout(2 * i, () => { + icon._deg += step; + icon.setStyle( + `-gtk-icon-transform: rotate(${icon._deg}deg);`, + ); + }); + } + }, + ], + ], + }), + }); + +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/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/SysTray.js b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/SysTray.js new file mode 100644 index 000000000..66c9427d4 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/SysTray.js @@ -0,0 +1,37 @@ +import PanelButton from "../PanelButton.js"; +import { SystemTray, Widget } from "../../imports.js"; +import Gdk from "gi://Gdk"; + +const SysTrayItem = (item) => + PanelButton({ + content: Widget.Icon({ binds: [["icon", item, "icon"]] }), + binds: [["tooltipMarkup", item, "tooltip-markup"]], + setup: (btn) => { + const id = item.menu.connect("popped-up", (menu) => { + btn.toggleClassName("active"); + menu.connect("notify::visible", (menu) => { + btn.toggleClassName("active", menu.visible); + }); + menu.disconnect(id); + }); + }, + onPrimaryClick: (btn) => + item.menu.popup_at_widget( + btn, + Gdk.Gravity.SOUTH, + Gdk.Gravity.NORTH, + null, + ), + onSecondaryClick: (btn) => + item.menu.popup_at_widget( + btn, + Gdk.Gravity.SOUTH, + Gdk.Gravity.NORTH, + null, + ), + }); + +export default () => + Widget.Box({ + binds: [["children", SystemTray, "items", (i) => i.map(SysTrayItem)]], + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/SystemIndicators.js b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/SystemIndicators.js new file mode 100644 index 000000000..65297ac01 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/SystemIndicators.js @@ -0,0 +1,150 @@ +import HoverRevealer from "../../misc/HoverRevealer.js"; +import PanelButton from "../PanelButton.js"; +import Indicator from "../../services/onScreenIndicator.js"; +import icons from "../../icons.js"; +import { App, Widget } from "../../imports.js"; +import { Bluetooth, Audio, Notifications, Network } from "../../imports.js"; + +const MicrophoneIndicator = () => + Widget.Icon({ + icon: icons.audio.mic.muted, + connections: [ + [ + Audio, + (icon) => { + icon.visible = Audio.microphone?.isMuted; + }, + "microphone-changed", + ], + ], + }); + +const DNDIndicator = () => + Widget.Icon({ + icon: icons.notifications.silent, + binds: [["visible", Notifications, "dnd"]], + }); + +const BluetoothDevicesIndicator = () => + Widget.Box({ + connections: [ + [ + 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({ + className: "bluetooth", + icon: icons.bluetooth.enabled, + binds: [["visible", Bluetooth, "enabled"]], + }); + +const NetworkIndicator = () => + Widget.Stack({ + items: [ + [ + "wifi", + Widget.Icon({ + connections: [ + [ + Network, + (icon) => { + icon.icon = Network.wifi?.iconName; + }, + ], + ], + }), + ], + [ + "wired", + Widget.Icon({ + connections: [ + [ + Network, + (icon) => { + icon.icon = Network.wired?.iconName; + }, + ], + ], + }), + ], + ], + binds: [["shown", Network, "primary"]], + }); + +const AudioIndicator = () => + Widget.Icon({ + connections: [ + [ + Audio, + (icon) => { + if (!Audio.speaker) return; + + const { muted, low, medium, high, overamplified } = + icons.audio.volume; + if (Audio.speaker.isMuted) return (icon.icon = muted); + + icon.icon = [ + [101, overamplified], + [67, high], + [34, medium], + [1, low], + [0, muted], + ].find( + ([threshold]) => + threshold <= Audio.speaker.volume * 100, + )[1]; + }, + "speaker-changed", + ], + ], + }); + +export default () => + PanelButton({ + className: "quicksettings panel-button", + onClicked: () => App.toggleWindow("quicksettings"), + onScrollUp: () => { + Audio.speaker.volume += 0.02; + Indicator.speaker(); + }, + onScrollDown: () => { + Audio.speaker.volume -= 0.02; + Indicator.speaker(); + }, + connections: [ + [ + App, + (btn, win, visible) => { + btn.toggleClassName( + "active", + win === "quicksettings" && visible, + ); + }, + ], + ], + child: Widget.Box({ + children: [ + DNDIndicator(), + BluetoothDevicesIndicator(), + BluetoothIndicator(), + NetworkIndicator(), + AudioIndicator(), + MicrophoneIndicator(), + ], + }), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/Workspaces.js b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/Workspaces.js new file mode 100644 index 000000000..5b4c9651d --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/bar/buttons/Workspaces.js @@ -0,0 +1,64 @@ +import { Hyprland, Widget, Utils } from "../../imports.js"; +import options from "../../options.js"; +import { range } from "../../utils.js"; + +const ws = options.workspaces; +const dispatch = (arg) => () => + Utils.execAsync(`hyprctl dispatch workspace ${arg}`); + +const Workspaces = () => + Widget.Box({ + children: range(ws || 20).map((i) => + Widget.Button({ + setup: (btn) => (btn.id = i), + onClicked: dispatch(i), + child: Widget.Label({ + label: `${i}`, + className: "indicator", + valign: "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.Box({ + className: "workspaces panel-button", + child: Widget.Box({ + // its nested like this to keep it consistent with other PanelButton widgets + child: Widget.EventBox({ + onScrollUp: dispatch(`${ws ? "r" : "m"}+1`), + onScrollDown: dispatch(`${ws ? "r" : "m"}-1`), + className: "eventbox", + child: Workspaces(), + }), + }), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/dashboard/Dashboard.js b/home/isabel/programs/gui/confs/bars/ags/config/js/dashboard/Dashboard.js new file mode 100644 index 000000000..d6304f399 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/dashboard/Dashboard.js @@ -0,0 +1,20 @@ +import DateColumn from "./DateColumn.js"; +import NotificationColumn from "./NotificationColumn.js"; +import PopupWindow from "../misc/PopupWindow.js"; +import Separator from "../misc/Separator.js"; +import { Widget } from "../imports.js"; + +export default ({ anchor = ["top"], layout = "top" } = {}) => + PopupWindow({ + name: "dashboard", + layout, + anchor, + content: Widget.Box({ + className: "dashboard", + children: [ + NotificationColumn(), + Separator({ orientation: "vertical" }), + DateColumn(), + ], + }), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/dashboard/DateColumn.js b/home/isabel/programs/gui/confs/bars/ags/config/js/dashboard/DateColumn.js new file mode 100644 index 000000000..7c6497d62 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/dashboard/DateColumn.js @@ -0,0 +1,62 @@ +import icons from "../icons.js"; +import Clock from "../misc/Clock.js"; +import * as vars from "../variables.js"; +import { Widget } from "../imports.js"; +import Theme from "../services/theme/theme.js"; + +const SysProgress = (type, title, unit) => + Widget.Box({ + className: `circular-progress-box ${type}`, + hexpand: true, + binds: [ + [ + "tooltipText", + vars[type], + "value", + (v) => `${title}: ${Math.floor(v * 100)}${unit}`, + ], + ], + child: Widget.CircularProgress({ + hexpand: true, + className: `circular-progress ${type}`, + child: Widget.Icon(icons.system[type]), + startAt: 0.75, + binds: [["value", vars[type]]], + connections: [ + [ + Theme, + (prog) => { + prog.rounded = Theme.getSetting("radii") > 0; + }, + ], + ], + }), + }); + +export default () => + Widget.Box({ + vertical: true, + className: "datemenu", + children: [ + Clock({ format: "%I:%M" }), + Widget.Label({ + binds: [["label", vars.uptime, "value", (t) => `uptime: ${t}`]], + }), + Widget.Box({ + className: "calendar", + child: Widget({ + type: imports.gi.Gtk.Calendar, + hexpand: true, + halign: "center", + }), + }), + Widget.Box({ + className: "system-info", + children: [ + SysProgress("cpu", "Cpu", "%"), + SysProgress("ram", "Ram", "%"), + SysProgress("temp", "Temperature", "°"), + ], + }), + ], + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/dashboard/NotificationColumn.js b/home/isabel/programs/gui/confs/bars/ags/config/js/dashboard/NotificationColumn.js new file mode 100644 index 000000000..8e12447f2 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/dashboard/NotificationColumn.js @@ -0,0 +1,93 @@ +import icons from "../icons.js"; +import Notification from "../misc/Notification.js"; +import { Widget, Notifications } from "../imports.js"; + +const ClearButton = () => + Widget.Button({ + onClicked: () => Notifications.clear(), + 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({ + className: "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({ + className: "placeholder", + vertical: true, + valign: "center", + halign: "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({ + className: "notifications", + vertical: true, + children: [ + Header(), + Widget.Scrollable({ + vexpand: true, + className: "notification-scrollable", + hscroll: "never", + vscroll: "automatic", + child: Widget.Box({ + className: "notification-list", + vertical: true, + children: [NotificationList(), Placeholder()], + }), + }), + ], + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/icons.js b/home/isabel/programs/gui/confs/bars/ags/config/js/icons.js new file mode 100644 index 000000000..61b31e6c0 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/icons.js @@ -0,0 +1,87 @@ +export default { + settings: "emblem-system-symbolic", + tick: "object-select-symbolic", + lock: "system-lock-screen-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: "", + }, + 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", + }, + 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: { + 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", + }, +}; diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/imports.js b/home/isabel/programs/gui/confs/bars/ags/config/js/imports.js new file mode 100644 index 000000000..1d981b474 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/imports.js @@ -0,0 +1,19 @@ +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"); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Avatar.js b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Avatar.js new file mode 100644 index 000000000..f9d31ff8e --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Avatar.js @@ -0,0 +1,19 @@ +import Theme from "../services/theme/theme.js"; +import { Widget } from "../imports.js"; + +export default (props) => + Widget.Box({ + ...props, + className: "avatar", + connections: [ + [ + Theme, + (box) => { + box.setStyle(` + background-image: url('${Theme.getSetting("avatar")}'); + background-size: cover; + `); + }, + ], + ], + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/misc/BatteryIcon.js b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/BatteryIcon.js new file mode 100644 index 000000000..0669e8ed6 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/BatteryIcon.js @@ -0,0 +1,19 @@ +import { Battery, Widget } from "../imports.js"; + +export default () => + Widget.Icon({ + className: "battery", + binds: [["icon", Battery, "icon-name"]], + connections: [ + [ + Battery, + (stack) => { + const { charging, charged } = Battery; + stack.shown = `${charging || charged}`; + stack.toggleClassName("charging", Battery.charging); + stack.toggleClassName("charged", Battery.charged); + stack.toggleClassName("low", Battery.percent < 30); + }, + ], + ], + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Clock.js b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Clock.js new file mode 100644 index 000000000..f1dc31b2d --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Clock.js @@ -0,0 +1,20 @@ +import { Widget } from "../imports.js"; +import GLib from "gi://GLib"; + +export default ({ + format = "%H:%M:%S %B %e. %A", + interval = 1000, + ...props +} = {}) => + Widget.Label({ + className: "clock", + ...props, + connections: [ + [ + interval, + (label) => + (label.label = + GLib.DateTime.new_now_local().format(format)), + ], + ], + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/misc/FontIcon.js b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/FontIcon.js new file mode 100644 index 000000000..1d7ff7fdb --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/FontIcon.js @@ -0,0 +1,44 @@ +import Gtk from "gi://Gtk"; +import GObject from "gi://GObject"; +import { Widget } from "../imports.js"; + +class FontIcon extends Gtk.Label { + static { + GObject.registerClass(this); + } + + constructor(params = "") { + const { icon = "", ...rest } = params; + super(typeof params === "string" ? {} : rest); + this.toggleClassName("font-icon"); + + if (typeof params === "object") this.icon = icon; + } + + 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, + ); + } + + vfunc_get_preferred_height() { + return [this.size, this.size]; + } + + vfunc_get_preferred_width() { + return [this.size, this.size]; + } +} + +export default (params) => + typeof params === "string" + ? Widget({ type: FontIcon, icon: params }) + : Widget({ type: FontIcon, ...params }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/misc/HoverRevealer.js b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/HoverRevealer.js new file mode 100644 index 000000000..a4dc2205d --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/HoverRevealer.js @@ -0,0 +1,50 @@ +import { Widget, Utils } from "../imports.js"; + +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, + transitionDuration: duration, + child, + }); + + const box = Widget.EventBox({ + ...rest, + connections: eventboxConnections, + onHover: () => { + if (open) return; + + revealer.revealChild = true; + Utils.timeout(duration, () => (open = true)); + }, + onHoverLost: () => { + if (!open) return; + + revealer.revealChild = false; + open = false; + }, + child: Widget.Box({ + vertical, + children: [posStart && indicator, revealer, posEnd && indicator], + }), + }); + + return Widget.Box({ + children: [box], + }); +}; diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/misc/IconBrowser.js b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/IconBrowser.js new file mode 100644 index 000000000..c8c18a9ca --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/IconBrowser.js @@ -0,0 +1,68 @@ +import { Widget } from "../imports.js"; +import Gtk from "gi://Gtk"; + +export default () => { + const selected = Widget.Label({ + style: "font-size: 1.2em;", + }); + + const flowbox = Widget({ + type: Gtk.FlowBox, + min_children_per_line: 10, + connections: [ + [ + "child-activated", + (_, { child }) => { + selected.label = child.iconName; + }, + ], + ], + setup: (self) => { + 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({ + onChange: ({ text }) => + flowbox.get_children().forEach((child) => { + child.visible = child.child.iconName.includes(text); + }), + }); + + return Widget({ + name: "icons", + type: Gtk.Window, + visible: true, + child: Widget.Box({ + style: "padding: 30px;", + spacing: 20, + vertical: true, + children: [ + entry, + Widget.Scrollable({ + hscroll: "never", + vscroll: "always", + hexpand: true, + vexpand: true, + style: "min-width: 500px;" + "min-height: 500px;", + child: flowbox, + }), + selected, + ], + }), + }); +}; diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Notification.js b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Notification.js new file mode 100644 index 000000000..5a28a842a --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Notification.js @@ -0,0 +1,150 @@ +import { Utils, Widget, Variable } from "../imports.js"; +import GLib from "gi://GLib"; + +const NotificationIcon = ({ appEntry, appIcon, image }) => { + if (image) { + return Widget.Box({ + valign: "start", + hexpand: false, + className: "icon img", + style: ` + background-image: url("${image}"); + background-size: contain; + background-repeat: no-repeat; + background-position: center; + min-width: 78px; + min-height: 78px; + `, + }); + } + + let icon = "dialog-information-symbolic"; + if (Utils.lookUpIcon(appIcon)) icon = appIcon; + + if (Utils.lookUpIcon(appEntry)) icon = appEntry; + + return Widget.Box({ + valign: "start", + hexpand: false, + className: "icon", + style: ` + min-width: 78px; + min-height: 78px; + `, + child: Widget.Icon({ + icon, + size: 58, + halign: "center", + hexpand: true, + valign: "center", + vexpand: true, + }), + }); +}; + +export default (notification) => { + const hovered = Variable(false); + + const hover = () => { + hovered.value = true; + hovered._block = true; + + Utils.timeout(100, () => (hovered._block = false)); + }; + + const hoverLost = () => + GLib.idle_add(0, () => { + if (hovered._block) return GLib.SOURCE_REMOVE; + + hovered.value = false; + notification.dismiss(); + return GLib.SOURCE_REMOVE; + }); + + const content = Widget.Box({ + className: "content", + children: [ + NotificationIcon(notification), + Widget.Box({ + hexpand: true, + vertical: true, + children: [ + Widget.Box({ + children: [ + Widget.Label({ + className: "title", + xalign: 0, + justification: "left", + hexpand: true, + maxWidthChars: 24, + truncate: "end", + wrap: true, + label: notification.summary, + useMarkup: notification.summary.startsWith("<"), + }), + Widget.Label({ + className: "time", + valign: "start", + label: GLib.DateTime.new_from_unix_local( + notification.time, + ).format("%H:%M"), + }), + Widget.Button({ + onHover: hover, + className: "close-button", + valign: "start", + child: Widget.Icon("window-close-symbolic"), + onClicked: () => notification.close(), + }), + ], + }), + Widget.Label({ + className: "description", + hexpand: true, + useMarkup: true, + xalign: 0, + justification: "left", + label: notification.body, + wrap: true, + }), + ], + }), + ], + }); + + const actionsbox = Widget.Revealer({ + transition: "slide_down", + binds: [["revealChild", hovered]], + child: Widget.EventBox({ + onHover: hover, + child: Widget.Box({ + className: "actions", + children: notification.actions.map((action) => + Widget.Button({ + onHover: hover, + className: "action-button", + onClicked: () => notification.invoke(action.id), + hexpand: true, + child: Widget.Label(action.label), + }), + ), + }), + }), + }); + + return Widget.EventBox({ + className: `notification ${notification.urgency}`, + vexpand: false, + onPrimaryClick: () => { + hovered.value = false; + notification.dismiss(); + }, + properties: [["hovered", hovered]], + onHover: hover, + onHoverLost: hoverLost, + child: Widget.Box({ + vertical: true, + children: [content, notification.actions.length > 0 && actionsbox], + }), + }); +}; diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/misc/PopupWindow.js b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/PopupWindow.js new file mode 100644 index 000000000..9dc618bb1 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/PopupWindow.js @@ -0,0 +1,98 @@ +import options from "../options.js"; +import { App, Widget } from "../imports.js"; + +const Padding = (windowName) => + Widget.EventBox({ + className: "padding", + hexpand: true, + vexpand: true, + connections: [ + ["button-press-event", () => App.toggleWindow(windowName)], + ], + }); + +const PopupRevealer = (windowName, transition, child) => + Widget.Box({ + style: "padding: 1px;", + child: Widget.Revealer({ + transition, + child, + transitionDuration: options.windowAnimationDuration, + connections: [ + [ + App, + (revealer, name, visible) => { + if (name === windowName) + revealer.reveal_child = visible; + }, + ], + ], + }), + }); + +const layouts = { + center: (windowName, child, expand) => + Widget.CenterBox({ + className: "shader", + style: expand ? "min-width: 5000px; min-height: 3000px;" : "", + children: [ + Padding(windowName), + Widget.CenterBox({ + vertical: true, + children: [Padding(windowName), child, Padding(windowName)], + }), + Padding(windowName), + ], + }), + top: (windowName, child) => + Widget.CenterBox({ + children: [ + Padding(windowName), + Widget.Box({ + vertical: true, + children: [ + PopupRevealer(windowName, "slide_down", child), + Padding(windowName), + ], + }), + Padding(windowName), + ], + }), + "top right": (windowName, child) => + Widget.Box({ + children: [ + Padding(windowName), + Widget.Box({ + hexpand: false, + vertical: true, + children: [ + PopupRevealer(windowName, "slide_down", child), + Padding(windowName), + ], + }), + ], + }), + "bottom right": (windowName, child) => + Widget.Box({ + children: [ + Padding(windowName), + Widget.Box({ + hexpand: false, + vertical: true, + children: [ + Padding(windowName), + PopupRevealer(windowName, "slide_up", child), + ], + }), + ], + }), +}; + +export default ({ layout = "center", expand = true, name, content, ...rest }) => + Widget.Window({ + name, + child: layouts[layout](name, content, expand), + popup: true, + focusable: true, + ...rest, + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Progress.js b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Progress.js new file mode 100644 index 000000000..0b108e3ae --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Progress.js @@ -0,0 +1,54 @@ +import { Widget, Utils } from "../imports.js"; + +export default ({ + height = 18, + width = 180, + vertical = false, + child, + ...props +}) => { + const fill = Widget.Box({ + className: "fill", + hexpand: vertical, + vexpand: !vertical, + halign: vertical ? "fill" : "start", + valign: vertical ? "end" : "fill", + children: [child], + }); + + return Widget.Box({ + ...props, + className: "progress", + style: ` + 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.setStyle(`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.setStyle(`min-${axis}: ${fill._size}px`); + }); + } + }), + }); +}; diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Separator.js b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Separator.js new file mode 100644 index 000000000..2110059bf --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Separator.js @@ -0,0 +1,9 @@ +import Gtk from "gi://Gtk"; +import { Widget } from "../imports.js"; + +export default ({ orientation = "vertical", ...rest } = {}) => + Widget({ + ...rest, + type: Gtk.Separator, + orientation: Gtk.Orientation[orientation.toUpperCase()], + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Spinner.js b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Spinner.js new file mode 100644 index 000000000..61d428c5a --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Spinner.js @@ -0,0 +1,9 @@ +import Gtk from "gi://Gtk"; +import { Widget } from "../imports.js"; + +export default (props) => + Widget({ + ...props, + type: Gtk.Spinner, + active: true, + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Wallpaper.js b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Wallpaper.js new file mode 100644 index 000000000..0e7b2da01 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/Wallpaper.js @@ -0,0 +1,19 @@ +import Theme from "../services/theme/theme.js"; +import { Widget } from "../imports.js"; + +export default ({ className, ...props }) => + Widget.Box({ + ...props, + className: `wallpaper ${className}`, + connections: [ + [ + Theme, + (box) => { + box.setStyle(` + background-image: url('${Theme.getSetting("wallpaper")}'); + background-size: cover; + `); + }, + ], + ], + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/misc/mpris.js b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/mpris.js new file mode 100644 index 000000000..0965572cc --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/misc/mpris.js @@ -0,0 +1,299 @@ +import icons from "../icons.js"; +import { Utils, Widget } from "../imports.js"; +import GLib from "gi://GLib"; + +const MEDIA_CACHE_PATH = Utils.CACHE_DIR + "/media"; + +export const CoverArt = (player, props) => + Widget.Box({ + ...props, + className: "cover", + binds: [ + [ + "style", + player, + "cover-path", + (path) => `background-image: url("${path}")`, + ], + ], + }); + +export const BlurredCoverArt = (player, props) => + Widget.Box({ + ...props, + className: "blurred-cover", + connections: [ + [ + player, + (box) => { + const url = player.coverPath; + if (!url) return; + + const blurredPath = MEDIA_CACHE_PATH + "/blurred"; + const blurred = + blurredPath + url.substring(MEDIA_CACHE_PATH.length); + + if (GLib.file_test(blurred, GLib.FileTest.EXISTS)) { + box.setStyle(`background-image: url("${blurred}")`); + return; + } + + Utils.ensureDirectory(blurredPath); + Utils.execAsync(["convert", url, "-blur", "0x22", blurred]) + .then(() => + box.setStyle(`background-image: url("${blurred}")`), + ) + .catch(() => {}); + }, + "notify::cover-path", + ], + ], + }); + +export const TitleLabel = (player, props) => + Widget.Label({ + ...props, + className: "title", + binds: [["label", player, "track-title"]], + }); + +export const ArtistLabel = (player, props) => + Widget.Label({ + ...props, + className: "artist", + binds: [["label", player, "track-artists", (a) => a.join(", ") || ""]], + }); + +export const PlayerIcon = (player, { symbolic = true, ...props } = {}) => + Widget.Icon({ + ...props, + className: "player-icon", + tooltipText: player.identity || "", + connections: [ + [ + player, + (icon) => { + const name = `${player.entry}${ + symbolic ? "-symbolic" : "" + }`; + Utils.lookUpIcon(name) + ? (icon.icon = name) + : (icon.icon = icons.mpris.fallback); + }, + ], + ], + }); + +export const PositionSlider = (player, props) => + Widget.Slider({ + ...props, + className: "position-slider", + drawValue: false, + onChange: ({ 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)], + ], + }); + +function lengthStr(length) { + const min = Math.floor(length / 60); + const sec = Math.floor(length % 60); + const sec0 = sec < 10 ? "0" : ""; + return `${min}:${sec0}${sec}`; +} + +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)], + ], + }); + +export const LengthLabel = (player) => + Widget.Label({ + connections: [ + [ + player, + (label) => { + player.length > 0 + ? (label.label = lengthStr(player.length)) + : (label.visible = !!player); + }, + ], + ], + }); + +export const Slash = (player) => + Widget.Label({ + label: "/", + connections: [ + [ + player, + (label) => { + label.visible = player.length > 0; + }, + ], + ], + }); + +const PlayerButton = ({ player, items, onClick, prop, canProp, cantValue }) => + Widget.Button({ + child: Widget.Stack({ + items, + binds: [["shown", player, prop, (p) => `${p}`]], + }), + onClicked: player[onClick].bind(player), + binds: [["visible", player, canProp, (c) => c !== cantValue]], + }); + +export const ShuffleButton = (player) => + PlayerButton({ + player, + items: [ + [ + "true", + Widget.Label({ + className: "shuffle enabled", + label: icons.mpris.shuffle.enabled, + }), + ], + [ + "false", + Widget.Label({ + className: "shuffle disabled", + label: icons.mpris.shuffle.disabled, + }), + ], + ], + onClick: "shuffle", + prop: "shuffle-status", + canProp: "shuffle-status", + cantValue: null, + }); + +export const LoopButton = (player) => + PlayerButton({ + player, + items: [ + [ + "None", + Widget.Label({ + className: "loop none", + label: icons.mpris.loop.none, + }), + ], + [ + "Track", + Widget.Label({ + className: "loop track", + label: icons.mpris.loop.track, + }), + ], + [ + "Playlist", + Widget.Label({ + className: "loop playlist", + label: icons.mpris.loop.playlist, + }), + ], + ], + onClick: "loop", + prop: "loop-status", + canProp: "loop-status", + cantValue: null, + }); + +export const PlayPauseButton = (player) => + PlayerButton({ + player, + items: [ + [ + "Playing", + Widget.Label({ + className: "playing", + label: icons.mpris.playing, + }), + ], + [ + "Paused", + Widget.Label({ + className: "paused", + label: icons.mpris.paused, + }), + ], + [ + "Stopped", + Widget.Label({ + className: "stopped", + label: icons.mpris.stopped, + }), + ], + ], + onClick: "playPause", + prop: "play-back-status", + canProp: "can-play", + cantValue: false, + }); + +export const PreviousButton = (player) => + PlayerButton({ + player, + items: [ + [ + "true", + Widget.Label({ + className: "previous", + label: icons.mpris.prev, + }), + ], + ], + onClick: "previous", + prop: "can-go-prev", + canProp: "can-go-prev", + cantValue: false, + }); + +export const NextButton = (player) => + PlayerButton({ + player, + items: [ + [ + "true", + Widget.Label({ + className: "next", + label: icons.mpris.next, + }), + ], + ], + onClick: "next", + prop: "can-go-next", + canProp: "can-go-next", + cantValue: false, + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/notifications/Notifications.js b/home/isabel/programs/gui/confs/bars/ags/config/js/notifications/Notifications.js new file mode 100644 index 000000000..44c909210 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/notifications/Notifications.js @@ -0,0 +1,59 @@ +import Notification from "../misc/Notification.js"; +import { Notifications, Widget, Utils } from "../imports.js"; + +const Popups = () => { + const map = new Map(); + + const onDismissed = (box, id, force = false) => { + if (!id || !map.has(id)) return; + + if (map.get(id)._hovered.value && !force) return; + + if (map.size - 1 === 0) box.get_parent().revealChild = false; + + Utils.timeout(200, () => { + map.get(id)?.destroy(); + map.delete(id); + }); + }; + + const onNotified = (box, id) => { + if (!id || Notifications.dnd) return; + + map.delete(id); + map.set(id, Notification(Notifications.getNotification(id))); + box.children = Array.from(map.values()).reverse(); + Utils.timeout(10, () => { + box.get_parent().revealChild = true; + }); + }; + + return Widget.Box({ + vertical: true, + connections: [ + [Notifications, onNotified, "notified"], + [Notifications, onDismissed, "dismissed"], + [Notifications, (box, id) => onDismissed(box, id, true), "closed"], + ], + }); +}; + +const PopupList = ({ transition = "slide_down" } = {}) => + Widget.Box({ + className: "notifications-popup-list", + style: "padding: 1px", + children: [ + Widget.Revealer({ + transition, + child: Popups(), + }), + ], + }); + +export default (monitor) => + Widget.Window({ + monitor, + name: `notifications${monitor}`, + anchor: ["top"], + child: PopupList(), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/options.js b/home/isabel/programs/gui/confs/bars/ags/config/js/options.js new file mode 100644 index 000000000..592c33358 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/options.js @@ -0,0 +1,25 @@ +export default { + // if this player is running this will be shown on panel + preferredMpris: "spotify", + + // number of workspaces shown on panel and overview + workspaces: 7, + + battaryBar: { + // wether to show percentage by deafult + showPercentage: false, + + // at what percentages should the battery-bar change color + low: 30, + medium: 50, + }, + + // path to read temperature from + temperature: "/sys/class/thermal/thermal_zone0/temp", + + // at what intervals should cpu, ram, temperature refresh + systemFetchInterval: 5000, + + // the slide down animation on quicksettings and dashboard + windowAnimationDuration: 250, +}; diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/osd/OSD.js b/home/isabel/programs/gui/confs/bars/ags/config/js/osd/OSD.js new file mode 100644 index 000000000..a5506d671 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/osd/OSD.js @@ -0,0 +1,83 @@ +import { Utils, Widget } from "../imports.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({ + className: "indicator", + style: "padding: 1px;", + child: Widget.Revealer({ + transition: "slide_left", + connections: [ + [ + Indicator, + (revealer, value) => { + revealer.revealChild = value > -1; + }, + ], + ], + child: Progress({ + width, + height, + vertical: true, + connections: [ + [Indicator, (progress, value) => progress.setValue(value)], + ], + child: Widget.Stack({ + valign: "start", + halign: "center", + hexpand: false, + items: [ + [ + "true", + Widget.Icon({ + halign: "center", + size: width, + connections: [ + [ + Indicator, + (icon, _v, name) => + (icon.icon = name || ""), + ], + ], + }), + ], + [ + "false", + FontIcon({ + halign: "center", + hexpand: true, + style: `font-size: ${width}px;`, + connections: [ + [ + Indicator, + (icon, _v, name) => + (icon.icon = name || ""), + ], + ], + }), + ], + ], + connections: [ + [ + Indicator, + (stack, _v, name) => { + stack.shown = `${!!Utils.lookUpIcon(name)}`; + }, + ], + ], + }), + }), + }), + }); + +export default (monitor) => + Widget.Window({ + name: `indicator${monitor}`, + monitor, + className: "indicator", + layer: "overlay", + anchor: ["right"], + child: OnScreenIndicator(), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/powermenu/PowerMenu.js b/home/isabel/programs/gui/confs/bars/ags/config/js/powermenu/PowerMenu.js new file mode 100644 index 000000000..304f50572 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/powermenu/PowerMenu.js @@ -0,0 +1,32 @@ +import icons from "../icons.js"; +import PowerMenu from "../services/powermenu.js"; +import PopupWindow from "../misc/PopupWindow.js"; +import { Widget } from "../imports.js"; + +const SysButton = (action, label) => + Widget.Button({ + onClicked: () => PowerMenu.action(action), + child: Widget.Box({ + vertical: true, + children: [ + Widget.Icon(icons.powermenu[action]), + Widget.Label(label), + ], + }), + }); + +export default () => + PopupWindow({ + name: "powermenu", + expand: true, + content: Widget.Box({ + className: "powermenu", + homogeneous: true, + children: [ + SysButton("sleep", "Sleep"), + SysButton("reboot", "Reboot"), + SysButton("logout", "Log Out"), + SysButton("shutdown", "Shutdown"), + ], + }), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/powermenu/Verification.js b/home/isabel/programs/gui/confs/bars/ags/config/js/powermenu/Verification.js new file mode 100644 index 000000000..0a7060e0f --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/powermenu/Verification.js @@ -0,0 +1,39 @@ +import PopupWindow from "../misc/PopupWindow.js"; +import PowerMenu from "../services/powermenu.js"; +import { Widget, App, Utils } from "../imports.js"; + +export default () => + PopupWindow({ + name: "verification", + expand: true, + content: Widget.Box({ + className: "verification", + vertical: true, + children: [ + Widget.Label({ + className: "title", + binds: [["label", PowerMenu, "title"]], + }), + Widget.Label({ + className: "desc", + label: "Are you sure?", + }), + Widget.Box({ + className: "buttons", + vexpand: true, + valign: "end", + homogeneous: true, + children: [ + Widget.Button({ + child: Widget.Label("No"), + onClicked: () => App.toggleWindow("verification"), + }), + Widget.Button({ + child: Widget.Label("Yes"), + onClicked: () => Utils.exec(PowerMenu.cmd), + }), + ], + }), + ], + }), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/QuickSettings.js b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/QuickSettings.js new file mode 100644 index 000000000..60a7cf40f --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/QuickSettings.js @@ -0,0 +1,68 @@ +import Header from "./widgets/Header.js"; +import PopupWindow from "../misc/PopupWindow.js"; +import { + Volume, + Microphone, + 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 Media from "./widgets/Media.js"; +import Brightness from "./widgets/Brightness.js"; +import DND from "./widgets/DND.js"; +import MicMute from "./widgets/MicMute.js"; +import { Widget } from "../imports.js"; + +const Row = (toggles, menus = []) => + Widget.Box({ + className: "row", + vertical: true, + children: [ + Widget.Box({ + children: toggles, + }), + ...menus, + ], + }); + +const Homogeneous = (toggles) => + Widget.Box({ + homogeneous: true, + children: toggles, + }); + +export default () => + PopupWindow({ + name: "quicksettings", + anchor: ["top", "right"], + layout: "top right", + content: Widget.Box({ + className: "quicksettings", + vertical: true, + children: [ + Row([Header()]), + Row([ + Widget.Box({ + className: "slider-box", + vertical: true, + children: [ + Row([Volume()], [SinkSelector(), AppMixer()]), + Row([Microphone()]), + Row([Brightness()]), + ], + }), + ]), + Row( + [Homogeneous([NetworkToggle(), BluetoothToggle()]), DND()], + [WifiSelection(), BluetoothDevices()], + ), + Row( + [Homogeneous([ThemeToggle()]), MicMute()], + [ThemeSelector()], + ), + Media(), + ], + }), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/ToggleButton.js b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/ToggleButton.js new file mode 100644 index 000000000..529a31c70 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/ToggleButton.js @@ -0,0 +1,131 @@ +import icons from "../icons.js"; +import Separator from "../misc/Separator.js"; +import { Utils, Widget, App, Variable } from "../imports.js"; + +export const opened = Variable(""); +App.connect("window-toggled", (_, name, visible) => { + if (name === "quicksettings" && !visible) + Utils.timeout(500, () => (opened.value = "")); +}); + +export const Arrow = (name, activate) => + Widget.Button({ + child: Widget.Icon({ + icon: icons.ui.arrow.right, + properties: [["deg", 0]], + connections: [ + [ + opened, + (icon) => { + if ( + (opened.value === name && !icon._opened) || + (opened.value !== name && icon._opened) + ) { + const step = opened.value === name ? 10 : -10; + icon._opened = !icon._opened; + for (let i = 0; i < 9; ++i) { + Utils.timeout(15 * i, () => { + icon._deg += step; + icon.setStyle( + `-gtk-icon-transform: rotate(${icon._deg}deg);`, + ); + }); + } + } + }, + ], + ], + }), + onClicked: () => { + opened.value = opened.value === name ? "" : name; + if (activate) activate(); + }, + }); + +export const ArrowToggleButton = ({ + name, + icon, + label, + activate, + deactivate, + activateOnArrow = true, + connection: [service, condition], +}) => + Widget.Box({ + className: "toggle-button", + connections: [ + [ + service, + (box) => { + box.toggleClassName("active", condition()); + }, + ], + ], + children: [ + Widget.Button({ + child: Widget.Box({ + hexpand: true, + children: [icon, label], + }), + onClicked: () => { + if (condition()) { + deactivate(); + if (opened.value === name) opened.value = ""; + } else { + activate(); + } + }, + }), + Arrow(name, activateOnArrow && activate), + ], + }); + +export const Menu = ({ name, icon, title, content }) => + Widget.Revealer({ + transition: "slide_down", + connections: [ + [ + opened, + (revealer) => { + revealer.revealChild = opened.value === name; + }, + ], + ], + child: Widget.Box({ + className: "menu", + vertical: true, + children: [ + Widget.Box({ + className: "title", + children: [icon, title], + }), + Separator({ orientation: "horizontal" }), + Widget.Box({ + className: "content", + children: [content], + }), + ], + }), + }); + +export const SimpleToggleButton = ({ + icon, + label, + toggle, + connection: [service, condition], +}) => + Widget.Button({ + className: "simple-toggle", + connections: [ + [ + service, + (box) => { + box.toggleClassName("active", condition()); + }, + ], + ], + child: Widget.Box({ + children: [icon, label], + }), + onClicked: toggle, + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Bluetooth.js b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Bluetooth.js new file mode 100644 index 000000000..18f083753 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Bluetooth.js @@ -0,0 +1,97 @@ +import icons from "../../icons.js"; +import Spinner from "../../misc/Spinner.js"; +import { Menu, ArrowToggleButton } from "../ToggleButton.js"; +import { Bluetooth, Widget } from "../../imports.js"; +import Gtk from "gi://Gtk"; + +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), + }); + +export const BluetoothDevices = () => + Menu({ + name: "bluetooth", + icon: Widget.Icon(icons.bluetooth.disabled), + title: Widget.Label("Bluetooth"), + content: Widget.Box({ + hexpand: true, + vertical: true, + connections: [ + [ + Bluetooth, + (box) => { + box.children = Bluetooth.devices + .filter((d) => d.name) + .map((device) => + Widget.Box({ + children: [ + Widget.Icon( + device.iconName + "-symbolic", + ), + Widget.Label(device.name), + device.batteryPercentage > 0 && + Widget.Label( + `${device.batteryPercentage}%`, + ), + Widget.Box({ hexpand: true }), + device.connecting + ? Spinner() + : Widget({ + type: Gtk.Switch, + active: device.connected, + connections: [ + [ + "notify::active", + ({ active }) => { + device.setConnection( + active, + ); + }, + ], + ], + }), + ], + }), + ); + }, + ], + ], + }), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Brightness.js b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Brightness.js new file mode 100644 index 000000000..1c83efaac --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Brightness.js @@ -0,0 +1,31 @@ +import icons from "../../icons.js"; +import Brightness from "../../services/brightness.js"; +import { Widget } from "../../imports.js"; + +const BrightnessSlider = () => + Widget.Slider({ + drawValue: false, + hexpand: true, + binds: [["value", Brightness, "screen"]], + onChange: ({ value }) => (Brightness.screen = value), + }); + +export default () => + Widget.Box({ + className: "slider", + children: [ + Widget.Icon({ + icon: icons.brightness.indicator, + className: "icon", + binds: [ + [ + "tooltip-text", + Brightness, + "screen", + (v) => `Screen Brightness: ${Math.floor(v * 100)}%`, + ], + ], + }), + BrightnessSlider(), + ], + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/DND.js b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/DND.js new file mode 100644 index 000000000..f57b58854 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/DND.js @@ -0,0 +1,22 @@ +import icons from "../../icons.js"; +import { SimpleToggleButton } from "../ToggleButton.js"; +import { Notifications, Widget } from "../../imports.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/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Header.js b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Header.js new file mode 100644 index 000000000..22724ccf9 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Header.js @@ -0,0 +1,95 @@ +import icons from "../../icons.js"; +import PowerMenu from "../../services/powermenu.js"; +import Theme from "../../services/theme/theme.js"; +import Avatar from "../../misc/Avatar.js"; +import { uptime } from "../../variables.js"; +import { Battery, Widget } from "../../imports.js"; + +export const BatteryProgress = () => + Widget.Box({ + className: "battery-progress", + vexpand: true, + binds: [["visible", Battery, "available"]], + connections: [ + [ + Battery, + (w) => { + w.toggleClassName("half", Battery.percent < 46); + w.toggleClassName("low", Battery.percent < 30); + }, + ], + ], + child: Widget.Overlay({ + vexpand: true, + child: Widget.ProgressBar({ + hexpand: true, + vexpand: true, + connections: [ + [ + Battery, + (progress) => { + progress.fraction = Battery.percent / 100; + }, + ], + ], + }), + overlays: [ + Widget.Label({ + connections: [ + [ + Battery, + (l) => { + l.label = + Battery.charging || Battery.charged + ? icons.battery.charging + : `${Battery.percent}%`; + }, + ], + ], + }), + ], + }), + }); + +export default () => + Widget.Box({ + className: "header", + children: [ + Avatar(), + Widget.Box({ + className: "system-box", + vertical: true, + hexpand: true, + children: [ + Widget.Box({ + children: [ + Widget.Button({ + valign: "center", + onClicked: () => Theme.openSettings(), + child: Widget.Icon(icons.settings), + }), + Widget.Label({ + className: "uptime", + hexpand: true, + valign: "center", + connections: [ + [ + uptime, + (label) => { + label.label = `uptime: ${uptime.value}`; + }, + ], + ], + }), + Widget.Button({ + valign: "center", + onClicked: () => PowerMenu.action("shutdown"), + child: Widget.Icon(icons.powermenu.shutdown), + }), + ], + }), + BatteryProgress(), + ], + }), + ], + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Media.js b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Media.js new file mode 100644 index 000000000..ed41c85d8 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Media.js @@ -0,0 +1,103 @@ +import * as mpris from "../../misc/mpris.js"; +import { Mpris, Widget } from "../../imports.js"; + +const blackList = ["Caprine"]; + +const Footer = (player) => + Widget.CenterBox({ + className: "footer-box", + children: [ + Widget.Box({ + className: "position", + children: [ + mpris.PositionLabel(player), + mpris.Slash(player), + mpris.LengthLabel(player), + ], + }), + Widget.Box({ + className: "controls", + children: [ + mpris.ShuffleButton(player), + mpris.PreviousButton(player), + mpris.PlayPauseButton(player), + mpris.NextButton(player), + mpris.LoopButton(player), + ], + }), + mpris.PlayerIcon(player, { + symbolic: false, + hexpand: true, + halign: "end", + }), + ], + }); + +const TextBox = (player) => + Widget.Box({ + children: [ + mpris.CoverArt(player, { + halign: "end", + hexpand: false, + child: Widget.Box({ + className: "shader", + hexpand: true, + }), + }), + Widget.Box({ + hexpand: true, + vertical: true, + className: "labels", + children: [ + mpris.TitleLabel(player, { + xalign: 0, + justification: "left", + wrap: true, + }), + mpris.ArtistLabel(player, { + xalign: 0, + justification: "left", + wrap: true, + }), + ], + }), + ], + }); + +const PlayerBox = (player) => + Widget.Box({ + className: `player ${player.name}`, + child: mpris.BlurredCoverArt(player, { + className: "cover-art-bg", + hexpand: true, + children: [ + Widget.Box({ + className: "shader", + hexpand: true, + vertical: true, + children: [ + TextBox(player), + mpris.PositionSlider(player), + Footer(player), + ], + }), + ], + }), + }); + +export default () => + Widget.Box({ + vertical: true, + className: "media", + binds: [ + [ + "children", + Mpris, + "players", + (ps) => + ps + .filter((p) => !blackList.includes(p.identity)) + .map(PlayerBox), + ], + ], + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/MicMute.js b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/MicMute.js new file mode 100644 index 000000000..469b3982c --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/MicMute.js @@ -0,0 +1,22 @@ +import icons from "../../icons.js"; +import { SimpleToggleButton } from "../ToggleButton.js"; +import { Audio, Widget } from "../../imports.js"; + +export default () => + SimpleToggleButton({ + icon: Widget.Icon({ + connections: [ + [ + Audio, + (icon) => { + icon.icon = Audio.microphone?.isMuted + ? icons.audio.mic.muted + : icons.audio.mic.high; + }, + "microphone-changed", + ], + ], + }), + toggle: () => (Audio.microphone.isMuted = !Audio.microphone.isMuted), + connection: [Audio, () => Audio.microphone?.isMuted], + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Network.js b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Network.js new file mode 100644 index 000000000..a267de142 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Network.js @@ -0,0 +1,77 @@ +import icons from "../../icons.js"; +import { Menu, ArrowToggleButton } from "../ToggleButton.js"; +import { Network, Widget } from "../../imports.js"; + +export const NetworkToggle = () => + ArrowToggleButton({ + name: "network", + icon: Widget.Icon({ + connections: [ + [ + Network, + (icon) => { + icon.icon = Network.wifi?.iconName || ""; + }, + ], + ], + }), + 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?.iconName; + }, + ], + ], + }), + title: Widget.Label("Wifi Selection"), + content: Widget.Box({ + vertical: true, + connections: [ + [ + Network, + (box) => + (box.children = Network.wifi?.accessPoints.map((ap) => + Widget.Button({ + onClicked: `nmcli device wifi connect ${ap.bssid}`, + child: Widget.Box({ + children: [ + Widget.Icon(ap.iconName), + Widget.Label(ap.ssid), + ap.active && + Widget.Icon({ + icon: icons.tick, + hexpand: true, + halign: "end", + }), + ], + }), + }), + )), + ], + ], + }), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Theme.js b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Theme.js new file mode 100644 index 000000000..8332d407c --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Theme.js @@ -0,0 +1,91 @@ +import Theme from "../../services/theme/theme.js"; +import { ArrowToggleButton, Menu, opened } from "../ToggleButton.js"; +import themes from "../../themes.js"; +import icons from "../../icons.js"; +import Separator from "../../misc/Separator.js"; +import { Widget } from "../../imports.js"; + +const prettyName = (name) => + name + .split("_") + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(" "); + +const ThemeIcon = () => + Widget.Stack({ + transition: "crossfade", + items: themes.map(({ name, icon }) => [name, Widget.Label(icon)]), + connections: [ + [Theme, (stack) => (stack.shown = Theme.getSetting("theme"))], + ], + }); + +export const ThemeToggle = () => + ArrowToggleButton({ + name: "theme", + icon: ThemeIcon(), + label: Widget.Label({ + connections: [ + [ + Theme, + (label) => { + label.label = prettyName(Theme.getSetting("theme")); + }, + ], + ], + }), + connection: [opened, () => opened.value === "theme"], + activate: () => opened.setValue("theme"), + activateOnArrow: false, + deactivate: () => {}, + }); + +export const ThemeSelector = () => + Menu({ + name: "theme", + icon: ThemeIcon(), + title: Widget.Label("Theme Selector"), + content: Widget.Box({ + vertical: true, + children: themes + .map(({ name, icon }) => + Widget.Button({ + onClicked: () => Theme.setSetting("theme", name), + child: Widget.Box({ + children: [ + Widget.Label(icon), + Widget.Label(prettyName(name)), + Widget.Icon({ + icon: icons.tick, + hexpand: true, + halign: "end", + connections: [ + [ + Theme, + (icon) => { + icon.visible = + Theme.getSetting( + "theme", + ) === name; + }, + ], + ], + }), + ], + }), + }), + ) + .concat([ + Separator({ orientation: "horizontal" }), + Widget.Button({ + onClicked: () => Theme.openSettings(), + child: Widget.Box({ + children: [ + Widget.Icon(icons.settings), + Widget.Label("Theme Settings"), + ], + }), + }), + ]), + }), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Volume.js b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Volume.js new file mode 100644 index 000000000..dd340d1b4 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/quicksettings/widgets/Volume.js @@ -0,0 +1,212 @@ +import icons from "../../icons.js"; +import FontIcon from "../../misc/FontIcon.js"; +import Separator from "../../misc/Separator.js"; +import { getAudioTypeIcon } from "../../utils.js"; +import { Arrow } from "../ToggleButton.js"; +import { Menu } from "../ToggleButton.js"; +import { Audio, Widget, Utils } from "../../imports.js"; + +const VolumeIndicator = (type = "speaker") => + Widget.Button({ + onClicked: () => (Audio[type].isMuted = !Audio[type].isMuted), + child: Widget.Icon({ + connections: [ + [ + Audio, + (icon) => { + if (!Audio[type]) return; + + icon.icon = + type === "speaker" + ? getAudioTypeIcon(Audio[type].iconName) + : icons.audio.mic.high; + + icon.tooltipText = `Volume ${Math.floor( + Audio[type].volume * 100, + )}%`; + }, + `${type}-changed`, + ], + ], + }), + }); + +const VolumeSlider = (type = "speaker") => + Widget.Slider({ + hexpand: true, + drawValue: false, + onChange: ({ value }) => (Audio[type].volume = value), + connections: [ + [ + Audio, + (slider) => { + slider.value = Audio[type].volume; + }, + `${type}-changed`, + ], + ], + }); + +export const Volume = () => + Widget.Box({ + className: "slider", + children: [ + VolumeIndicator("speaker"), + VolumeSlider("speaker"), + Arrow("sink-selector"), + Widget.Box({ + child: Arrow("app-mixer"), + connections: [ + [ + Audio, + (box) => { + box.visible = Audio.apps.length > 0; + }, + ], + ], + }), + ], + }); + +export const Microphone = () => + Widget.Box({ + className: "slider", + binds: [["visible", Audio, "recorders", (r) => r.length > 0]], + children: [VolumeIndicator("microphone"), VolumeSlider("microphone")], + }); + +const MixerItem = (stream) => + Widget.Box({ + hexpand: true, + className: "mixer-item", + children: [ + Widget.Icon({ + binds: [["tooltipText", stream, "name"]], + connections: [ + [ + stream, + (icon) => { + icon.icon = Utils.lookUpIcon(stream.name) + ? stream.name + : icons.mpris.fallback; + }, + ], + ], + }), + Widget.Box({ + children: [ + Widget.Box({ + vertical: true, + children: [ + Widget.Label({ + xalign: 0, + truncate: "end", + binds: [["label", stream, "description"]], + }), + Widget.Slider({ + hexpand: true, + drawValue: false, + binds: [["value", stream, "volume"]], + onChange: ({ value }) => + (stream.volume = value), + }), + ], + }), + Widget.Label({ + xalign: 1, + connections: [ + [ + stream, + (l) => { + l.label = `${Math.floor( + stream.volume * 100, + )}%`; + }, + ], + ], + }), + ], + }), + ], + }); + +const SinkItem = (stream) => + Widget.Button({ + hexpand: true, + onClicked: () => (Audio.speaker = stream), + child: Widget.Box({ + children: [ + Widget.Icon({ + icon: getAudioTypeIcon(stream.iconName), + tooltipText: stream.iconName, + }), + Widget.Label( + stream.description.split(" ").slice(0, 4).join(" "), + ), + Widget.Icon({ + icon: icons.tick, + hexpand: true, + halign: "end", + connections: [ + [ + "draw", + (icon) => { + icon.visible = Audio.speaker === stream; + }, + ], + ], + }), + ], + }), + }); + +const SettingsButton = () => + Widget.Button({ + onClicked: "pavucontrol", + hexpand: true, + child: Widget.Box({ + children: [Widget.Icon(icons.settings), Widget.Label("Settings")], + }), + }); + +export const AppMixer = () => + Menu({ + name: "app-mixer", + icon: FontIcon(icons.audio.mixer), + title: Widget.Label("App Mixer"), + content: Widget.Box({ + className: "app-mixer", + vertical: true, + children: [ + Widget.Box({ + vertical: true, + binds: [ + ["children", Audio, "apps", (a) => a.map(MixerItem)], + ], + }), + Separator({ orientation: "horizontal" }), + SettingsButton(), + ], + }), + }); + +export const SinkSelector = () => + Menu({ + name: "sink-selector", + icon: Widget.Icon(icons.audio.type.headset), + title: Widget.Label("Sink Selector"), + content: Widget.Box({ + className: "sink-selector", + vertical: true, + children: [ + Widget.Box({ + vertical: true, + binds: [ + ["children", Audio, "speakers", (s) => s.map(SinkItem)], + ], + }), + Separator({ orientation: "horizontal" }), + SettingsButton(), + ], + }), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/screencorner/ScreenCorners.js b/home/isabel/programs/gui/confs/bars/ags/config/js/screencorner/ScreenCorners.js new file mode 100644 index 000000000..9feacb0a2 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/screencorner/ScreenCorners.js @@ -0,0 +1,72 @@ +import Gtk from "gi://Gtk"; +import { Widget } from "../imports.js"; + +const Corner = (place) => + Widget({ + type: Gtk.DrawingArea, + className: "corner", + hexpand: true, + vexpand: true, + halign: place.includes("left") ? "start" : "end", + valign: place.includes("top") ? "start" : "end", + setup: (widget) => widget.set_size_request(32, 32), + connections: [ + [ + "draw", + (widget, cr) => { + const context = widget.get_style_context(); + const c = context.get_property( + "background-color", + Gtk.StateFlags.NORMAL, + ); + const r = context.get_property( + "border-radius", + Gtk.StateFlags.NORMAL, + ); + 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.$dispose(); + }, + ], + ], + }); + +const places = ["topleft", "topright", "bottomleft", "bottomright"]; +export default (monitor) => + places.map((place) => + Widget.Window({ + name: `corner${monitor}${place}`, + monitor, + className: "corner", + anchor: [ + place.includes("top") ? "top" : "bottom", + place.includes("right") ? "right" : "left", + ], + child: Corner(place), + }), + ); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/services/brightness.js b/home/isabel/programs/gui/confs/bars/ags/config/js/services/brightness.js new file mode 100644 index 000000000..d66bd3b3f --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/services/brightness.js @@ -0,0 +1,45 @@ +import { Service, Utils } from "../imports.js"; + +class Brightness extends Service { + static { + Service.register( + this, + {}, + { + screen: ["float", "rw"], + }, + ); + } + + _screen = 0; + + get screen() { + return this._screen; + } + + set screen(percent) { + 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(); + try { + this._screen = + Number(Utils.exec("brightnessctl g")) / + Number(Utils.exec("brightnessctl m")); + } catch (error) { + console.error("missing dependancy: brightnessctl"); + } + } +} + +export default new Brightness(); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/services/onScreenIndicator.js b/home/isabel/programs/gui/confs/bars/ags/config/js/services/onScreenIndicator.js new file mode 100644 index 000000000..9b621d0b5 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/services/onScreenIndicator.js @@ -0,0 +1,46 @@ +import { Service, Utils } from "../imports.js"; +import icons from "../icons.js"; +import { getAudioTypeIcon } from "../utils.js"; +import { Audio } from "../imports.js"; +import Brightness from "./brightness.js"; + +class Indicator extends Service { + static { + Service.register(this, { + popup: ["double", "string"], + }); + } + + _delay = 1500; + _count = 0; + + 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, + getAudioTypeIcon(Audio.speaker.iconName), + ); + } + + display() { + // brightness is async, so lets wait a bit + Utils.timeout(10, () => + this.popup(Brightness.screen, icons.brightness.screen), + ); + } + + connectWidget(widget, callback) { + Utils.connect(this, widget, callback, "popup"); + } +} + +export default new Indicator(); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/services/powermenu.js b/home/isabel/programs/gui/confs/bars/ags/config/js/services/powermenu.js new file mode 100644 index 000000000..22ba327e9 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/services/powermenu.js @@ -0,0 +1,38 @@ +import { App, Service } from "../imports.js"; + +class PowerMenu extends Service { + static { + Service.register( + this, + {}, + { + title: ["string"], + cmd: ["string"], + }, + ); + } + + get title() { + return this._title || ""; + } + get cmd() { + return this._cmd || ""; + } + + 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/isabel/programs/gui/confs/bars/ags/config/js/services/theme/hyprland.js b/home/isabel/programs/gui/confs/bars/ags/config/js/services/theme/hyprland.js new file mode 100644 index 000000000..acb782ee7 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/services/theme/hyprland.js @@ -0,0 +1,36 @@ +import { App, Utils } from "../../imports.js"; + +const noAlphaignore = ["verification", "powermenu"]; + +export default function () { + try { + App.connect("config-parsed", () => { + for (const [name] of App.windows) { + Utils.execAsync([ + "hyprctl", + "keyword", + "layerrule", + `unset, ${name}`, + ]).then(() => { + Utils.execAsync([ + "hyprctl", + "keyword", + "layerrule", + `blur, ${name}`, + ]); + if (!noAlphaignore.every((skip) => !name.includes(skip))) + return; + + Utils.execAsync([ + "hyprctl", + "keyword", + "layerrule", + `ignorealpha 0.6, ${name}`, + ]); + }); + } + }); + } catch (error) { + console.error(error); + } +} diff --git a/home/isabel/programs/gui/confs/bars/ags/config/theme/scss.js b/home/isabel/programs/gui/confs/bars/ags/config/js/services/theme/scss.js similarity index 52% rename from home/isabel/programs/gui/confs/bars/ags/config/theme/scss.js rename to home/isabel/programs/gui/confs/bars/ags/config/js/services/theme/scss.js index fc7b479a9..eba10eeed 100644 --- a/home/isabel/programs/gui/confs/bars/ags/config/theme/scss.js +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/services/theme/scss.js @@ -1,9 +1,9 @@ -import { execAsync, writeFile } from 'resource:///com/github/Aylur/ags/utils.js'; +import { Utils, App } from "../../imports.js"; -const generated = str => `// THIS FILE IS GENERATED +const generated = (str) => `// THIS FILE IS GENERATED ${str}`; -const scss = t => `$theme: '${t.color_scheme}'; +const scss = (t) => `$theme: '${t.color_scheme}'; $red: ${t.red}; $green: ${t.green}; @@ -24,7 +24,10 @@ $spacing: ${t.spacing}px; $accent: ${t.accent}; $accent_fg: ${t.accent_fg}; -$hover: transparentize(${t.widget_bg}, ${Math.max((t.widget_opacity * 0.90) / 100, 0)}); +$hover: transparentize(${t.widget_bg}, ${Math.max( + (t.widget_opacity * 0.9) / 100, + 0, +)}); $widget_bg: transparentize(${t.widget_bg}, ${t.widget_opacity / 100}); $active_gradient: linear-gradient(${t.active_gradient}); @@ -37,30 +40,38 @@ $text_shadow: 2px 2px 2px $shadow; $icon_shadow: 2px 2px $shadow; $popover_radius: ${t.radii * 1.7}px; -$popover_border_color: transparentize(${t.border_color}, ${Math.max((t.border_opacity - 1) / 100, 0)}); +$popover_border_color: transparentize(${t.border_color}, ${Math.max( + (t.border_opacity - 1) / 100, + 0, +)}); $popover_padding: ${t.spacing * 1.8}px; $drop_shadow: ${t.drop_shadow}; $transition: ${t.transition}ms; -$font_size: 16px; -$font: 'Ubuntu Nerd Font'; -$mono_font: 'Mononoki Nerd Font', monospace; -$wallpaper_fg: white; +$font_size: ${t.font_size}px; +$font: '${t.font}'; +$mono_font: '${t.mono_font}', monospace; +$wallpaper_fg: ${t.wallpaper_fg}; $shader_fg: white; -$screen_corners: ${t.bar_style === 'normal' && t.screen_corners}; +$screen_corners: ${t.bar_style === "normal" && t.screen_corners}; $bar_style: ${t.bar_style}; $layout: ${t.layout};`; -export async function setupScss(theme) { - const path = ags.App.configDir; +export default async function (theme) { + const tmp = "/tmp/ags/scss"; + Utils.ensureDirectory(tmp); try { - await writeFile(generated(scss(theme)), `${path}/scss/generated.scss`); - await execAsync(['sassc', `${path}/scss/main.scss`, `${path}/style.css`]); - ags.App.resetCss(); - ags.App.applyCss(`${path}/style.css`); + await Utils.writeFile(generated(scss(theme)), `${tmp}/generated.scss`); + await Utils.writeFile( + generated(theme.additional_scss || ""), + `${tmp}/additional.scss`, + ); + Utils.exec(`sassc ${App.configDir}/scss/main.scss ${tmp}/style.css`); + App.resetCss(); + App.applyCss(`${tmp}/style.css`); } catch (error) { - logError(error); + console.error(error); } } diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/services/theme/theme.js b/home/isabel/programs/gui/confs/bars/ags/config/js/services/theme/theme.js new file mode 100755 index 000000000..fe7339729 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/services/theme/theme.js @@ -0,0 +1,130 @@ +import themes from "../../themes.js"; +import setupScss from "./scss.js"; +import setupHyprland from "./hyprland.js"; +import SettingsDialog from "../../settingsdialog/SettingsDialog.js"; +import IconBrowser from "../../misc/IconBrowser.js"; +import { Service, Utils } from "../../imports.js"; + +const THEME_CACHE = Utils.CACHE_DIR + "/theme-overrides.json"; + +class ThemeService extends Service { + static { + Service.register(this); + } + + get themes() { + return themes; + } + + _defaultAvatar = `/home/${Utils.USER}/media/pictures/pfps/avatar`; + _defaultTheme = themes[0].name; + + constructor() { + super(); + try { + Utils.exec("swww init"); + } catch (error) { + print("missing dependancy: swww"); + } + this.setup(); + } + + openSettings() { + if (!this._dialog) this._dialog = SettingsDialog(); + + this._dialog.hide(); + this._dialog.present(); + } + + iconBrowser() { + IconBrowser(); + } + + getTheme() { + return themes.find(({ name }) => name === this.getSetting("theme")); + } + + setup() { + const theme = { + ...this.getTheme(), + ...this.settings, + }; + setupScss(theme); + setupHyprland(); + this.setupOther(); + this.setupWallpaper(); + } + + reset() { + Utils.exec(`rm ${THEME_CACHE}`); + this._settings = null; + this.setup(); + this.emit("changed"); + } + + setupOther() { + const darkmode = this.getSetting("color_scheme") === "dark"; + + if (Utils.exec("which gsettings")) { + const gsettings = + "gsettings set org.gnome.desktop.interface color-scheme"; + Utils.execAsync( + `${gsettings} "prefer-${darkmode ? "dark" : "light"}"`, + ).catch(print); + } + } + + setupWallpaper() { + Utils.execAsync(["swww", "img", this.getSetting("wallpaper")]).catch( + (err) => console.error(err), + ); + } + + get settings() { + if (this._settings) return this._settings; + + try { + this._settings = JSON.parse(Utils.readFile(THEME_CACHE)); + } catch (_) { + this._settings = {}; + } + + return this._settings; + } + + setSetting(prop, value) { + const settings = this.settings; + settings[prop] = value; + Utils.writeFile(JSON.stringify(settings, null, 2), THEME_CACHE).catch( + (err) => console.error(err), + ); + this._settings = settings; + this.emit("changed"); + + if (prop === "layout") { + if (!this._notiSent) { + this._notiSent = true; + Utils.execAsync([ + "notify-send", + "Layout Change Needs a Reload", + ]); + } + return; + } + + this.setup(); + } + + getSetting(prop) { + if (prop === "theme") return this.settings.theme || this._defaultTheme; + + if (prop === "avatar") + return this.settings.avatar || this._defaultAvatar; + + return this.settings[prop] !== undefined + ? this.settings[prop] + : this.getTheme()[prop]; + } +} + +export default new ThemeService(); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/settingsdialog/SettingsDialog.js b/home/isabel/programs/gui/confs/bars/ags/config/js/settingsdialog/SettingsDialog.js new file mode 100644 index 000000000..8d36bea87 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/settingsdialog/SettingsDialog.js @@ -0,0 +1,352 @@ +import Gtk from "gi://Gtk"; +import Theme from "../services/theme/theme.js"; +import themes from "../themes.js"; +import Wallpaper from "../misc/Wallpaper.js"; +import { Widget, Variable } from "../imports.js"; + +const Row = (title, child) => + Widget.Box({ + className: "row", + children: [Widget.Label(`${title}: `), child], + }); + +const Img = (title, prop) => + Row( + title, + Widget({ + title, + type: Gtk.FileChooserButton, + hexpand: true, + halign: "end", + connections: [ + [ + "selection-changed", + (w) => + Theme.setSetting( + prop, + w.get_uri().replace("file://", ""), + ), + ], + ], + }), + ); + +const SpinButton = (title, prop, max = 100, min = 0) => + Row( + title, + Widget({ + type: Gtk.SpinButton, + setup: (w) => { + w.set_range(min, max); + w.set_increments(1, 1); + }, + hexpand: true, + halign: "end", + connections: [ + [ + "value-changed", + (b) => !b._block && Theme.setSetting(prop, b.value), + ], + [ + Theme, + (b) => { + b._block = true; + b.value = Theme.getSetting(prop); + b._block = false; + }, + ], + ], + }), + ); + +const SwitchButton = (title, prop) => + Row( + title, + Widget({ + type: Gtk.Switch, + halign: "end", + hexpand: true, + connections: [ + [ + Theme, + (s) => { + s._block = true; + s.active = Theme.getSetting(prop); + s._block = false; + }, + ], + [ + "notify::active", + (s) => !s._block && Theme.setSetting(prop, s.active), + ], + ], + }), + ); + +const Color = (title, prop) => + Row( + title, + Widget.Box({ + hexpand: true, + halign: "end", + className: "color", + children: [ + Widget.Entry({ + onAccept: ({ text }) => Theme.setSetting(prop, text), + valign: "center", + connections: [ + [Theme, (w) => (w.text = Theme.getSetting(prop))], + ], + }), + Widget({ + type: Gtk.ColorButton, + alpha: true, + valign: "center", + connections: [ + [ + "color-set", + (w) => { + w.get_parent().children[0].set_text( + w.rgba.to_string(), + ); + Theme.setSetting(prop, w.rgba.to_string()); + }, + ], + ], + }), + ], + }), + ); + +const Text = (title, prop) => + Row( + title, + Widget.Entry({ + className: "text", + hexpand: true, + halign: "end", + connections: [[Theme, (w) => (w.text = Theme.getSetting(prop))]], + onAccept: ({ text }) => Theme.setSetting(prop, text), + }), + ); + +const TextSpinButton = (title, prop, list) => + Row( + title, + Widget.Box({ + className: "text-spin", + hexpand: true, + halign: "end", + properties: [ + ["values", list], + [ + "step", + (box, step) => { + const label = box.get_children()[0]; + const max = box._values.length - 1; + let index = box._values.indexOf(label.label) + step; + + if (index > max) index = 0; + + if (index < 0) index = max; + + const value = box._values[index]; + label.label = value; + Theme.setSetting(prop, value); + }, + ], + ], + children: [ + Widget.Label({ + connections: [ + [ + Theme, + (label) => (label.label = Theme.getSetting(prop)), + ], + ], + }), + Widget.Button({ + child: Widget.Icon("pan-down-symbolic"), + onClicked: (btn) => { + const box = btn.get_parent(); + box._step(box, -1); + }, + }), + Widget.Button({ + child: Widget.Icon("pan-up-symbolic"), + onClicked: (btn) => { + const box = btn.get_parent(); + box._step(box, +1); + }, + }), + ], + }), + ); + +const FontButton = (title, prop) => + Row( + title, + Widget({ + type: Gtk.FontButton, + hexpand: true, + halign: "end", + useSize: false, + showSize: false, + fontName: Theme.getSetting(prop), + connections: [ + [ + "font-set", + ({ fontName }) => { + Theme.setSetting(prop, fontName); + }, + ], + ], + }), + ); + +const page = Variable("󰒓 General"); +const showPage = (p) => (page.value = p); + +const Tab = (name) => + Widget.Button({ + hexpand: true, + className: "tab", + onClicked: () => showPage(name), + child: Widget.Label(name), + connections: [ + [page, (b) => b.toggleClassName("active", page.value === name)], + ], + }); + +const Layout = (pages) => + Widget.Box({ + vertical: true, + className: "settings", + hexpand: false, + children: [ + Widget.Box({ + className: "headerbar", + valign: "start", + child: Widget.Box({ + className: "tabs", + children: [ + ...Object.keys(pages).map((page) => Tab(page)), + Widget.Button({ + className: "tab", + onClicked: () => Theme.reset(), + child: Widget.Label("󰦛 Reset"), + hexpand: true, + }), + ], + }), + }), + Widget.Box({ + className: "content", + child: Widget.Stack({ + transition: "slide_left_right", + items: Object.keys(pages).map((page) => [ + page, + pages[page], + ]), + binds: [["shown", page]], + }), + }), + Widget.Label({ + wrap: true, + className: "disclaimer", + label: + "These settings override all preset themes. " + + "To make them permanent: edit ~/.config/ags/theme/themes.js", + }), + ], + }); + +const Page = (children) => + Widget.Scrollable({ + child: Widget.Box({ + vertical: true, + children, + }), + }); + +export default () => + Widget({ + type: Gtk.Window, + name: "settings", + child: Layout({ + "󰒓 General": Page([ + Wallpaper({ + className: "row", + hexpand: true, + vexpand: true, + }), + Img("Wallpaper", "wallpaper"), + Img("Avatar", "avatar"), + SpinButton("Useless Gaps", "wm_gaps", 128), + SpinButton("Spacing", "spacing", 18), + SpinButton("Roundness", "radii", 36), + // TextSpinButton('Layout', 'layout', ['topbar', 'bottombar']), + TextSpinButton("Bar Style", "bar_style", [ + "normal", + "floating", + "separated", + ]), + SwitchButton("Screen Corners", "screen_corners"), + ]), + "󰏘 Colors": Page([ + TextSpinButton("Color Theme", "color_scheme", [ + "light", + "dark", + ]), + ...[ + "Red", + "Green", + "Yellow", + "Blue", + "Magenta", + "Teal", + "Orange", + ].map((c) => Color(c, c.toLowerCase())), + ]), + "󰃟 Theme": Page([ + TextSpinButton( + "Theme", + "theme", + themes.map((t) => t.name), + ), + Color("Background Color", "bg_color"), + Color("Foreground Color", "fg_color"), + Color("Hovered Foreground Color", "hover_fg"), + Text("Hyprland Active Border Color", "hypr_active_border"), + Text("Hyprland Inactive Border Color", "hypr_inactive_border"), + Color("Accent Color", "accent"), + Color("Accent Foreground", "accent_fg"), + Text("Active Gradient", "active_gradient"), + Color("Widget Background", "widget_bg"), + SpinButton("Widget Opacity", "widget_opacity"), + Color("Border Color", "border_color"), + SpinButton("Border Width", "border_width"), + SpinButton("Border Opacity", "border_opacity"), + ]), + "󰠱 Miscellaneous": Page([ + Color("Shadow", "shadow"), + SwitchButton("Drop Shadow", "drop_shadow"), + SpinButton("Transition", "transition", 1000), + Text("Desktop Clock Position", "desktop_clock"), + Color("Wallpaper Foreground Color", "wallpaper_fg"), + FontButton("Font", "font"), + FontButton("Mono Font", "mono_font"), + SpinButton("Font Size", "font_size"), + ]), + }), + connections: [ + [ + "delete-event", + (win) => { + win.hide(); + return true; + }, + ], + ], + setup: (win) => win.set_default_size(700, 600), + }); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/themes.js b/home/isabel/programs/gui/confs/bars/ags/config/js/themes.js new file mode 100644 index 000000000..0e6087e49 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/themes.js @@ -0,0 +1,79 @@ +import { Utils } from "./imports.js"; + +const WP = `/home/${Utils.USER}/media/pictures/wallpapers/`; + +const mocha_colors = { + bg_color: "#1e1e2e", + fg_color: "#cdd6f4", + hover_fg: "#cdd6f4", + red: "#f38ba8", + green: "#a6e3a1", + yellow: "#f9e2af", + blue: "#74c7ec", + magenta: "#cba6f7", + teal: "#94e2d5", + orange: "#fab387", +}; + +const latte_colors = { + bg_color: "#eff1f5", + fg_color: "#4c4f69", + hover_fg: "#4c4f69", + red: "#d20f39", + green: "#40a02b", + yellow: "#df8e1d", + blue: "#209fb5", + magenta: "#8839ef", + teal: "#179299", + orange: "#fe640b", +}; + +const settings = { + wm_gaps: 8, + radii: 9, + spacing: 9, + drop_shadow: true, + transition: 200, + screen_corners: false, + bar_style: "floating", + layout: "topbar", + border_opacity: 97, + border_width: 1, + widget_opacity: 94, + font: "Ubuntu Nerd Font", + mono_font: "Mononoki Nerd Font", + font_size: 16, +}; + +const misc_colors = { + wallpaper_fg: "white", + shadow: "rgba(0, 0, 0, .6)", + accent: "$blue", + accent_fg: "$bg_color", + widget_bg: "$fg_color", + active_gradient: "to right, $accent, lighten($accent, 6%)", + border_color: "$fg_color", +}; + +// themes +const mocha = { + wallpaper: WP + "tempest.png", + name: "mocha", + color_scheme: "dark", + icon: "", + ...mocha_colors, + ...settings, + ...misc_colors, +}; + +const latte = { + wallpaper: WP + "coke.jpg", + name: "latte", + color_scheme: "light", + icon: "", + ...latte_colors, + ...settings, + ...misc_colors, +}; + +export default [mocha, latte]; diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/utils.js b/home/isabel/programs/gui/confs/bars/ags/config/js/utils.js new file mode 100644 index 000000000..b58d92adf --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/utils.js @@ -0,0 +1,107 @@ +import Cairo from "cairo"; +import options from "./options.js"; +import icons from "./icons.js"; +import Theme from "./services/theme/theme.js"; +import { Utils, App, Battery, Mpris, Audio } from "./imports.js"; + +/** @type {function((id: number) => typeof Gtk.Widget): typeof Gtk.Widget[]}*/ +export function forMonitors(widget) { + const ws = JSON.parse(Utils.exec("hyprctl -j monitors")); + return ws.map((/** @type {Record} */ mon) => + widget(mon.id), + ); +} + +export function range(length, start = 1) { + return Array.from({ length }, (_, i) => i + start); +} + +export function substitute(collection, item) { + return collection.find(([from]) => from === item)?.[1] || item; +} + +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; +} + +export function warnOnLowBattery() { + const { low } = options.battaryBar; + Battery.connect("notify::percent", () => { + if (Battery.percent === low || Battery.percent === low / 2) { + Utils.execAsync([ + "notify-send", + `${Battery.percent}% Battery Percentage`, + "-i", + icons.battery.warning, + "-u", + "critical", + ]); + } + }); +} + +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], + ]; + + for (const [from, to] of substitues) { + if (from === icon) return to; + } + + return icon; +} + +export function scssWatcher() { + return Utils.subprocess( + [ + "inotifywait", + "--recursive", + "--event", + "create,modify", + "-m", + App.configDir + "/scss", + ], + () => Theme.setup(), + () => print("missing dependancy for css hotreload: inotify-tools"), + ); +} + +export function activePlayer() { + let active; + globalThis.mpris = () => active || Mpris.players[0]; + Mpris.connect("player-added", (mpris, bus) => { + mpris.getPlayer(bus)?.connect("changed", (player) => { + active = player; + }); + }); +} + +export async function globalServices() { + globalThis.audio = Audio; + globalThis.ags = await import("./imports.js"); + globalThis.brightness = (await import("./services/brightness.js")).default; + globalThis.indicator = ( + await import("./services/onScreenIndicator.js") + ).default; + globalThis.theme = (await import("./services/theme/theme.js")).default; +} + +export function launchApp(app) { + Utils.execAsync(`hyprctl dispatch exec ${app.executable}`); + app.frequency += 1; +} diff --git a/home/isabel/programs/gui/confs/bars/ags/config/js/variables.js b/home/isabel/programs/gui/confs/bars/ags/config/js/variables.js new file mode 100755 index 000000000..31ccc7661 --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/ags/config/js/variables.js @@ -0,0 +1,81 @@ +import options from "./options.js"; +import { Variable, Utils } from "./imports.js"; + +export const uptime = Variable("", { + poll: [ + 60_000, + "cat /proc/uptime", + (line) => { + const uptime = Number.parseInt(line.split(".")[0]) / 60; + const h = Math.floor(uptime / 60); + const s = Math.floor(uptime % 60); + return `${h}:${s < 10 ? "0" + s : s}`; + }, + ], +}); + +export const distro = Utils.exec("cat /etc/os-release") + .split("\n") + .find((line) => line.startsWith("ID")) + .split("=")[1]; + +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 ""; + } +})(); + +const divide = ([total, free]) => free / total; +export const cpu = Variable(0, { + poll: [ + options.systemFetchInterval, + "top -b -n 1", + (out) => + divide([ + 100, + out + .split("\n") + .find((line) => line.includes("Cpu(s)")) + ?.split(/\s+/)[1] + .replace(",", "."), + ]), + ], +}); + +export const ram = Variable(0, { + poll: [ + options.systemFetchInterval, + "free", + (out) => + divide( + out + .split("\n") + .find((line) => line.includes("Mem:")) + ?.split(/\s+/) + .splice(1, 2), + ), + ], +}); + +export const temp = Variable(0, { + poll: [ + options.systemFetchInterval, + "cat " + options.temperature, + (n) => n / 100_000, + ], +}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/layouts/leftbar.js b/home/isabel/programs/gui/confs/bars/ags/config/layouts/leftbar.js deleted file mode 100644 index a0e00762f..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/layouts/leftbar.js +++ /dev/null @@ -1,46 +0,0 @@ -import * as shared from './shared.js'; -import { Launcher } from './shared.js'; -import { Workspaces } from './widgets/hyprland.js'; -import { Separator } from '../modules/misc.js'; -import { PanelIndicator as MediaIndicator } from './widgets/media.js'; -import { PanelIndicator as NotificationIndicator } from './widgets/notifications.js'; -import { DistroIcon } from '../modules/misc.js'; -import { PanelButton as ColorPicker } from '../modules/colorpicker.js'; -import { PanelButton as PowerMenu } from './widgets/powermenu.js'; -import { PanelButton as DashBoard } from './widgets/dashboard.js'; -import { PanelButton as QuickSettings } from './widgets/quicksettings.js'; - -const Bar = monitor => shared.Bar({ - anchor: 'top left bottom', - vertical: true, - monitor, - start: [ - Launcher({ child: DistroIcon() }), - Workspaces({ vertical: true }), - // MediaIndicator({ hexpand: false, halign: 'end' }), - ], - center: [ - DashBoard({ format: '%I\n܅\n%M' }), - ], - end: [ - // NotificationIndicator({ direction: 'right', hexpand: false, halign: 'start' }), - // ags.Widget.Box({ hexpand: true }), - ColorPicker(), - Separator({ valign: 'center' }), - QuickSettings({ vertical: true }), - Separator({ valign: 'center' }), - PowerMenu(), - ], -}); - -export default monitors => ([ - ...monitors.map(monitor => [ - Bar(monitor), - shared.Notifications(monitor, 'slide_down', 'top'), - shared.Desktop(monitor), - ...shared.Corners(monitor), - shared.OSDIndicator(monitor), - ]), - shared.Quicksettings({ position: 'bottom left' }), - shared.Dashboard({ position: 'left' }), -]).flat(2); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/layouts/shared.js b/home/isabel/programs/gui/confs/bars/ags/config/layouts/shared.js deleted file mode 100644 index 18d7748d2..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/layouts/shared.js +++ /dev/null @@ -1,113 +0,0 @@ -const { Window, CenterBox, Box, Button } = ags.Widget; -import { Corner } from '../modules/corner.js'; -import { OnScreenIndicator } from '../modules/onscreenindicator.js'; -import { Applauncher } from '../modules/applauncher.js'; -import { PopupLayout } from './widgets/popuplayout.js'; -import { Desktop as DesktopWidget } from './widgets/desktop.js'; -import * as dashboard from './widgets/dashboard.js'; -import * as quicksettings from './widgets/quicksettings.js'; -import * as powermenu from './widgets/powermenu.js'; -import * as notifications from '../modules/notifications.js'; - -// bar -export const Launcher = ({ child }) => Button({ - className: 'launcher panel-button', - connections: [[ags.App, (btn, win, visible) => { - btn.toggleClassName('active', win === 'applauncher' && visible); - }]], - onClicked: () => ags.App.toggleWindow('applauncher'), - child: Box({ children: [child] }), -}); - -export const Bar = ({ vertical, start, center, end, anchor, monitor }) => Window({ - name: `bar${monitor}`, - exclusive: true, - monitor, - anchor, - child: CenterBox({ - className: 'panel', - vertical, - startWidget: Box({ children: start, vertical, className: 'start' }), - centerWidget: Box({ children: center, vertical, className: 'center' }), - endWidget: Box({ children: end, vertical, className: 'end', valign: 'end' }), - }), -}); - -// static -export const Notifications = (monitor, transition, anchor) => Window({ - monitor, - name: `notifications${monitor}`, - anchor, - child: notifications.PopupList({ transition }), -}); - - -export const Desktop = monitor => Window({ - monitor, - name: `desktop${monitor}`, - className: 'desktop', - anchor: ['top', 'bottom', 'left', 'right'], - child: DesktopWidget(), - layer: 'background', -}); - -export const Corners = ( - monitor, - places = ['topleft', 'topright', 'bottomleft', 'bottomright'], -) => places.map(place => Window({ - name: `corner${monitor}${place}`, - monitor, - className: 'corner', - anchor: [place.includes('top') ? 'top' : 'bottom', place.includes('right') ? 'right' : 'left'], - child: Corner(place), -})); - -export const OSDIndicator = monitor => Window({ - name: `indicator${monitor}`, - monitor, - className: 'indicator', - layer: 'overlay', - anchor: ['right'], - child: OnScreenIndicator(), -}); - -//popups -const Popup = (name, child) => Window({ - name, - popup: true, - focusable: false, - layer: 'overlay', - child: PopupLayout({ - layout: 'center', - window: name, - child: child(), - }), -}); - -export const ApplauncherPopup = () => Popup('applauncher', Applauncher); -export const PowermenuPopup = () => Popup('powermenu', powermenu.PopupContent); -export const VerificationPopup = () => Popup('verification', powermenu.Verification); - -export const Dashboard = ({ position }) => Window({ - name: 'dashboard', - popup: true, - focusable: false, - anchor: position, - child: PopupLayout({ - layout: position, - window: 'dashboard', - child: dashboard.PopupContent(), - }), -}); - -export const Quicksettings = ({ position }) => Window({ - name: 'quicksettings', - popup: true, - focusable: false, - anchor: position, - child: PopupLayout({ - layout: position, - window: 'quicksettings', - child: quicksettings.PopupContent(), - }), -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/layouts/topbar.js b/home/isabel/programs/gui/confs/bars/ags/config/layouts/topbar.js deleted file mode 100644 index 386b8f0bb..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/layouts/topbar.js +++ /dev/null @@ -1,45 +0,0 @@ -import * as shared from './shared.js'; -import { Launcher } from './shared.js'; -import { Workspaces } from './widgets/hyprland.js'; -import { Separator } from '../modules/misc.js'; -import { PanelIndicator as MediaIndicator } from './widgets/media.js'; -import { PanelIndicator as NotificationIndicator } from './widgets/notifications.js'; -import { DistroIcon } from '../modules/misc.js'; -import { PanelButton as ColorPicker } from '../modules/colorpicker.js'; -import { PanelButton as PowerMenu } from './widgets/powermenu.js'; -import { PanelButton as DashBoard } from './widgets/dashboard.js'; -import { PanelButton as QuickSettings } from './widgets/quicksettings.js'; - -const Bar = monitor => shared.Bar({ - anchor: 'top left right', - monitor, - start: [ - Launcher({ child: DistroIcon() }), - Workspaces(), - MediaIndicator({ hexpand: true, halign: 'end' }), - ], - center: [ - DashBoard(), - ], - end: [ - NotificationIndicator({ direction: 'right', hexpand: true, halign: 'start' }), - ags.Widget.Box({ hexpand: true }), - ColorPicker(), - Separator({ valign: 'center' }), - QuickSettings(), - Separator({ valign: 'center' }), - PowerMenu(), - ], -}); - -export default monitors => ([ - ...monitors.map(monitor => [ - Bar(monitor), - shared.Notifications(monitor, 'slide_down', 'top'), - shared.Desktop(monitor), - ...shared.Corners(monitor), - shared.OSDIndicator(monitor), - ]), - shared.Quicksettings({ position: 'top right' }), - shared.Dashboard({ position: 'top' }), -]).flat(2); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/dashboard.js b/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/dashboard.js deleted file mode 100644 index c972f7668..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/dashboard.js +++ /dev/null @@ -1,47 +0,0 @@ -import { Clock } from '../../modules/clock.js'; -import { Separator } from '../../modules/misc.js'; -import { Wallpaper } from '../../modules/wallpaper.js'; -import * as datemenu from './datemenu.js'; -import * as notifications from './notifications.js'; -const { App } = ags; -const { Button, Box } = ags.Widget; - - -export const PanelButton = ({ format } = {}) => Button({ - className: 'dashboard panel-button', - onClicked: () => App.toggleWindow('dashboard'), - connections: [[App, (btn, win, visible) => { - btn.toggleClassName('active', win === 'dashboard' && visible); - }]], - child: Clock({ - format, - justification: 'center', - }), -}); - -export const PopupContent = () => Box({ - className: 'dashboard', - vexpand: false, - children: [ - Box({ - vertical: true, - children: [datemenu.PopupContent()], - }), - Separator({ vexpand: true }), - Box({ - className: 'notifications', - vertical: true, - children: [ - notifications.Header(), - Box({ - className: 'notification-list-box', - children: [ - Wallpaper({ - children: [notifications.List()], - }), - ], - }), - ], - }), - ], -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/datemenu.js b/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/datemenu.js deleted file mode 100644 index 754df6987..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/datemenu.js +++ /dev/null @@ -1,27 +0,0 @@ -import { Clock, Uptime } from '../../modules/clock.js'; -const { Box, Label } = ags.Widget; - -export const PopupContent = props => Box({ - ...props, - vertical: true, - className: 'datemenu', - children: [ - Clock({ format: '%I:%M' }), - Box({ - className: 'uptime-box', - halign: 'center', - children: [ - Label('uptime'), - Uptime(), - ], - }), - Box({ - className: 'calendar', - children: [ - ags.Widget({ - type: imports.gi.Gtk.Calendar, - }), - ], - }), - ], -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/desktop.js b/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/desktop.js deleted file mode 100644 index dd123e1f9..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/desktop.js +++ /dev/null @@ -1,48 +0,0 @@ -import { Separator } from '../../modules/misc.js'; -const { Theme, System } = ags.Service; -const { MenuItem, Menu, Box, Label, Icon, EventBox, CenterBox } = ags.Widget; - -export const Desktop = props => EventBox({ - ...props, - onSecondaryClick: (_, event) => Menu({ - className: 'desktop', - children: [ - MenuItem({ - child: Box({ - children: [ - Icon('system-shutdown-symbolic'), - Label({ - label: 'System', - hexpand: true, - xalign: 0, - }), - ], - }), - submenu: Menu({ - children: [ - Item('Shutdown', 'system-shutdown-symbolic', () => System.action('Shutdown')), - Item('Log Out', 'system-log-out-symbolic', () => System.action('Log Out')), - Item('Reboot', 'system-reboot-symbolic', () => System.action('Log Out')), - Item('Sleep', 'weather-clear-night-symbolic', () => System.action('Log Out')), - ], - }), - }), - MenuItem({ className: 'separator' }), - Item('Settings', 'org.gnome.Settings-symbolic', Theme.openSettings), - ], - }).popup_at_pointer(event), - onMiddleClick: print, - child: Box({ - vertical: true, - vexpand: true, - hexpand: true, - connections: [[Theme, box => { - const [halign = 'center', valign = 'center', offset = 64] = - Theme.getSetting('desktop_clock')?.split(' ') || []; - - box.halign = imports.gi.Gtk.Align[halign.toUpperCase()]; - box.valign = imports.gi.Gtk.Align[valign.toUpperCase()]; - box.setStyle(`margin: ${Number(offset)}px;`); - }]], - }), -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/hyprland.js b/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/hyprland.js deleted file mode 100644 index cb34418e9..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/hyprland.js +++ /dev/null @@ -1,21 +0,0 @@ -import * as hyprland from '../../modules/hyprland.js'; -const { Box, EventBox, Button } = ags.Widget; -const { execAsync } = ags.Utils; - -export const Workspaces = ({ props, vertical }) => Box({ - ...props, - className: 'workspaces panel-button', - children: [Box({ - children: [EventBox({ - className: 'eventbox', - child: hyprland.Workspaces({ - vertical, - indicator: () => Box({ - className: 'indicator', - valign: 'center', - children: [Box({ className: 'fill' })], - }), - }), - })], - })], -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/media.js b/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/media.js deleted file mode 100644 index 964aafcc9..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/media.js +++ /dev/null @@ -1,149 +0,0 @@ -import { HoverRevealer } from '../../modules/misc.js'; -import * as mpris from '../../modules/mpris.js'; -const { Box, CenterBox, Label } = ags.Widget; -const { Mpris } = ags.Service; -const { timeout } = ags.Utils; - -export const MediaBox = ({ player = mpris.prefer, ...props }) => mpris.MprisBox({ - ...props, - className: 'mediabox', - player, - children: [ - mpris.BlurredCoverArt({ - player, - className: 'cover-art-bg', - hexpand: true, - children: [Box({ - className: 'shader', - hexpand: true, - vertical: true, - children: [ - Box({ - children: [ - mpris.CoverArt({ - player, - className: 'cover-art', - halign: 'end', - hexpand: false, - }), - Box({ - hexpand: true, - vertical: true, - className: 'labels', - children: [ - mpris.TitleLabel({ - player, - className: 'title', - xalign: 0, - justification: 'left', - wrap: true, - }), - mpris.ArtistLabel({ - player, - className: 'artist', - xalign: 0, - justification: 'left', - wrap: true, - }), - ], - }), - ], - }), - mpris.PositionSlider({ - className: 'position-slider', - player, - }), - CenterBox({ - className: 'footer-box', - children: [ - Box({ - children: [ - mpris.PositionLabel({ player }), - mpris.Slash({ player }), - mpris.LengthLabel({ player }), - ], - }), - Box({ - className: 'controls', - children: [ - mpris.ShuffleButton({ player }), - mpris.PreviousButton({ player }), - mpris.PlayPauseButton({ player }), - mpris.NextButton({ player }), - mpris.LoopButton({ player }), - ], - }), - mpris.PlayerIcon({ - player, - hexpand: true, - halign: 'end', - }), - ], - }), - ], - })], - }), - ], -}); - -export const PopupContent = props => Box({ - vertical: true, - className: 'media', - ...props, - properties: [['players', new Map()]], - connections: [ - [Mpris, (box, busName) => { - if (!busName || box._players.has(busName)) - return; - - const widget = MediaBox({ player: busName }); - box._players.set(busName, widget); - box.add(widget); - widget.show(); - }, 'player-added'], - ], -}); - -export const PanelIndicator = ({ - player = mpris.prefer, - direction = 'left', - onPrimaryClick = () => Mpris.getPlayer(player)?.playPause(), - ...props -} = {}) => mpris.MprisBox({ - ...props, - className: 'media panel-button', - player, - children: [HoverRevealer({ - direction, - onPrimaryClick, - onScrollUp: () => Mpris.getPlayer(player)?.next(), - onScrollDown: () => Mpris.getPlayer(player)?.previous(), - onSecondaryClick: () => Mpris.getPlayer(player)?.playPause(), - indicator: mpris.PlayerIcon({ - player, - className: 'icon', - symbolic: true, - }), - child: Box({ - children: [ - mpris.ArtistLabel({ player }), - Label(' - '), - mpris.TitleLabel({ player }), - ], - }), - connections: [[Mpris, revealer => { - const mpris = Mpris.getPlayer(player); - if (!mpris) - return; - - if (revealer._current === mpris.trackTitle) - return; - - revealer._current = mpris.trackTitle; - revealer.reveal_child = true; - timeout(3000, () => { - revealer.reveal_child = false; - }); - }]], - })], -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/notifications.js b/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/notifications.js deleted file mode 100644 index cbba68dce..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/notifications.js +++ /dev/null @@ -1,57 +0,0 @@ -import { HoverRevealer } from '../../modules/misc.js'; -import * as notifications from '../../modules/notifications.js'; -const { Notifications } = ags.Service; -const { timeout } = ags.Utils; -const { Box, Scrollable, Label } = ags.Widget; - -export const Header = props => Box({ - ...props, - className: 'header', - children: [ - Label({ label: 'Notifications', hexpand: true, xalign: 0 }), - notifications.ClearButton(), - ], -}); - -export const List = props => Scrollable({ - ...props, - hscroll: 'never', - vscroll: 'automatic', - child: Box({ - vertical: true, - children: [ - notifications.NotificationList(), - notifications.Placeholder(), - ], - }), -}); - -export const PanelIndicator = ({ direction = 'left', ...props } = {}) => Box({ - ...props, - className: 'notifications panel-button', - connections: [[Notifications, box => { - box.visible = - Notifications.notifications.size > 0 && - !Notifications.dnd; - }]], - children: [HoverRevealer({ - connections: [[Notifications, revealer => { - const title = Array.from(Notifications.notifications)?.pop()?.[1].summary; - if (revealer._title === title) - return; - - revealer._title = title; - revealer.reveal_child = true; - timeout(3000, () => { - revealer.reveal_child = false; - }); - }]], - direction, - indicator: notifications.DNDIndicator(), - child: Label({ - connections: [[Notifications, label => { - label.label = Array.from(Notifications.notifications)?.pop()?.[1].summary || ''; - }]], - }), - })], -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/popuplayout.js b/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/popuplayout.js deleted file mode 100644 index 10adc70f3..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/popuplayout.js +++ /dev/null @@ -1,121 +0,0 @@ -const { EventBox, CenterBox, Box, Revealer } = ags.Widget; -const { App } = ags; - -const Padding = windowName => EventBox({ - className: 'padding', - hexpand: true, - vexpand: true, - connections: [['button-press-event', () => App.toggleWindow(windowName)]], -}); - -const PopupRevealer = (windowName, transition, child) => Box({ - style: 'padding: 1px;', - children: [Revealer({ - transition, - child, - transitionDuration: 350, - connections: [[App, (revealer, name, visible) => { - if (name === windowName) - revealer.reveal_child = visible; - }]], - })], -}); - -const layouts = { - 'center': (windowName, child) => CenterBox({ - className: 'shader', - children: [ - Padding(windowName), - CenterBox({ - vertical: true, - children: [ - Padding(windowName), - child, - Padding(windowName), - ], - }), - Padding(windowName), - ], - }), - 'left': (windowName, child) => Box({ - children: [ - Padding(windowName), - Box({ - hexpand: false, - vertical: true, - children: [ - Padding(windowName), - PopupRevealer(windowName, 'slide_right', child), - ], - }), - ], - }), - 'top': (windowName, child) => CenterBox({ - children: [ - Padding(windowName), - Box({ - vertical: true, - children: [ - PopupRevealer(windowName, 'slide_down', child), - Padding(windowName), - ], - }), - Padding(windowName), - ], - }), - 'top right': (windowName, child) => Box({ - children: [ - Padding(windowName), - Box({ - hexpand: false, - vertical: true, - children: [ - PopupRevealer(windowName, 'slide_down', child), - Padding(windowName), - ], - }), - ], - }), - 'bottom right': (windowName, child) => Box({ - children: [ - Padding(windowName), - Box({ - hexpand: false, - vertical: true, - children: [ - Padding(windowName), - PopupRevealer(windowName, 'slide_up', child), - ], - }), - ], - }), - 'top left': (windowName, child) => Box({ - children: [ - Padding(windowName), - Box({ - hexpand: false, - vertical: true, - children: [ - Padding(windowName), - PopupRevealer(windowName, 'slide_right', child), - ], - }), - ], - }), - 'bottom left': (windowName, child) => Box({ - children: [ - Padding(windowName), - Box({ - hexpand: false, - vertical: true, - children: [ - Padding(windowName), - PopupRevealer(windowName, 'slide_right', child), - ], - }), - ], - }), - -}; - -export const PopupLayout = ({ layout, window, child }) => layouts[layout](window, child); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/powermenu.js b/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/powermenu.js deleted file mode 100644 index cf6ead80f..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/powermenu.js +++ /dev/null @@ -1,94 +0,0 @@ -const { App, Service } = ags; -const { exec, error } = ags.Utils; -const { Icon, Label, Box, Button } = ags.Widget; - -class System extends Service { - static { - Service.register(this); - Service.export(this, 'System'); - } - - static instance = new System(); - - static action(action) { - const cmd = { - 'Sleep': 'systemctl suspend', - 'Reboot': 'systemctl reboot', - 'Log Out': 'pkill Hyprland', - 'Shutdown': 'shutdown now', - }[action]; - - if (!cmd) - error(`There is no ${action} system action`); - - App.getWindow('powermenu').hide(); - App.getWindow('verification').show(); - System.instance._action = { cmd, action }; - System.instance.emit('changed'); - } -} - -const SysButton = (icon, action) => Button({ - onClicked: () => System.action(action), - child: Box({ - vertical: true, - children: [ - Icon({ icon, size: 42 }), - Label(action), - ], - }), -}); - -export const PopupContent = () => Box({ - homogeneous: true, - className: 'powermenu', - children: [ - SysButton('weather-clear-night-symbolic', 'Sleep'), - SysButton('system-reboot-symbolic', 'Reboot'), - SysButton('system-log-out-symbolic', 'Log Out'), - SysButton('system-shutdown-symbolic', 'Shutdown'), - ], -}); - -export const Verification = () => Box({ - className: 'verification', - vertical: true, - children: [ - Label({ - className: 'title', - connections: [[System, label => { - label.label = System.instance._action?.action || ''; - }]], - }), - Label({ - className: 'desc', - label: 'Are you sure?', - }), - Box({ - className: 'buttons', - vexpand: true, - valign: 'end', - homogeneous: true, - children: [ - Button({ - child: Label('No'), - onClicked: () => App.toggleWindow('verification'), - }), - Button({ - child: Label('Yes'), - onClicked: () => exec(System.instance._action.cmd), - }), - ], - }), - ], -}); - -export const PanelButton = () => Button({ - className: 'powermenu panel-button', - onClicked: () => App.toggleWindow('powermenu'), - connections: [[ags.App, (btn, win, visible) => { - if (win === 'powermenu' || win === 'verification') - btn.toggleClassName('active', visible); - }]], - child: Icon('system-shutdown-symbolic'), -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/quicksettings.js b/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/quicksettings.js deleted file mode 100644 index 863761d4e..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/layouts/widgets/quicksettings.js +++ /dev/null @@ -1,405 +0,0 @@ -import { Uptime } from '../../modules/clock.js'; -import { FontIcon, HoverRevealer, Separator } from '../../modules/misc.js'; -import * as battery from '../../modules/battery.js'; -import * as audio from '../../modules/audio.js'; -import * as brightness from '../../modules/brightness.js'; -import * as network from '../../modules/network.js'; -import * as bluetooth from '../../modules/bluetooth.js'; -import * as notifications from '../../modules/notifications.js'; -import * as theme from '../../theme/theme.js'; -import * as media from './media.js'; -const { Button, Box, Icon, Label, Revealer } = ags.Widget; -const { Service, App } = ags; -const { Bluetooth, Battery, Audio, Network, Theme } = Service; -const { execAsync, timeout, USER } = ags.Utils; - -class QSMenu extends Service { - static { Service.register(this); } - static instance = new QSMenu(); - static opened = ''; - static toggle(menu) { - QSMenu.opened = QSMenu.opened === menu ? '' : menu; - QSMenu.instance.emit('changed'); - } - - constructor() { - super(); - App.instance.connect('window-toggled', (_a, name, visible) => { - if (name === 'quicksettings' && !visible) { - QSMenu.opened = ''; - QSMenu.instance.emit('changed'); - } - }); - } -} - -const Arrow = (menu, toggleOn) => Button({ - className: 'arrow', - onClicked: () => { - QSMenu.toggle(menu); - if (toggleOn) - toggleOn(); - }, - connections: [[QSMenu, button => { - button.toggleClassName('opened', QSMenu.opened === menu); - }]], - child: Icon({ - icon: 'pan-end-symbolic', - properties: [ - ['deg', 0], - ['opened', false], - ], - connections: [[QSMenu, icon => { - if (QSMenu.opened === menu && !icon._opened || QSMenu.opened !== menu && icon._opened) { - const step = QSMenu.opened === menu ? 10 : -10; - icon._opened = !icon._opened; - for (let i = 0; i < 9; ++i) { - timeout(5 * i, () => { - icon._deg += step; - icon.setStyle(`-gtk-icon-transform: rotate(${icon._deg}deg);`); - }); - } - } - }]], - }), -}); - -const RevealerMenu = (name, child) => Box({ - children: [Revealer({ - transition: 'slide_down', - connections: [[QSMenu, r => r.reveal_child = name === QSMenu.opened]], - child, - })], -}); - -const Avatar = () => Box({ - className: 'avatar', - connections: [[Theme, box => { - box.setStyle(` - background-image: url('${Theme.getSetting('avatar')}'); - background-size: cover; - `); - }]], - children: [Box({ - className: 'shader', - hexpand: true, - children: [Label({ - className: 'user', - halign: 'start', - valign: 'end', - label: '@' + USER, - })], - })], -}); - -const SysButton = (icon, action, className = '') => Button({ - className, - onClicked: () => Service.System.action(action), - tooltipText: action, - child: Icon(icon), -}); - -const SystemBox = () => Box({ - vertical: true, - halign: 'end', - valign: 'center', - children: [ - Box({ - valign: 'center', - className: 'system', - children: [ - Button({ - className: 'settings', - onClicked: () => { App.toggleWindow('quicksettings'); Theme.openSettings(); }, - tooltipText: 'Settings', - child: Icon('org.gnome.Settings-symbolic'), - }), - Box({ - className: 'uptime', - children: [ - Label('uptime: '), - Uptime(), - ], - }), - SysButton('system-log-out-symbolic', 'Log Out'), - SysButton('system-shutdown-symbolic', 'Shutdown', 'shutdown'), - ], - }), - battery.BatteryProgress(), - ], -}); - -const VolumeBox = () => Box({ - vertical: true, - className: 'volume-box', - children: [ - Box({ - className: 'volume', - children: [ - Button({ - child: audio.SpeakerTypeIndicator(), - onClicked: 'pactl set-sink-mute @DEFAULT_SINK@ toggle', - }), - audio.SpeakerSlider({ hexpand: true }), - audio.SpeakerPercentLabel(), - Arrow('stream-selector'), - ], - }), - RevealerMenu('stream-selector', Box({ - vertical: true, - className: 'menu', - children: [ - audio.StreamSelector(), - Separator(), - Button({ - onClicked: () => { - execAsync('pavucontrol').catch(print); - App.closeWindow('quicksettings'); - }, - child: Label({ - label: 'Settings', - xalign: 0, - }), - }), - ], - })), - ], -}); - -const BrightnessBox = () => Box({ - className: 'brightness', - children: [ - Button({ - onClicked: () => { - execAsync('wl-gammactl').catch(print); - App.closeWindow('quicksettings'); - }, - child: brightness.Indicator(), - }), - brightness.BrightnessSlider(), - brightness.PercentLabel(), - ], -}); - -const ArrowToggle = ({ icon, label, connection, toggle, name, toggleOn }) => Box({ - connections: [[ - connection.service, - w => w.toggleClassName('active', connection.callback()), - ]], - className: `arrow toggle ${name}`, - children: [ - Button({ - hexpand: true, - className: 'toggle', - onClicked: toggle, - child: Box({ - children: [ - icon, - label, - ], - }), - }), - Arrow(name, toggleOn), - ], -}); - -const NetworkToggle = () => ArrowToggle({ - icon: network.WifiIndicator(), - label: network.SSIDLabel(), - connection: { - service: Network, - callback: () => Network.wifi?.enabled, - }, - toggle: Network.toggleWifi, - toggleOn: () => { - Network.wifi.enabled = true; - Network.wifi.scan(); - }, - name: 'network', -}); - -const BluetoothToggle = () => ArrowToggle({ - icon: bluetooth.Indicator(), - label: bluetooth.ConnectedLabel(), - connection: { - service: Bluetooth, - callback: () => Bluetooth.enabled, - }, - toggle: () => Bluetooth.enabled = !Bluetooth.enabled, - toggleOn: () => { - Bluetooth.enabled = QSMenu.opened === 'bluetooth' - ? true : Bluetooth.enabled; - }, - name: 'bluetooth', -}); - -const SmallToggle = (toggle, indicator) => toggle({ - className: 'toggle', - halign: 'fill', - hexpand: true, - vexpand: true, - child: indicator({ halign: 'center' }), -}); - -const DNDToggle = () => SmallToggle( - notifications.DNDToggle, - notifications.DNDIndicator, -); - -const MuteToggle = () => SmallToggle( - audio.MicrophoneMuteToggle, - audio.MicrophoneMuteIndicator, -); - -const AsusctlToggle = () => SmallToggle( - asusctl.ProfileToggle, - asusctl.ProfileIndicator, -); - -const AsusmodeToggle = () => SmallToggle( - asusctl.ModeToggle, - asusctl.ModeIndicator, -); - -const ThemeToggle = () => Button({ - className: 'toggle', - onClicked: () => QSMenu.toggle('theme'), - child: theme.Indicator(), - connections: [[QSMenu, w => w.toggleClassName('on', QSMenu.opened === 'theme')]], -}); - -const AppmixerToggle = () => Button({ - className: 'toggle', - onClicked: () => QSMenu.toggle('app-mixer'), - child: FontIcon({ icon: '' }), - tooltipText: 'App Mixer', - connections: [[QSMenu, w => w.toggleClassName('on', QSMenu.opened === 'app-mixer')]], -}); - -const Submenu = ({ menuName, icon, title, contentType }) => RevealerMenu(menuName, Box({ - vertical: true, - className: `submenu ${menuName}`, - children: [ - Box({ className: 'title', children: [icon, Label(title)] }), - contentType({ className: 'content', hexpand: true }), - ], -})); - -const Appmixer = () => Submenu({ - menuName: 'app-mixer', - icon: FontIcon({ icon: '' }), - title: 'App Mixer', - contentType: audio.AppMixer, -}); - -const NetworkSelection = () => Submenu({ - menuName: 'network', - icon: Icon('network-wireless-symbolic'), - title: 'Wireless Networks', - contentType: network.WifiSelection, -}); - -const BluetoothSelection = () => Submenu({ - menuName: 'bluetooth', - icon: Icon('bluetooth-symbolic'), - title: 'Bluetooth', - contentType: bluetooth.Devices, -}); - -const ThemeSelection = () => Submenu({ - menuName: 'theme', - icon: Icon('preferences-desktop-theme-symbolic'), - title: 'Theme', - contentType: theme.Selector, -}); - -export const PopupContent = () => Box({ - className: 'quicksettings', - vertical: true, - hexpand: false, - children: [ - Box({ - className: 'header', - children: [ - Avatar(), - SystemBox(), - ], - }), - VolumeBox(), - BrightnessBox(), - Box({ - className: 'toggles-box', - children: [ - Box({ - vertical: true, - className: 'arrow-toggles', - children: [NetworkToggle(), BluetoothToggle()], - }), - Box({ - vertical: true, - className: 'small-toggles', - vexpand: true, - hexpand: false, - children: [ - Box({ children: [DNDToggle(), MuteToggle()] }), - Box({ children: [AppmixerToggle(), ThemeToggle()] }), - ], - }), - ], - }), - Appmixer(), - NetworkSelection(), - BluetoothSelection(), - ThemeSelection(), - media.PopupContent(), - ], -}); - -const BluetoothIndicator = () => Box({ - connections: [[Bluetooth, box => { - box.children = Array.from(Bluetooth.connectedDevices.values()) - .map(({ iconName, name }) => HoverRevealer({ - indicator: Icon(iconName + '-symbolic'), - child: Label(name), - })); - - box.visible = Bluetooth.connectedDevices.size > 0; - }]], -}); - -const BatteryIndicator = () => HoverRevealer({ - direction: 'right', - indicator: battery.Indicator(), - child: battery.LevelLabel(), - connections: [[Battery, revealer => { - revealer.reveal_child = Battery.percent < 100; - }]], -}); - -export const PanelButton = ({ vertical }) => Button({ - className: 'quicksettings panel-button', - onClicked: () => App.toggleWindow('quicksettings'), - onScrollUp: () => { - Audio.speaker.volume += 0.02; - Service.Indicator.speaker(); - }, - onScrollDown: () => { - Audio.speaker.volume -= 0.02; - Service.Indicator.speaker(); - }, - connections: [[App, (btn, win, visible) => { - btn.toggleClassName('active', win === 'quicksettings' && visible); - }]], - child: Box({ - vertical, - children: [ - audio.MicrophoneMuteIndicator({ unmuted: null }), - notifications.DNDIndicator({ noisy: null }), - BluetoothIndicator(), - bluetooth.Indicator({ disabled: null }), - network.Indicator(), - audio.SpeakerIndicator(), - BatteryIndicator(), - ], - }), -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/modules/applauncher.js b/home/isabel/programs/gui/confs/bars/ags/config/modules/applauncher.js deleted file mode 100644 index 3f9ade80f..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/modules/applauncher.js +++ /dev/null @@ -1,92 +0,0 @@ -const { App } = ags; -const { Applications } = ags.Service; -const { Label, Box, Icon, Button, Scrollable, Entry } = ags.Widget; -import { Wallpaper } from './wallpaper.js'; -import { Separator } from './misc.js'; - -const AppItem = (app, window) => Button({ - className: 'app', - connections: [['clicked', () => { - App.closeWindow(window); - app.launch(); - }]], - child: Box({ - children: [ - Icon({ - icon: app.iconName, - size: 42, - }), - Box({ - vertical: true, - children: [ - Label({ - className: 'title', - label: app.name, - xalign: 0, - valign: 'center', - ellipsize: 3, - }), - Label({ - className: 'description', - label: app.description || '', - wrap: true, - xalign: 0, - justification: 'left', - valign: 'center', - }), - ], - }), - ], - }), -}); - -export const Applauncher = ({ windowName = 'applauncher' } = {}) => { - const list = Box({ vertical: true }); - const entry = Entry({ - hexpand: true, - placeholderText: 'Search', - onAccept: ({ text }) => { - const list = Applications.query(text); - if (list[0]) { - App.toggleWindow(windowName); - list[0].launch(); - } - }, - onChange: ({ text }) => { - list.children = Applications.query(text).map(app => [ - Separator(), - AppItem(app, windowName), - ]).flat(); - list.add(Separator()); - list.show_all(); - }, - }); - - return Box({ - className: 'applauncher', - properties: [['list', list]], - vertical: true, - children: [ - Wallpaper({ - children: [ - Icon('folder-saved-search-symbolic'), - entry, - ], - - }), - Scrollable({ - hscroll: 'never', - child: list, - }), - ], - connections: [[App, (_b, name, visible) => { - if (name !== windowName) - return; - - entry.set_text('-'); // force onChange - entry.set_text(''); - if (visible) - entry.grab_focus(); - }]], - }); -}; diff --git a/home/isabel/programs/gui/confs/bars/ags/config/modules/audio.js b/home/isabel/programs/gui/confs/bars/ags/config/modules/audio.js deleted file mode 100644 index 459fe1289..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/modules/audio.js +++ /dev/null @@ -1,185 +0,0 @@ -const { Audio } = ags.Service; -const { Label, Box, Icon, Stack, Button, Slider } = ags.Widget; - -const iconSubstitute = item => { - const substitues = [ - { from: 'audio-headset-bluetooth', to: 'audio-headphones-symbolic' }, - { from: 'audio-card-analog-usb', to: 'audio-speakers-symbolic' }, - { from: 'audio-card-analog-pci', to: 'audio-card-symbolic' }, - ]; - - for (const { from, to } of substitues) { - if (from === item) - return to; - } - return item; -}; - -export const SpeakerIndicator = ({ - items = [ - ['101', Icon('audio-volume-overamplified-symbolic')], - ['67', Icon('audio-volume-high-symbolic')], - ['34', Icon('audio-volume-medium-symbolic')], - ['1', Icon('audio-volume-low-symbolic')], - ['0', Icon('audio-volume-muted-symbolic')], - ], - ...props -} = {}) => Stack({ - ...props, - items, - connections: [[Audio, stack => { - if (!Audio.speaker) - return; - - if (Audio.speaker.isMuted) - return stack.shown = '0'; - - const vol = Audio.speaker.volume * 100; - for (const threshold of [100, 66, 33, 0, -1]) { - if (vol > threshold + 1) - return stack.shown = `${threshold + 1}`; - } - }, 'speaker-changed']], -}); - -export const SpeakerTypeIndicator = props => Icon({ - ...props, - connections: [[Audio, icon => { - if (Audio.speaker) - icon.icon = iconSubstitute(Audio.speaker.iconName); - }]], -}); - -export const SpeakerPercentLabel = props => Label({ - ...props, - connections: [[Audio, label => { - if (!Audio.speaker) - return; - - label.label = `${Math.floor(Audio.speaker.volume * 100)}%`; - }, 'speaker-changed']], -}); - -export const SpeakerSlider = props => Slider({ - ...props, - drawValue: false, - onChange: ({ value }) => Audio.speaker.volume = value, - connections: [[Audio, slider => { - if (!Audio.speaker) - return; - - slider.sensitive = !Audio.speaker.isMuted; - slider.value = Audio.speaker.volume; - }, 'speaker-changed']], -}); - -export const MicrophoneMuteIndicator = ({ - muted = Icon('microphone-disabled-symbolic'), - unmuted = Icon('microphone-sensitivity-high-symbolic'), - ...props -} = {}) => Stack({ - ...props, - items: [ - ['true', muted], - ['false', unmuted], - ], - connections: [[Audio, stack => { - stack.shown = `${Audio.microphone?.isMuted}`; - }, 'microphone-changed']], -}); - -export const MicrophoneMuteToggle = props => Button({ - ...props, - onClicked: 'pamixer --default-source -t', - connections: [[Audio, button => { - if (!Audio.microphone) - return; - - button.toggleClassName('on', Audio.microphone.isMuted); - }, 'microphone-changed']], -}); - -export const AppMixer = props => { - const AppItem = stream => { - const icon = Icon(); - const label = Label({ xalign: 0, justify: 'left', wrap: true, ellipsize: 3 }); - const percent = Label({ xalign: 1 }); - const slider = Slider({ - hexpand: true, - drawValue: false, - onChange: ({ value }) => { - stream.volume = value; - }, - }); - const sync = () => { - icon.icon = stream.iconName; - icon.tooltipText = stream.name; - slider.value = stream.volume; - percent.label = `${Math.floor(stream.volume * 100)}%`; - label.label = stream.description || ''; - }; - const id = stream.connect('changed', sync); - return Box({ - hexpand: true, - children: [ - icon, - Box({ - children: [ - Box({ - vertical: true, - children: [ - label, - slider, - ], - }), - percent, - ], - }), - ], - connections: [['destroy', () => stream.disconnect(id)]], - setup: sync, - }); - }; - - return Box({ - ...props, - vertical: true, - connections: [[Audio, box => { - box.children = Array.from(Audio.apps.values()) - .map(stream => AppItem(stream)); - }]], - }); -}; - -export const StreamSelector = ({ streams = 'speakers', ...props } = {}) => Box({ - ...props, - vertical: true, - connections: [[Audio, box => { - box.children = Array.from(Audio[streams].values()).map(stream => Button({ - child: Box({ - children: [ - Icon({ - icon: iconSubstitute(stream.iconName), - tooltipText: stream.iconName, - }), - Label(stream.description.split(' ').slice(0, 4).join(' ')), - Icon({ - icon: 'object-select-symbolic', - hexpand: true, - halign: 'end', - connections: [['draw', icon => { - icon.visible = Audio.speaker === stream; - }]], - }), - ], - }), - onClicked: () => { - if (streams === 'speakers') - Audio.speaker = stream; - - if (streams === 'microphones') - Audio.microphone = stream; - }, - })); - }]], -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/modules/battery.js b/home/isabel/programs/gui/confs/bars/ags/config/modules/battery.js deleted file mode 100644 index 2ce1ccb20..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/modules/battery.js +++ /dev/null @@ -1,73 +0,0 @@ -const { Battery } = ags.Service; -const { Label, Icon, Stack, ProgressBar, Overlay, Box } = ags.Widget; - -const icons = charging => ([ - ...Array.from({ length: 9 }, (_, i) => i * 10).map(i => ([ - `${i}`, Icon({ - className: `${i} ${charging ? 'charging' : 'discharging'}`, - icon: `battery-level-${i}${charging ? '-charging' : ''}-symbolic`, - }), - ])), - ['100', Icon({ - className: `100 ${charging ? 'charging' : 'discharging'}`, - icon: `battery-level-100${charging ? '-charged' : ''}-symbolic`, - })], -]); - -const Indicators = charging => Stack({ - items: icons(charging), - connections: [[Battery, stack => { - stack.shown = `${Math.floor(Battery.percent / 10) * 10}`; - }]], -}); - -export const Indicator = ({ - charging = Indicators(true), - discharging = Indicators(false), - ...props -} = {}) => Stack({ - ...props, - className: 'battery', - items: [ - ['true', charging], - ['false', discharging], - ], - connections: [[Battery, stack => { - const { charging, charged } = Battery; - stack.shown = `${charging || charged}`; - stack.toggleClassName('charging', Battery.charging); - stack.toggleClassName('charged', Battery.charged); - stack.toggleClassName('low', Battery.percent < 30); - }]], -}); - -export const LevelLabel = props => Label({ - ...props, - connections: [[Battery, label => label.label = `${Battery.percent}%`]], -}); - -export const BatteryProgress = props => Box({ - ...props, - className: 'battery-progress', - connections: [[Battery, w => { - w.toggleClassName('half', Battery.percent < 46); - w.toggleClassName('charging', Battery.charging); - w.toggleClassName('charged', Battery.charged); - w.toggleClassName('low', Battery.percent < 30); - }]], - children: [Overlay({ - child: ProgressBar({ - hexpand: true, - connections: [[Battery, progress => { - progress.fraction = Battery.percent / 100; - }]], - }), - overlays: [Label({ - connections: [[Battery, l => { - l.label = Battery.charging || Battery.charged - ? '󱐋' - : `${Battery.percent}%`; - }]], - })], - })], -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/modules/bluetooth.js b/home/isabel/programs/gui/confs/bars/ags/config/modules/bluetooth.js deleted file mode 100644 index d47dde269..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/modules/bluetooth.js +++ /dev/null @@ -1,62 +0,0 @@ -import { Spinner } from './misc.js'; -const { Bluetooth } = ags.Service; -const { Icon, Label, Box, Button, Stack } = ags.Widget; - -export const Indicator = ({ - enabled = Icon({ icon: 'bluetooth-active-symbolic', className: 'enabled' }), - disabled = Icon({ icon: 'bluetooth-disabled-symbolic', className: 'disabled' }), - ...props -} = {}) => Stack({ - ...props, - items: [ - ['true', enabled], - ['false', disabled], - ], - connections: [[Bluetooth, stack => { - stack.shown = `${Bluetooth.enabled}`; - }]], -}); - -export const Toggle = props => Button({ - ...props, - onClicked: () => Bluetooth.enabled = !Bluetooth.enabled, - connections: [[Bluetooth, button => button.toggleClassName('on', Bluetooth.enabled)]], -}); - -export const ConnectedLabel = props => Label({ - ...props, - connections: [[Bluetooth, label => { - if (!Bluetooth.enabled) - return label.label = 'Disabled'; - - if (Bluetooth.connectedDevices.size === 0) - return label.label = 'Not Connected'; - - if (Bluetooth.connectedDevices.size === 1) - return label.label = Bluetooth.connectedDevices.entries().next().value[1].alias; - - label.label = `${Bluetooth.connectedDevices.size} Connected`; - }]], -}); - -export const Devices = props => Box({ - ...props, - vertical: true, - connections: [[Bluetooth, box => { - box.children = Array.from(Bluetooth.devices.values()).map(device => Box({ - hexpand: false, - children: [ - Icon(device.iconName + '-symbolic'), - Label(device.name), - Box({ hexpand: true }), - device._connecting ? Spinner() : ags.Widget({ - type: imports.gi.Gtk.Switch, - active: device.connected, - connections: [['activate', ({ active }) => { - device.setConnection(active); - }]], - }), - ], - })); - }]], -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/modules/brightness.js b/home/isabel/programs/gui/confs/bars/ags/config/modules/brightness.js deleted file mode 100644 index a024b2b73..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/modules/brightness.js +++ /dev/null @@ -1,63 +0,0 @@ -const { Service } = ags; -const { exec, execAsync } = ags.Utils; -const { Icon, Label, Slider } = ags.Widget; - -class BrightnessService extends Service { - static { Service.register(this); } - - _screen = 0; - - get screen() { return this._screen; } - - set screen(percent) { - if (percent < 0) - percent = 0; - - if (percent > 1) - percent = 1; - - execAsync(`brightnessctl s ${percent * 100}% -q`) - .then(() => { - this._screen = percent; - this.emit('changed'); - }) - .catch(print); - } - - constructor() { - super(); - this._screen = Number(exec('brightnessctl g')) / Number(exec('brightnessctl m')); - } -} - -class Brightness { - static { Service.export(this, 'Brightness'); } - static instance = new BrightnessService(); - - static get screen() { return Brightness.instance.screen; } - static set screen(value) { Brightness.instance.screen = value; } -} - -export const BrightnessSlider = props => Slider({ - ...props, - drawValue: false, - hexpand: true, - connections: [ - [Brightness, slider => { - slider.value = Brightness.screen; - }], - ], - onChange: ({ value }) => Brightness.screen = value, -}); - -export const Indicator = props => Icon({ - ...props, - icon: 'display-brightness-symbolic', -}); - -export const PercentLabel = props => Label({ - ...props, - connections: [ - [Brightness, label => label.label = `${Math.floor(Brightness.screen * 100)}%`], - ], -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/modules/clock.js b/home/isabel/programs/gui/confs/bars/ags/config/modules/clock.js deleted file mode 100644 index c03e1d2a1..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/modules/clock.js +++ /dev/null @@ -1,29 +0,0 @@ -const { Label } = ags.Widget; -const { execAsync } = ags.Utils; -const { DateTime } = imports.gi.GLib; - -export const Clock = ({ - format = '%I:%M:%S | %d/%m/%y', - interval = 1000, - ...props -} = {}) => Label({ - className: 'clock', - ...props, - connections: [[interval, label => - label.label = DateTime.new_now_local().format(format), - ]], -}); - -export const Uptime = ({ - interval = 100_000, - ...props -} = {}) => Label({ - ...props, - connections: [[interval, label => { - execAsync(['bash', '-c', "uptime | awk '{print $3}' | tr ',' ' '"]) - .then(time => label.label = time) - .catch(print); - }]], -}); - - diff --git a/home/isabel/programs/gui/confs/bars/ags/config/modules/colorpicker.js b/home/isabel/programs/gui/confs/bars/ags/config/modules/colorpicker.js deleted file mode 100644 index 0f0f5ecbf..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/modules/colorpicker.js +++ /dev/null @@ -1,39 +0,0 @@ -const { Notifications } = ags.Service; -const { execAsync } = ags.Utils; -const { Gravity } = imports.gi.Gdk; -const { Button, Icon, Menu, MenuItem, Label } = ags.Widget; - -const wlCopy = color => execAsync(['wl-copy', color]).catch(print); - -export const PanelButton = props => Button({ - ...props, - className: 'panel-button colorpicker', - child: Icon('color-select-symbolic'), - properties: [['colors', []]], - connections: [['clicked', btn => execAsync('hyprpicker').then(color => { - wlCopy(color); - if (!btn._colors.includes(color)) { - btn._colors.push(color); - if (btn._colors > 10) - btn._colors.shift(); - } - - btn._id = Notifications.instance.Notify( - 'Color Picker', - btn._id || null, - 'color-select-symbolic', - color, - '', - [], - {}, - ); - }).catch(print)]], - onSecondaryClick: btn => btn._colors.length > 0 ? Menu({ - className: 'colorpicker', - children: btn._colors.map(color => MenuItem({ - child: Label(color), - style: `background-color: ${color}`, - onActivate: () => wlCopy(color), - })), - }).popup_at_widget(btn, Gravity.WEST, Gravity.EAST, null) : false, -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/modules/corner.js b/home/isabel/programs/gui/confs/bars/ags/config/modules/corner.js deleted file mode 100644 index 329a41b8a..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/modules/corner.js +++ /dev/null @@ -1,43 +0,0 @@ -const { Gtk } = imports.gi; - -export const Corner = place => ags.Widget({ - type: Gtk.DrawingArea, - className: 'corner', - hexpand: true, - vexpand: true, - halign: place.includes('left') ? 'start' : 'end', - valign: place.includes('top') ? 'start' : 'end', - setup: widget => { widget.set_size_request(0, 0); }, - connections: [['draw', (widget, cr) => { - const context = widget.get_style_context(); - const c = context.get_property('background-color', Gtk.StateFlags.NORMAL); - const r = context.get_property('border-radius', Gtk.StateFlags.NORMAL); - 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(); - }]], -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/modules/hyprland.js b/home/isabel/programs/gui/confs/bars/ags/config/modules/hyprland.js deleted file mode 100644 index e9a7614ef..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/modules/hyprland.js +++ /dev/null @@ -1,25 +0,0 @@ -const { App } = ags; -const { Hyprland, Applications } = ags.Service; -const { execAsync, lookUpIcon } = ags.Utils; -const { Box, Button, Label, Icon } = ags.Widget; - -export const Workspaces = ({ - fixed = 7, - vertical, - indicator, - ...props -} = {}) => Box({ - ...props, - vertical, - children: Array.from({ length: fixed }, (_, i) => i + 1).map(i => Button({ - onClicked: () => execAsync(`hyprctl dispatch workspace ${i}`).catch(print), - child: indicator ? indicator() : Label(`${i}`), - connections: [[Hyprland, btn => { - const { workspaces, active } = Hyprland; - const occupied = workspaces.has(i) && workspaces.get(i).windows > 0; - btn.toggleClassName('active', active.workspace.id === i); - btn.toggleClassName('occupied', occupied); - btn.toggleClassName('empty', !occupied); - }]], - })), -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/modules/misc.js b/home/isabel/programs/gui/confs/bars/ags/config/modules/misc.js deleted file mode 100644 index 410ea3085..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/modules/misc.js +++ /dev/null @@ -1,152 +0,0 @@ -const { Box, Label, Overlay, Icon, Revealer, EventBox } = ags.Widget; -const { timeout, exec } = ags.Utils; - -export const Separator = ({ className = '', ...props } = {}) => Box({ - hexpand: false, - vexpand: false, - ...props, - className: [...className.split(' '), 'separator'].join(' '), -}); - -export const FontIcon = ({ icon = '', ...props }) => { - const box = Box({ - style: 'min-width: 1px; min-height: 1px;', - }); - const label = Label({ - label: icon, - halign: 'center', - valign: 'center', - }); - return Box({ - ...props, - setup: box => box.label = label, - className: 'icon', - children: [Overlay({ - child: box, - overlays: [label], - passThrough: true, - connections: [['draw', overlay => { - const size = overlay.get_style_context() - .get_property('font-size', imports.gi.Gtk.StateFlags.NORMAL) || 11; - - box.setStyle(`min-width: ${size}px; min-height: ${size}px;`); - }]], - })], - }); -}; - -export const DistroIcon = props => FontIcon({ - ...props, - className: 'distro-icon', - icon: (() => { - // eslint-disable-next-line quotes - const distro = exec(`bash -c "cat /etc/os-release | grep '^ID' | head -n 1 | cut -d '=' -f2"`) - .toLowerCase(); - - 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 ''; - } - })(), -}); - -export const Spinner = ({ icon = 'process-working-symbolic' }) => Icon({ - icon, - properties: [['deg', 0]], - connections: [[10, w => { - w.setStyle(`-gtk-icon-transform: rotate(${w._deg++ % 360}deg);`); - }]], -}); - -export const Progress = ({ height = 18, width = 180, vertical = false, child, ...props }) => { - const fill = Box({ - className: 'fill', - hexpand: vertical, - vexpand: !vertical, - halign: vertical ? 'fill' : 'start', - valign: vertical ? 'end' : 'fill', - children: [child], - }); - const progress = Box({ - ...props, - className: 'progress', - style: ` - min-width: ${width}px; - min-height: ${height}px; - `, - children: [fill], - }); - 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.setStyle(`min-${axis}: ${preferred}px;`); - return; - } - - const frames = 10; - const goal = preferred - fill._size; - const step = goal / frames; - - for (let i = 0; i < frames; ++i) { - timeout(5 * i, () => { - fill._size += step; - fill.setStyle(`min-${axis}: ${fill._size}px`); - }); - } - }; - return progress; -}; - -export const HoverRevealer = ({ - indicator, - child, - direction = 'left', - duration = 300, - connections, - ...rest -}) => Box({ - children: [EventBox({ - ...rest, - onHover: w => { - if (w._open) - return; - - w.get_child().get_children()[direction === 'down' || direction === 'right' ? 1 : 0].reveal_child = true; - timeout(duration, () => w._open = true); - }, - onHoverLost: w => { - if (!w._open) - return; - - w.get_child().get_children()[direction === 'down' || direction === 'right' ? 1 : 0].reveal_child = false; - w._open = false; - }, - child: Box({ - vertical: direction === 'down' || direction === 'up', - children: [ - direction === 'down' || direction === 'right' ? indicator : null, - Revealer({ - transition: `slide_${direction}`, - connections, - transitionDuration: duration, - child, - }), - direction === 'up' || direction === 'left' ? indicator : null, - ], - }), - })], -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/modules/mpris.js b/home/isabel/programs/gui/confs/bars/ags/config/modules/mpris.js deleted file mode 100644 index c9f08401c..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/modules/mpris.js +++ /dev/null @@ -1,351 +0,0 @@ -const { CACHE_DIR, execAsync, ensureDirectory, lookUpIcon } = ags.Utils; -const { Button, Icon, Label, Box, Stack, Slider } = ags.Widget; -const { Mpris } = ags.Service; -const { GLib } = imports.gi; - -const MEDIA_CACHE_PATH = CACHE_DIR + '/media'; - -export const prefer = players => { - const preferred = 'spotify'; - let last; - for (const [name, mpris] of players) { - if (name.includes(preferred)) - return mpris; - - last = mpris; - } - - return last; -}; - -export const MprisBox = ({ player = prefer, ...props } = {}) => Box({ - ...props, - connections: [[Mpris, box => { - const mpris = Mpris.getPlayer(player); - box.visible = mpris; - - if (!mpris) - return; - - if (box._current) - box.toggleClassName(box._current, false); - - box._current = mpris.name; - box.toggleClassName(mpris.name); - }]], - setup: box => { - const id = box.connect('draw', () => { - box.visible = Mpris.getPlayer(player); - box.disconnect(id); - }); - }, -}); - -export const CoverArt = ({ player = prefer, ...props } = {}) => Box({ - ...props, - connections: [[Mpris, box => { - const url = Mpris.getPlayer(player)?.coverPath; - if (!url) - return; - - box.setStyle(`background-image: url("${url}")`); - }]], -}); - -export const BlurredCoverArt = ({ player = prefer, ...props } = {}) => Box({ - ...props, - connections: [[Mpris, box => { - const url = Mpris.getPlayer(player)?.coverPath; - if (!url) - return; - - const blurredPath = MEDIA_CACHE_PATH + '/blurred'; - const blurred = blurredPath + - url.substring(MEDIA_CACHE_PATH.length); - - if (GLib.file_test(blurred, GLib.FileTest.EXISTS)) { - box.setStyle(`background-image: url("${blurred}")`); - return; - } - - ensureDirectory(blurredPath); - execAsync(['convert', url, '-blur', '0x22', blurred]) - .then(() => box.setStyle(`background-image: url("${blurred}")`)) - .catch(() => { }); - }]], -}); - -export const TitleLabel = ({ player = prefer, ...props } = {}) => Label({ - ...props, - className: 'title', - connections: [[Mpris, label => { - label.label = Mpris.getPlayer(player)?.trackTitle || ''; - }]], -}); - -export const ArtistLabel = ({ player = prefer, ...props } = {}) => Label({ - ...props, - className: 'artist', - connections: [[Mpris, label => { - label.label = Mpris.getPlayer(player)?.trackArtists.join(', ') || ''; - }]], -}); - -export const PlayerLabel = ({ player = prefer, ...props } = {}) => Label({ - ...props, - connections: [[Mpris, label => { - label.label = Mpris.getPlayer(player)?.identity || ''; - }]], -}); - -export const PlayerIcon = ({ symbolic = false, player = prefer, ...props } = {}) => Icon({ - ...props, - connections: [[Mpris, icon => { - const name = `${Mpris.getPlayer(player)?.entry}${symbolic ? '-symbolic' : ''}`; - lookUpIcon(name) - ? icon.icon_name = name - : icon.icon_name = 'audio-x-generic-symbolic'; - }]], -}); - -export const VolumeSlider = ({ player = prefer, ...props } = {}) => Slider({ - ...props, - drawValue: false, - onChange: ({ value }) => { - const mpris = Mpris.getPlayer(player); - if (mpris && mpris.volume >= 0) - Mpris.getPlayer(player).volume = value; - }, - connections: [[Mpris, slider => { - if (slider._dragging) - return; - - const mpris = Mpris.getPlayer(player); - slider.visible = mpris; - if (mpris) { - slider.visible = mpris.volume >= 0; - slider.value = mpris.volume; - } - }]], -}); - -export const VolumeIcon = ({ player = prefer, items } = {}) => Stack({ - items: items || [ - ['67', Icon('audio-volume-high-symbolic')], - ['34', Icon('audio-volume-medium-symbolic')], - ['1', Icon('audio-volume-low-symbolic')], - ['0', Icon('audio-volume-muted-symbolic')], - ], - connections: [[Mpris, stack => { - const mpris = Mpris.getPlayer(player); - stack.visible = mpris?.volume >= 0; - const value = (mpris?.volume || 0) * 100; - if (66 <= value) - stack.shown = '67'; - - if (34 <= value) - stack.shown = '34'; - - if (1 <= value) - stack.shown = '1'; - - stack.shown = '0'; - }]], -}); - -export const PositionSlider = ({ player = prefer, ...props } = {}) => { - const update = slider => { - if (slider._dragging) - return; - - const mpris = Mpris.getPlayer(player); - slider.visible = mpris?.length > 0; - if (mpris && mpris.length > 0) - slider.adjustment.value = mpris.position / mpris.length; - }; - return Slider({ - ...props, - drawValue: false, - onChange: ({ adjustment: { value } }) => { - const mpris = Mpris.getPlayer(player); - if (mpris && mpris.length >= 0) - Mpris.getPlayer(player).position = mpris.length * value; - }, - connections: [ - [Mpris, update], - [1000, update], - ], - }); -}; - -function lengthStr(length) { - const min = Math.floor(length / 60); - const sec0 = Math.floor(length % 60) < 10 ? '0' : ''; - const sec = Math.floor(length % 60); - return `${min}:${sec0}${sec}`; -} - -export const PositionLabel = ({ player = prefer, ...props } = {}) => { - const update = label => { - const mpris = Mpris.getPlayer(player); - - if (mpris && !label._binding) { - label._binding = mpris.connect('position', (_, time) => { - label.label = lengthStr(time); - }); - label.connect('destroy', () => { - if (mpris) - mpris.disconnect(label._binding); - - label._binding = null; - }); - } - - mpris && mpris.length > 0 - ? label.label = lengthStr(mpris.position) - : label.visible = mpris; - - return true; - }; - return Label({ - ...props, - connections: [ - [Mpris, update], - [1000, update], - ], - }); -}; - -export const LengthLabel = ({ player = prefer, ...props } = {}) => Label({ - ...props, - connections: [[Mpris, label => { - const mpris = Mpris.getPlayer(player); - mpris && mpris.length > 0 - ? label.label = lengthStr(mpris.length) - : label.visible = mpris; - }]], -}); - -export const Slash = ({ player = prefer, ...props } = {}) => Label({ - ...props, - label: '/', - className: 'slash', - connections: [ - [Mpris, label => { - const mpris = Mpris.getPlayer(player); - label.visible = mpris && mpris.length > 0; - }], - ], -}); - -const PlayerButton = ({ - player = prefer, - items, - onClick, - prop, - canProp, - cantValue, - ...rest -} = {}) => Button({ - ...rest, - child: Stack({ items }), - onClicked: () => Mpris.getPlayer(player)?.[onClick](), - connections: [[Mpris, button => { - const mpris = Mpris.getPlayer(player); - if (!mpris || mpris[canProp] === cantValue) - return button.hide(); - - button.show(); - button.child.shown = `${mpris[prop]}`; - }]], -}); - -export const ShuffleButton = ({ - player, - enabled = Label({ className: 'shuffle enabled', label: '󰒟' }), - disabled = Label({ className: 'shuffle disabled', label: '󰒟' }), - ...props -} = {}) => PlayerButton({ - ...props, - player, - items: [ - ['true', enabled], - ['false', disabled], - ], - onClick: 'shuffle', - prop: 'shuffleStatus', - canProp: 'shuffleStatus', - cantValue: null, -}); - -export const LoopButton = ({ - player, - none = Label({ className: 'loop none', label: '󰓦' }), - track = Label({ className: 'loop track', label: '󰓦' }), - playlist = Label({ className: 'loop playlist', label: '󰑐' }), - ...props -} = {}) => PlayerButton({ - ...props, - player, - items: [ - ['None', none], - ['Track', track], - ['Playlist', playlist], - ], - onClick: 'loop', - prop: 'loopStatus', - canProp: 'loopStatus', - cantValue: null, -}); - -export const PlayPauseButton = ({ - player, - playing = Label({ className: 'playing', label: '󰏦' }), - paused = Label({ className: 'paused', label: '󰐍' }), - stopped = Label({ className: 'stopped', label: '󰐍' }), - ...props -} = {}) => PlayerButton({ - ...props, - player, - items: [ - ['Playing', playing], - ['Paused', paused], - ['Stopped', stopped], - ], - onClick: 'playPause', - prop: 'playBackStatus', - canProp: 'canPlay', - cantValue: false, -}); - -export const PreviousButton = ({ - player, - child = Label({ className: 'previous', label: '󰒮' }), - ...props -} = {}) => PlayerButton({ - ...props, - player, - items: [ - ['true', child], - ], - onClick: 'previous', - prop: 'canGoPrev', - canProp: 'canGoPrev', - cantValue: false, -}); - -export const NextButton = ({ - player, - child = Label({ className: 'next', label: '󰒭' }), - ...props -} = {}) => PlayerButton({ - ...props, - player, - items: [ - ['true', child], - ], - onClick: 'next', - prop: 'canGoNext', - canProp: 'canGoNext', - cantValue: false, -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/modules/network.js b/home/isabel/programs/gui/confs/bars/ags/config/modules/network.js deleted file mode 100644 index f85321d50..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/modules/network.js +++ /dev/null @@ -1,131 +0,0 @@ -const { Network } = ags.Service; -const { Label, Icon, Box, Stack, Button } = ags.Widget; - -export const SSIDLabel = props => Label({ - ...props, - connections: [[Network, label => label.label = Network.wifi?.ssid || 'Not Connected']], -}); - -export const WifiStrengthLabel = props => Label({ - ...props, - connections: [[Network, label => label.label = `${Network.wifi?.strength || -1}`]], -}); - -export const WiredIndicator = ({ - connecting = Icon('network-wired-acquiring-symbolic'), - disconnected = Icon('network-wired-no-route-symbolic'), - disabled = Icon('network-wired-disconnected-symbolic'), - connected = Icon('network-wired-symbolic'), - unknown = Icon('content-loading-symbolic'), -} = {}) => Stack({ - items: [ - ['unknown', unknown], - ['disconnected', disconnected], - ['disabled', disabled], - ['connected', connected], - ['connecting', connecting], - ], - connections: [[Network, stack => { - if (!Network.wired) - return; - - const { internet } = Network.wired; - if (internet === 'connected' || internet === 'connecting') - return stack.shown = internet; - - if (Network.connectivity !== 'full') - return stack.shown = 'disconnected'; - - return stack.shown = 'disabled'; - }]], -}); - -export const WifiIndicator = ({ - disabled = Icon('network-wireless-disabled-symbolic'), - disconnected = Icon('network-wireless-offline-symbolic'), - connecting = Icon('network-wireless-acquiring-symbolic'), - connected = [ - ['80', Icon('network-wireless-signal-excellent-symbolic')], - ['60', Icon('network-wireless-signal-good-symbolic')], - ['40', Icon('network-wireless-signal-ok-symbolic')], - ['20', Icon('network-wireless-signal-weak-symbolic')], - ['0', Icon('network-wireless-signal-none-symbolic')], - ], -} = {}) => Stack({ - items: [ - ['disabled', disabled], - ['disconnected', disconnected], - ['connecting', connecting], - ...connected, - ], - connections: [[Network, stack => { - if (!Network.wifi) - return; - - const { internet, enabled, strength } = Network.wifi; - if (internet === 'connected') { - for (const threshold of [80, 60, 40, 20, 0]) { - if (strength >= threshold) - return stack.shown = `${threshold}`; - } - } - - if (internet === 'connecting') - return stack.shown = 'connecting'; - - if (enabled) - return stack.shown = 'disconnected'; - - return stack.shown = 'disabled'; - }]], -}); - -export const Indicator = ({ - wifi = WifiIndicator(), - wired = WifiIndicator(), -} = {}) => Stack({ - items: [ - ['wired', wired], - ['wifi', wifi], - ], - connections: [[Network, stack => { - stack.shown = Network.primary || 'wifi'; - }]], -}); - -export const WifiToggle = props => Button({ - ...props, - onClicked: Network.toggleWifi, - connections: [[Network, button => { - button.toggleClassName('on', Network.wifi?.enabled); - }]], -}); - -const icons = [ - { value: 80, icon: 'network-wireless-signal-excellent-symbolic' }, - { value: 60, icon: 'network-wireless-signal-good-symbolic' }, - { value: 40, icon: 'network-wireless-signal-ok-symbolic' }, - { value: 20, icon: 'network-wireless-signal-weak-symbolic' }, - { value: 0, icon: 'network-wireless-signal-none-symbolic' }, -]; - -export const WifiSelection = props => Box({ - ...props, - vertical: true, - connections: [[Network, box => box.children = - Network.wifi?.accessPoints.map(ap => Button({ - onClicked: `nmcli device wifi connect ${ap.bssid}`, - child: Box({ - children: [ - Icon(icons.find(({ value }) => value <= ap.strength).icon), - Label(ap.ssid), - ap.active && Icon({ - icon: 'object-select-symbolic', - hexpand: true, - halign: 'end', - }), - ], - }), - })), - ]], -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/modules/notifications.js b/home/isabel/programs/gui/confs/bars/ags/config/modules/notifications.js deleted file mode 100644 index 130d076dd..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/modules/notifications.js +++ /dev/null @@ -1,247 +0,0 @@ -const { GLib } = imports.gi; -const { Notifications } = ags.Service; -const { lookUpIcon, timeout } = ags.Utils; -const { Box, Icon, Label, EventBox, Button, Stack, Revealer } = ags.Widget; - -const NotificationIcon = ({ appEntry, appIcon, image }) => { - if (image) { - return Box({ - valign: 'start', - hexpand: false, - className: 'icon img', - style: ` - background-image: url("${image}"); - background-size: contain; - background-repeat: no-repeat; - background-position: center; - min-width: 78px; - min-height: 78px; - `, - }); - } - - let icon = 'dialog-information-symbolic'; - if (lookUpIcon(appIcon)) - icon = appIcon; - - if (lookUpIcon(appEntry)) - icon = appEntry; - - return Box({ - valign: 'start', - hexpand: false, - className: 'icon', - style: ` - min-width: 78px; - min-height: 78px; - `, - children: [Icon({ - icon, size: 58, - halign: 'center', hexpand: true, - valign: 'center', vexpand: true, - })], - }); -}; - -const Notification = ({ id, summary, body, actions, urgency, time, ...icon }) => EventBox({ - className: `notification ${urgency}`, - onPrimaryClick: () => Notifications.dismiss(id), - properties: [['hovered', false]], - onHover: w => { - if (w._hovered) - return; - - timeout(300, () => w._hovered = true); - }, - onHoverLost: w => { - if (!w._hovered) - return; - - w._hovered = false; - Notifications.dismiss(id); - }, - vexpand: false, - child: Box({ - vertical: true, - children: [ - Box({ - children: [ - NotificationIcon(icon), - Box({ - hexpand: true, - vertical: true, - children: [ - Box({ - children: [ - Label({ - className: 'title', - xalign: 0, - justification: 'left', - hexpand: true, - maxWidthChars: 24, - ellipsize: 3, - wrap: true, - label: summary, - useMarkup: summary.startsWith('<'), - }), - Label({ - className: 'time', - valign: 'start', - label: GLib.DateTime.new_from_unix_local(time).format('%H:%M'), - }), - Button({ - className: 'close-button', - valign: 'start', - child: Icon('window-close-symbolic'), - onClicked: () => Notifications.close(id), - }), - ], - }), - Label({ - className: 'description', - hexpand: true, - useMarkup: true, - xalign: 0, - justification: 'left', - label: body, - wrap: true, - }), - ], - }), - ], - }), - Box({ - className: 'actions', - children: actions.map(action => Button({ - className: 'action-button', - onClicked: () => Notifications.invoke(id, action.id), - hexpand: true, - child: Label(action.label), - })), - }), - ], - }), -}); - -export const NotificationList = props => Box({ - ...props, - vertical: true, - vexpand: true, - className: 'notification-list', - connections: [[Notifications, box => { - box.children = Array.from(Notifications.notifications.values()) - .map(n => Notification(n)); - - box.visible = Notifications.notifications.size > 0; - }]], -}); - -export const PopupList = ({ transition = 'slide_down' } = {}) => Box({ - className: 'notifications-popup-list', - style: 'padding: 1px', - children: [ - Revealer({ - transition, - child: Box({ - vertical: true, - properties: [ - ['map', new Map()], - ['dismiss', (box, id, force = false) => { - if (!id || !box._map.has(id)) - return; - - if (box._map.get(id)._hovered && !force) - return; - - if (box._map.size - 1 === 0) - box.get_parent().reveal_child = false; - - timeout(200, () => { - box._map.get(id)?.destroy(); - box._map.delete(id); - }); - }], - ['notify', (box, id) => { - if (!id) - return; - - if (box._map.has(id)) - box._map.get(id).destroy(); - - const widget = Notification(Notifications.notifications.get(id)); - box._map.set(id, widget); - box.add(widget); - box.show_all(); - - timeout(10, () => { - box.get_parent().reveal_child = true; - }); - }], - ], - 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'], - ], - }), - }), - ], -}); - -export const Placeholder = props => Box({ - className: 'placeholder', - vertical: true, - valign: 'center', - vexpand: true, - halign: 'center', - hexpand: true, - ...props, - children: [ - Label({ label: '󰂛', className: 'icon' }), - Label('Your inbox is empty'), - ], - connections: [ - [Notifications, box => box.visible = Notifications.notifications.size === 0], - ], -}); - -export const ClearButton = props => Button({ - ...props, - onClicked: Notifications.clear, - connections: [[Notifications, button => button.sensitive = Notifications.notifications.size > 0]], - child: Box({ - children: [ - Label('Clear '), - Stack({ - items: [ - ['true', Icon('user-trash-full-symbolic')], - ['false', Icon('user-trash-symbolic')], - ], - connections: [[Notifications, stack => { - stack.shown = `${Notifications.notifications.size > 0}`; - }]], - }), - ], - }), -}); - -export const DNDIndicator = ({ - silent = Icon('notifications-disabled-symbolic'), - noisy = Icon('preferences-system-notifications-symbolic'), -} = {}) => Stack({ - items: [ - ['true', silent], - ['false', noisy], - ], - connections: [[Notifications, stack => { - stack.shown = `${Notifications.dnd}`; - }]], -}); - -export const DNDToggle = props => Button({ - ...props, - onClicked: () => { Notifications.dnd = !Notifications.dnd; }, - connections: [[Notifications, button => { - button.toggleClassName('on', Notifications.dnd); - }]], -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/modules/onscreenindicator.js b/home/isabel/programs/gui/confs/bars/ags/config/modules/onscreenindicator.js deleted file mode 100644 index 477fc7796..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/modules/onscreenindicator.js +++ /dev/null @@ -1,114 +0,0 @@ -const { Service } = ags; -const { timeout, lookUpIcon, connect } = ags.Utils; -const { Box, Revealer, Stack, Icon } = ags.Widget; -import { FontIcon, Progress } from './misc.js'; - -class IndicatorService extends Service { - static { - Service.register(this, { - 'popup': ['double', 'string'], - }); - } - - _delay = 1500; - _count = 0; - - popup(value, icon) { - this.emit('popup', value, icon); - this._count++; - timeout(this._delay, () => { - this._count--; - - if (this._count === 0) - this.emit('popup', -1, icon); - }); - } - - speaker() { - const value = ags.Service.Audio.speaker.volume; - const icon = value => { - const icons = []; - icons[0] = 'audio-volume-muted-symbolic'; - icons[1] = 'audio-volume-low-symbolic'; - icons[34] = 'audio-volume-medium-symbolic'; - icons[67] = 'audio-volume-high-symbolic'; - icons[101] = 'audio-volume-overamplified-symbolic'; - for (const i of [101, 67, 34, 1, 0]) { - if (i <= value * 100) - return icons[i]; - } - }; - this.popup(value, icon(value)); - } - - display() { - // brightness is async, so lets wait a bit - timeout(10, () => { - const value = ags.Service.Brightness.screen; - const icon = value => { - const icons = ['󰛩', '󱩎', '󱩏', '󱩐', '󱩑', '󱩒', '󱩓', '󱩔', '󱩕', '󱩖', '󰛨']; - return icons[Math.ceil(value * 10)]; - }; - this.popup(value, icon(value)); - }); - } - - kbd() { - // brightness is async, so lets wait a bit - timeout(10, () => { - const value = ags.Service.Brightness.kbd; - this.popup((value * 33 + 1) / 100, 'keyboard-brightness-symbolic'); - }); - } - - connectWidget(widget, callback) { - connect(this, widget, callback, 'popup'); - } -} - -class Indicator { - static { Service.export(this, 'Indicator'); } - static instance = new IndicatorService(); - static popup(value, icon) { Indicator.instance.popup(value, icon); } - static speaker() { Indicator.instance.speaker(); } - static display() { Indicator.instance.display(); } - static kbd() { Indicator.instance.kbd(); } -} - -export const OnScreenIndicator = ({ height = 300, width = 48 } = {}) => Box({ - className: 'indicator', - style: 'padding: 1px;', - children: [Revealer({ - transition: 'slide_left', - connections: [[Indicator, (revealer, value) => { - revealer.revealChild = value > -1; - }]], - child: Progress({ - width, - height, - vertical: true, - connections: [[Indicator, (progress, value) => progress.setValue(value)]], - child: Stack({ - valign: 'start', - halign: 'center', - hexpand: false, - items: [ - ['true', Icon({ - halign: 'center', - size: width, - connections: [[Indicator, (icon, _v, name) => icon.icon = name || '']], - })], - ['false', FontIcon({ - halign: 'center', - hexpand: true, - style: `font-size: ${width}px;`, - connections: [[Indicator, ({ label }, _v, name) => label.label = name || '']], - })], - ], - connections: [[Indicator, (stack, _v, name) => { - stack.shown = `${!!lookUpIcon(name)}`; - }]], - }), - }), - })], -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/modules/wallpaper.js b/home/isabel/programs/gui/confs/bars/ags/config/modules/wallpaper.js deleted file mode 100644 index 05c7504a3..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/modules/wallpaper.js +++ /dev/null @@ -1,13 +0,0 @@ -import { Theme } from '../theme/theme.js'; -const { Box } = ags.Widget; - -export const Wallpaper = props => Box({ - className: 'wallpaper', - ...props, - connections: [[Theme, box => { - box.setStyle(` - background-image: url('${Theme.getSetting('wallpaper')}'); - background-size: cover; - `); - }]], -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/scss/common.scss b/home/isabel/programs/gui/confs/bars/ags/config/scss/common.scss index ee2d8f4a2..96bca5e14 100644 --- a/home/isabel/programs/gui/confs/bars/ags/config/scss/common.scss +++ b/home/isabel/programs/gui/confs/bars/ags/config/scss/common.scss @@ -1,316 +1,371 @@ window { - background-color: transparent; + background-color: transparent; } -@mixin common{ - all: unset; +@mixin common { + all: unset; - * { - font-size: $font_size; - font-family: $font, sans-serif; - } + * { + font-size: $font_size; + font-family: $font, sans-serif; + } } -@mixin widget{ - @include common; - border-radius: $radii; - color: $fg_color; - background-color: $widget_bg; - border: $border; +@mixin widget { + @include common; + border-radius: $radii; + color: $fg_color; + background-color: $widget_bg; + border: $border; } @mixin button_focus() { - box-shadow: inset 0 0 0 $border_width $accent; - background-color: $hover; - color: $hover_fg; + 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; + 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; + 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); + box-shadow: none; + background-color: transparent; + color: transparentize($fg_color, 0.7); } -@mixin button($flat: false, $reactive: true, $radii: $radii, $focusable: true){ - @include common; - 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; - } +@mixin button($flat: false, $reactive: true, $radii: $radii, $focusable: true) { + @include common; + 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; + } } -@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; - } - } - } +@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; + } + } + } } @mixin floating_widget { - @include common; - - @if $drop_shadow { - box-shadow: 0 0 6px 0 $shadow; - } - margin: max($spacing, 8px); - border: $border_width solid $popover_border_color; - border-radius: $popover_radius; - background-color: $bg_color; - color: $fg_color; - padding: $popover_padding; + @include common; + + @if $drop_shadow { + box-shadow: 0 0 min(6px, $spacing/2) 0 $shadow; + } + margin: max($spacing, 8px); + border: $border_width solid $popover_border_color; + border-radius: $popover_radius; + background-color: $bg_color; + color: $fg_color; + padding: $popover_padding; } -@mixin slider($width: .7em, $slider_width: .5em, $gradient: $active_gradient, $slider: true, $focusable: true, $radii: $radii){ - @include common; - * { all:unset; } - - 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; - } - - slider { - @if $slider { - background-color: transparentize($fg_color, 0.5); - } - } - } - - @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; - } - } - } - - } +@mixin slider( + $width: 0.7em, + $slider_width: 0.5em, + $gradient: $active_gradient, + $slider: true, + $focusable: true, + $radii: $radii +) { + @include common; + * { + all: unset; + } + + 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; + } + } + } + } } -@mixin shader($width: 3em){ - @include common; +@mixin shader($width: 3em) { + @include common; + border-radius: max($radii - $border_width, 0); - label { - color: $shader_fg; - text-shadow: $text_shadow; - } + label { + color: $shader_fg; + text-shadow: $text_shadow; + } - @if $theme == 'dark' { - box-shadow: inset 0 0 $width $width/3 transparentize($bg_color, 0.3); - } + @if $theme == "dark" { + box-shadow: inset 0 0 $width $width/3 transparentize($bg_color, 0.2); + } - @if $theme == 'light' { - background-color: transparentize($bg_color, 0.8); - } + @if $theme == "light" { + background-color: transparentize($bg_color, 0.8); + } } -@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; +@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; } -@mixin scrollbar{ - scrollbar, scrollbar * { - all: unset; - } - - scrollbar.vertical{ - slider{ - background: $widget_bg; - border-radius: $radii; - min-width: .6em; - min-height: 2em; - transition: $transition; - - &:hover { - background-color: transparentize($fg_color, 0.6); - min-width: .8em; - } - } - } +@mixin scrollbar { + 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; + } } -@mixin switch{ - @include button; +@mixin switch { + @include button; - slider { - background-color: $fg_color; - border-radius: $radii; - min-width: 24px; - min-height: 24px; - } + slider { + background-color: $fg_color; + border-radius: $radii; + min-width: 24px; + min-height: 24px; + } - image { color: transparent; } + image { + color: transparent; + } } +@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); + } +} tooltip { - @include common; - 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; - } + @include common; + * { + 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; + } } window.popup { - > * { - border: none; - box-shadow: none; - } - - menu { - border-radius: $popover_radius; - background-color: $bg_color; - padding: $spacing; - border: $border; - - menuitem { - @include button; - padding: $spacing/2; - margin: $spacing/2 0; - > * { margin-left: -30px; } - &:first-child { margin-top: 0; } - &:last-child { margin-bottom: 0; } - } - } + > * { + border: none; + box-shadow: none; + } + + menu { + border-radius: $popover_radius; + background-color: $bg_color; + padding: $spacing; + border: $border; + + 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/isabel/programs/gui/confs/bars/ags/config/scss/main.scss b/home/isabel/programs/gui/confs/bars/ags/config/scss/main.scss index affcae47a..63779b627 100644 --- a/home/isabel/programs/gui/confs/bars/ags/config/scss/main.scss +++ b/home/isabel/programs/gui/confs/bars/ags/config/scss/main.scss @@ -1,12 +1,12 @@ -@import './generated'; -@import './common'; -@import './widgets/notifications'; -@import './widgets/media'; -@import './widgets/datemenu'; -@import './widgets/applauncher'; -@import './widgets/quicksettings'; -@import './widgets/powermenu'; -@import './widgets/desktop'; -@import './widgets/dashboard'; -@import './widgets/bar'; -@import './widgets/settings'; +@import "/tmp/ags/scss/generated"; +@import "./common"; +@import "./widgets/notifications"; +@import "./widgets/media"; +@import "./widgets/applauncher"; +@import "./widgets/quicksettings"; +@import "./widgets/powermenu"; +@import "./widgets/desktop"; +@import "./widgets/dashboard"; +@import "./widgets/bar"; +@import "./widgets/settings"; +@import "/tmp/ags/scss/additional"; diff --git a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/applauncher.scss b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/applauncher.scss index 589a4be0b..1dd4ba7c8 100644 --- a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/applauncher.scss +++ b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/applauncher.scss @@ -1,93 +1,87 @@ window#applauncher .applauncher { - @include floating_widget; - - .wallpaper { - margin: $popover_padding; - margin-bottom: 0; - padding: 30px; - border-radius: $radii; - - @if $drop_shadow { - box-shadow: 0 0 0 $border_width $border_color, - inset 0 0 $spacing 0 $shadow; - } - - @else { - box-shadow: 0 0 0 $border_width $border_color; - } - - image { - @include widget; - border-radius: $radii/2; - background-color: transparentize($bg_color, 0.4); - padding: $spacing/2; - margin-right: $spacing; - -gtk-icon-transform: scale(0.8); - } - - entry { - @include widget; - border-radius: $radii/2; - background-color: transparentize($bg_color, 0.4); - transition: $transition; - padding: $spacing/2; - } - } - - .separator { - min-height: 1px; - background-color: $hover; - margin: $spacing/2; - } - - scrolledwindow { - @include scrollbar; - padding: $popover_padding; - min-width: 500px; - min-height: 350px; - } - - .app { - all: unset; - transition: $transition; - padding: $spacing; - - label { - transition: $transition; - - &.title { - color: $fg_color; - } - - &.description { - color: transparentize($fg_color, 0.3); - } - } - - image { - transition: $transition; - margin-right: $spacing; - } - - &: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; - } - } - } + @include floating_widget; + + .header { + margin: $popover_padding; + margin-bottom: $popover_padding/2; + + image, + entry { + @include widget; + padding: $spacing/2; + } + + entry { + padding-left: $spacing; + } + + image { + margin-right: $spacing; + -gtk-icon-transform: scale(0.8); + font-size: $font-size * 1.6; + } + } + + .separator { + min-height: 1px; + background-color: $hover; + margin: $spacing/2; + } + + scrolledwindow { + @include scrollbar; + padding: $popover_padding; + min-width: 500px; + min-height: 350px; + } + + .placeholder { + margin-top: $spacing; + color: $fg_color; + font-size: 1.2em; + } + + .app { + all: unset; + transition: $transition; + padding: $spacing; + + label { + transition: $transition; + + &.title { + color: $fg_color; + } + + &.description { + color: transparentize($fg_color, 0.3); + } + } + + image { + transition: $transition; + margin-right: $spacing; + } + + &: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/isabel/programs/gui/confs/bars/ags/config/scss/widgets/bar.scss b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/bar.scss index 7e59430af..bf07a7f97 100644 --- a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/bar.scss +++ b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/bar.scss @@ -1,301 +1,293 @@ -$float: 5px; +$float: $spacing * 0.7; @mixin panel_button($flat: false, $reactive: true) { - all: unset; - - @if $bar_style =='separated' { - transition: $transition; - - >* { - @include floating_widget; - border-radius: $radii; - margin: $wm_gaps $float; - transition: $transition; - } - - &:hover>* { - color: $hover_fg; - - @if $drop_shadow { - box-shadow: 0 0 $wm_gaps/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); - - >* { - margin: $float; - } - } - - label { - font-weight: bold; - } - - image { - font-size: $font-size * 1.2; - } - - >* { - padding: .3em .5em; - } + all: unset; + + @if $bar_style == "separated" { + transition: $transition; + + > * { + @include floating_widget; + border-radius: $radii; + margin: $wm_gaps $float; + 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); + + > * { + margin: $float; + } + } + + label { + font-size: $font-size; + font-weight: bold; + } + + image { + font-size: $font-size * 1.2; + } + + > * { + padding: 0.3em 0.5em; + } } .panel { - @if $bar_style =='normal' { - background-color: $bg_color; - } - - @if not $screen_corners and $bar_style =='normal' { - border-bottom: $border; - } - - @if $bar_style =='floating' { - @include floating_widget; - 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($flat: true); - } - - .quicksettings>box>* { - @if $layout !='leftbar' { - margin: 0 $spacing/2; - - &:last-child { - margin-right: 0; - } - - &:first-child { - margin-left: 0; - } - } - - @else { - margin: $spacing/2 0; - - &:last-child { - margin-right: 0; - } - - &:first-child { - margin-left: 0; - } - } - } - - .separator { - @if $bar_style =='separated' { - background-color: transparent; - } - - @else { - background-color: transparentize($fg_color, 0.7); - } - - @if $layout =='leftbar' { - min-height: 5px; - min-width: 22px; - } - - @else { - min-height: 22px; - min-width: 5px; - } - - border-radius: $radii; - - } - - .launcher { - label { - color: transparentize($accent, 0.2); - } - - &:hover label { - color: $accent; - } - - &:active label, - &.active label { - color: $accent_fg; - } - } - - .powermenu { - image { - color: transparentize($red, 0.3); - } - - &:hover image { - color: transparentize($red, 0.15); - } - - &:active image { - color: $red; - } - } - - .quicksettings:not(.active) .battery { - &.low { - color: $red; - } - - &.charged, - &.charging { - color: $green; - } - } - - .workspaces { - >* { - padding: 0; - } - - @if $layout =='leftbar' { - padding-left: 4px; - } - - .eventbox { - transition: $transition; - - @if $bar_style =='separated' { - border-radius: max($radii - $border_width, 0); - - &:hover { - background-color: $hover; - } - } - - @else { - @include button; - } - } - - button { - all: unset; - - .indicator { - min-width: 10px; - min-height: 10px; - border-radius: $radii*0.6; - border: 2px solid transparent; - transition: border-color $transition; - - @if $layout =='leftbar' { - margin: $spacing/2 $spacing/1.5; - } - - @else { - margin: 0 $spacing/2; - } - - .fill { - transition: background-color $transition; - margin: 2px; - min-width: 6px; - min-height: 6px; - border-radius: max($radii*0.7 - 4px, 0); - } - } - - @if $layout !='leftbar' { - &:last-child .indicator { - margin-right: $spacing; - } - - &:first-child .indicator { - margin-left: $spacing; - } - } - - @else { - &:last-child .indicator { - margin-bottom: $spacing; - } - - &:first-child .indicator { - margin-top: $spacing; - } - } - - &.empty .indicator { - border-color: transparentize($fg_color, 0.3); - } - - &.occupied .indicator { - border-color: transparentize($fg_color, 0.1); - - .fill { - background-color: transparentize($fg_color, 0.1) - } - } - - &:hover .indicator { - border-color: transparentize($accent, 0.2); - - .fill { - background-color: transparentize($accent, 0.2) - } - } - - &.active .indicator, - &:active .indicator { - border-color: $accent; - - .fill { - background-color: $accent - } - } - - &.empty .indicator .fill { - background-color: transparent; - } - } - } - - .media { - &.spotify .icon { - color: $green; - } - - &.firefox .icon { - color: $orange; - } - - &.mpv .icon { - color: $magenta; - } - } + @if $bar_style == "normal" { + background-color: $bg_color; + } + + @if not $screen_corners and $bar_style == "normal" { + @if $layout == "bottombar" { + border-top: $border; + } @else { + border-bottom: $border; + } + } + + @if $bar_style == "floating" { + @include floating_widget; + 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($flat: true); + } + + separator { + background-color: transparentize($fg_color, 0.98); + border-radius: $radii; + min-height: 5px; + min-width: 5px; + } + + .quicksettings > box > * { + margin: 0 $spacing/2; + + &:last-child { + margin-right: 0; + } + + &:first-child { + margin-left: 0; + } + } + + .applauncher { + label { + color: transparentize($accent, 0.2); + } + + &:hover label { + color: $accent; + } + + &:active label, + &.active label { + color: $accent_fg; + } + } + + .powermenu { + image { + color: transparentize($red, 0.3); + } + + &:hover image { + color: transparentize($red, 0.15); + } + + &:active image { + color: $red; + } + } + + /* 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 { + image { + margin-right: $spacing/2; + } + + .font-icon { + font-size: 1.3em; + } + + levelbar trough { + @include widget; + min-width: 60px; + min-height: 14px; + + 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); + } + } + + .workspaces { + > * { + padding: 0; + } + + .eventbox { + transition: $transition; + + @if $bar_style == "separated" { + border-radius: max($radii - $border_width, 0); + + &:hover { + background-color: $hover; + } + } @else { + @include button($flat: true); + } + } + + button { + all: unset; + + .indicator { + font-size: 0; + min-width: 6px; + min-height: 6px; + border-radius: $radii * 0.6; + border: $border; + margin: 0 $spacing/2; + transition: $transition/2; + background-color: transparentize($fg_color, 0.8); + } + + &:last-child .indicator { + margin-right: $spacing; + } + + &:first-child .indicator { + margin-left: $spacing; + } + + &.occupied .indicator { + background-color: transparentize($fg_color, 0.2); + min-width: 8px; + min-height: 8px; + } + + &: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: 12px; + } + } + } } diff --git a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/dashboard.scss b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/dashboard.scss index 3cc20c456..6fce64cac 100644 --- a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/dashboard.scss +++ b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/dashboard.scss @@ -1,68 +1,151 @@ +@mixin calendar { + @include widget; + padding: $spacing * 2 $spacing * 2 0; + + calendar { + all: unset; + + &.button { + @include button($flat: true); + margin: 1em; + } + + &:selected { + @include button($flat: false); + } + + &.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 .dashboard { - @include floating_widget; - - .notifications { - @include notifications; - min-width: 450px; - - .header { - padding-left: .3em; - margin-bottom: $spacing; - } - - .notification-list-box { - @include widget; - - .wallpaper { - border-radius: max($radii - $border_width, 0); - background-position: bottom right; - - @if $drop_shadow { - box-shadow: inset 0 0 $spacing 0 $shadow; - } - } - } - - .notification-list { - padding: $spacing/2; - - .notification>box { - @include floating_widget; - border-radius: $radii; - padding: $spacing; - margin: $spacing/2; - } - } - - .placeholder { - color: $wallpaper_fg; - - .icon { - font-size: 7em - } - - label { - @if $drop_shadow { - text-shadow: $text_shadow; - } - - @else { - @include text_border; - } - - } - } - } - - .separator { - background-color: transparentize($fg_color, 0.94); - min-width: 2px; - border-radius: $radii; - margin: 0 $spacing; - } - - .datemenu { - @include datemenu; - } + @include floating_widget; + + .notifications { + min-width: 450px; + + .header { + padding-left: 0.3em; + margin-bottom: $spacing; + + label { + font-size: 1.2em; + } + + button { + @include button; + padding: $spacing/2 $spacing; + + label { + font-size: 1.2em; + } + } + } + + .notification-scrollable { + @include scrollbar; + + scrollbar, + scrollbar:hover { + border-radius: max($radii - $border_width, 0); + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + + .notification { + @include notification; + + > box { + @include widget; + margin: $spacing/2 0; + padding: $spacing; + } + } + } + + .placeholder { + color: $wallpaper_fg; + + image { + font-size: 7em; + } + + label { + font-size: 1.2em; + } + + label, + image { + @if $drop_shadow { + text-shadow: $text_shadow; + -gtk-icon-shadow: $text_shadow; + } @else { + @include text_border; + } + } + } + } + + separator { + background-color: $popover_border_color; + min-width: 2px; + border-radius: $radii; + margin: 0 $spacing; + } + + .clock { + font-size: 5em; + } + + .uptime { + font-size: 2em; + color: transparentize($fg_color, 0.2); + } + + .calendar { + @include calendar; + + margin-top: $spacing * 2; + } + + .circular-progress-box { + @include widget; + margin-top: $spacing; + margin-right: $spacing; + + &:last-child { + margin-right: 0; + } + + padding: $spacing; + + .circular-progress { + min-height: $spacing * 8; + min-width: $spacing * 8; + margin: $spacing/2; + font-size: $spacing; + background-color: $bg_color; + color: $accent; + image { + font-size: 1.8em; + } + } + } } diff --git a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/datemenu.scss b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/datemenu.scss deleted file mode 100644 index b713a3fcb..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/datemenu.scss +++ /dev/null @@ -1,58 +0,0 @@ -@mixin calendar { - @include widget; - padding: $spacing*2 $spacing*2 0; - - calendar { - all: unset; - - &.button { - @include button($flat: true); - margin: 1em; - } - - &:selected { - background-color: $hover; - 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: .2em; - } -} - -@mixin datemenu { - .clock { - font-size: 5em; - } - - .uptime { - font-size: 2em; - color: transparentize($fg_color, 0.2); - } - - .calendar { - @include calendar; - - margin-top: $spacing*2; - } -} - -window#datemenu .datemenu { - @include floating_widget; - @include datemenu; -} \ No newline at end of file diff --git a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/desktop.scss b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/desktop.scss index d2413853f..40ab31082 100644 --- a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/desktop.scss +++ b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/desktop.scss @@ -1,51 +1,23 @@ window.corner .corner { - background-color: if($screen_corners, $bg_color, transparent); - border-radius: if($screen_corners, $radii*2, 0); -} - -.desktop { - @if $bar_style =='normal' { - border-radius: if($screen_corners, $popover_radius, 0); - box-shadow: inset 0 0 $spacing 0 $shadow; - } - - @if $drop_shadow { - label { - text-shadow: $text_shadow; - } - } - - @else { - - .separator { - border: $border; - } - - label { - @include text_border; - } - } + background-color: if($screen_corners, $bg_color, transparent); + border-radius: if($screen_corners, $radii * 2, 0); } window.indicator .progress { - @include floating_widget; - padding: $spacing/2; - - .fill { - border-radius: max($popover_radius - $spacing/2, 0); - background-color: $accent; - color: $accent_fg; - - image { - -gtk-icon-transform: scale(0.7); - } - - .icon overlay { - font-size: 34px; - - label { - font-size: 34px; - } - } - } + @include floating_widget; + padding: $spacing/2; + + .fill { + border-radius: max($popover_radius - $spacing/2, 0); + background-color: $accent; + color: $accent_fg; + + image { + -gtk-icon-transform: scale(0.7); + } + + .font-icon { + font-size: 34px; + } + } } diff --git a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/media.scss b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/media.scss index 318f998e0..4d525b5e1 100644 --- a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/media.scss +++ b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/media.scss @@ -1,114 +1,130 @@ @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); - } + 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() { - label { - color: $shader_fg; - text-shadow: $text_shadow; - } - - .shader { - @include shader; - } - - .cover-art { - border-radius: $radii*0.8; - min-height: 100px; - min-width: 100px; - box-shadow: 2px 2px 2px 0 $shadow; - margin: $spacing; - margin-bottom: 0; - - .shader { - background-color: transparent; - border-radius: max($radii*0.8 - 1px, 0); - box-shadow: inset 0 0 0 999px transparentize($bg_color, 0.8); - } - } - - .cover-art-bg, .cover-art { - background-size: cover; - background-position: center; - } - - .labels { - margin-top: $spacing; - - label { - font-size: 1.1em; - text-shadow: $text_shadow; - - &.title { - font-weight: bold; - } - } - } - - .position-slider { - @include slider($width: .4em, $slider: false, $gradient: linear-gradient($shader_fg, $shader_fg), $radii: 0); - margin: $spacing 0; - - trough { - border: none; - background-color: transparentize($shader_fg, 0.7); - } - } - - .footer-box { - margin: -$spacing/2 $spacing $spacing/2; - - image { - -gtk-icon-shadow: $text_shadow; - } - } - - .controls button { - all: 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); } - - &.firefox .footer-box { - margin-top: -$spacing*2; - } + @include widget; + + label { + color: $shader_fg; + text-shadow: $text_shadow; + } + + .shader { + @include shader; + } + + .cover { + border-radius: $radii * 0.8; + min-height: 100px; + min-width: 100px; + box-shadow: 2px 2px 2px 0 $shadow; + margin: $spacing; + margin-bottom: 0; + + .shader { + background-color: transparent; + border-radius: max($radii * 0.8 - 1px, 0); + box-shadow: inset 0 0 0 999px transparentize($bg_color, 0.8); + } + } + + .blurred-cover, + .cover { + background-size: cover; + background-position: center; + border-radius: max($radii - $border_width, 0); + } + + .labels { + margin-top: $spacing; + + 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: $spacing 0; + + trough { + border: none; + background-color: transparentize($shader_fg, 0.7); + } + } + + .footer-box { + margin: -$spacing/2 $spacing $spacing/2; + + image { + -gtk-icon-shadow: $text_shadow; + } + } + + .controls button { + all: 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/isabel/programs/gui/confs/bars/ags/config/scss/widgets/notifications.scss b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/notifications.scss index 1dd84ada3..27b1a9e54 100644 --- a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/notifications.scss +++ b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/notifications.scss @@ -1,113 +1,94 @@ @mixin notification() { - &.critical > box { - box-shadow: inset 0 0 .5em 0 $red; - } - - > box { - border-radius: $radii/2; - padding: $spacing; - } - - &:hover { - .close-button{ - @include button_hover; - background-color: transparentize($red, .5); - } - } - - .title { - margin-right: $spacing; - color: $fg_color; - font-size: 1.1em; - } - - .time { - color: transparentize($fg_color, .2); - } - - .description { - font-size: .9em; - color: transparentize($fg_color, .2); - } - - .icon { - border-radius: $radii*0.8; - margin-right: $spacing; - - &.img { - border: $border; - } - } - - .actions button { - @include button; - border-radius: $radii*0.8; - font-size: 1.2em; - padding: $spacing/2 $spacing; - margin: $spacing $spacing/2 0; - - &:first-child { - margin-left: 0; - } - - &:last-child { - margin-right: 0; - } - } - - button.close-button { - @include button($flat: true); - margin-left: $spacing; - border-radius: $radii*0.8; - min-width: 1.2em; - min-height: 1.2em; - - &:hover { - background-color: transparentize($red, .5); - } - - &:active { - background-image: linear-gradient($red, $red); - } - } + &.critical > box { + box-shadow: inset 0 0 0.5em 0 $red; + } + + > box { + border-radius: $radii/2; + padding: $spacing; + } + + &:hover { + .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; + } + } + } + + .actions { + padding-top: $spacing; + + button { + @include button; + border-radius: $radii * 0.8; + font-size: 1.2em; + padding: $spacing/2 0; + margin: 0 $spacing/2 0; + + &:first-child { + margin-left: 0; + } + + &:last-child { + margin-right: 0; + } + } + } + + button.close-button { + @include button($flat: true); + margin-left: $spacing; + border-radius: $radii * 0.8; + min-width: 1.2em; + min-height: 1.2em; + + &:hover { + background-color: transparentize($red, 0.5); + } + + &:active { + background-image: linear-gradient($red, $red); + } + } } -@mixin notifications { - .header { - label { - font-size: 1.2em; - } - - button { - @include button; - padding: $spacing/2 $spacing; - - label { - font-size: 1.2em; - } - } - } - - .notification-list { - @include scrollbar; - - .notification { - @include notification; - } - } -} - -.notifications-popup-list{ - .notification { - @include notification; +.notifications-popup-list { + .notification { + @include notification; - > box { - @include floating_widget; - border-radius: $radii; - } + > box { + @include floating_widget; + border-radius: $radii; + } - .description { - min-width: 350px; - } - } + .description { + min-width: 350px; + } + } } diff --git a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/powermenu.scss b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/powermenu.scss index 77d30db25..80a7018e4 100644 --- a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/powermenu.scss +++ b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/powermenu.scss @@ -1,76 +1,88 @@ -window#powermenu, window#verification { - .shader { - min-width: 4000px; - min-height: 4000px; - background-color: rgba(0, 0, 0, 0.05); - } +window#powermenu, +window#verification { + .shader { + background-color: rgba(0, 0, 0, 0.05); + } } window#verification .verification { - @include floating_widget; - padding: $popover_padding*1.2; - min-width: 300px; - min-height: 100px; + @include floating_widget; + padding: $popover_padding * 1.2; + min-width: 300px; + min-height: 100px; - .title { - font-size: 1.7em; - } + .title { + font-size: 1.7em; + } - .desc { - color: transparentize($fg_color, 0.1); - font-size: 1.2em; - } + .desc { + color: transparentize($fg_color, 0.1); + font-size: 1.2em; + } - .buttons { - margin-top: $spacing*2; + .buttons { + margin-top: $spacing * 2; - button { - @include button; - font-size: 1.6em; - padding: $spacing; - margin: 0 $popover_padding*1.2/2; + button { + @include button; + font-size: 1.6em; + padding: $spacing; + margin: 0 $popover_padding * 1.2/2; - &:first-child { - margin-left: 0; - } + &:first-child { + margin-left: 0; + } - &:last-child { - margin-right: 0; - } - } - } + &:last-child { + margin-right: 0; + } + } + } } window#powermenu .powermenu { - @include floating_widget; - padding: $popover_padding; - border-radius: $radii*3; + @include floating_widget; + padding: $popover_padding; + border-radius: $radii * 3; - button { - @include common; + button { + @include common; - image { - @include button; - margin: $popover_padding; - margin-bottom: $popover_padding/2; - border-radius: $radii*2; - min-width: 120px; - min-height: 120px; - } + image { + @include button; + margin: $popover_padding; + margin-bottom: $popover_padding/2; + border-radius: $radii * 2; + min-width: 120px; + min-height: 120px; + font-size: 68px; + } - label, image { - color: transparentize($fg_color, 0.1); - } + 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; } + &:hover { + image { + @include button_hover; + } + label { + color: $fg_color; + } + } + &:focus image { + @include button_focus; + } + &:active image { + @include button_active; + } - &:focus, &:active { - label{ color: $accent; } - } - } + &:focus, + &:active { + label { + color: $accent; + } + } + } } diff --git a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/quicksettings.scss b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/quicksettings.scss index 25d9b89b9..7150d78db 100644 --- a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/quicksettings.scss +++ b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/quicksettings.scss @@ -1,243 +1,192 @@ window#quicksettings .quicksettings { - @include floating_widget; - - .header { - > box:last-child { - @include widget; - padding: $spacing; - } - - .avatar { - @include widget; - margin-right: $spacing; - min-width: $spacing*7 + 38px; - - .shader { - @include shader; - } - } - - .user { - font-size: 1.2em; - color: transparentize($fg_color, 0.2); - margin: $spacing/2; - } - - .battery-progress { - progressbar { - @include slider($width: $spacing*3.4); - margin-top: $spacing; - } - - label { - margin-top: $spacing; - color: $accent_fg; - font-size: $spacing*2; - font-weight: bold; - } - - &.half label { color: $fg_color; } - } - - .system { - button, .uptime { - @include button; - padding: $spacing; - margin-left: $spacing; - font-weight: bold; - &:first-child { margin-left: 0; } - } - } - } - - .volume-box { - @include widget; - margin-top: $spacing; - - scale { - @include slider; - margin-right: $spacing; - } - - button { - @include button($flat: true); - padding: $spacing/2; - margin: $spacing/2; - } - - .menu { - all: unset; - border-top: 1px solid $widget_bg; - padding: $spacing; - - .separator { - min-height: 1px; - margin: $spacing/2 0; - background-color: $widget_bg; - } - - button { - @include button($flat: true); - border-radius: $radii*.7; - padding: $spacing/2; - margin-top: $spacing / 2; - &:first-child { margin-top: 0; } - - image { - margin-right: $spacing/2; - } - } - } - } - - .brightness { - @include widget; - margin-top: $spacing; - padding-right: $spacing; - - scale { - @include slider; - margin: 0 $spacing; - margin-left: 0; - } - - button { - @include button($flat: true); - padding: $spacing/2; - margin: $spacing/2; - } - } - - .toggles-box { - margin-top: $spacing; - - .small-toggles { - @include widget; - padding: $spacing/2; - - .toggle { - @include button; - margin: $spacing/2; - padding: $spacing; - } - } - - .arrow-toggles { - @include widget; - padding: $spacing/2; - margin-right: $spacing; - - .toggle.arrow { - @include button; - margin: $spacing/2; - - label { - margin-left: $spacing/2; - font-weight: bold; - } - - button { - @include button($flat: true); - padding: $spacing; - - &: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; - } - } - } - } - } - - .submenu { - @include widget; - margin-top: $spacing; - - .title { - > *:first-child { - margin: $spacing; - } - - label { - font-weight: bold; - font-size: 1.2em; - } - } - - .content { - border-top: 1px solid $widget_bg; - padding: $spacing; - } - - &.app-mixer .content { - scale { - @include slider; - } - - > box { - padding: $spacing; - } - - label:last-child { - min-width: 3em; - } - - image { - margin-right: $spacing; - } - } - - &.network .content, &.theme, .content { - button { - @include button($flat: true); - border-radius: $radii*0.8; - padding: $spacing/2; - margin-top: $spacing / 2; - &:first-child { margin-top: 0; } - } - - image { - margin-right: $spacing/2; - } - } - - &.bluetooth .content { - > box { - padding: $spacing/2; - } - - switch { - @include switch; - } - } - } - - .media { - .mediabox{ - @include widget; - @include media; - margin-top: $spacing; - - .cover-art-bg { - border-radius: max($radii - $border_width, 0); - } - - .shader { - border-radius: max($radii - $border_width, 0); - } - } - } + @include floating_widget; + + .row { + margin-top: $spacing; + &:first-child { + margin-top: 0; + } + } + + .header { + .avatar { + @include widget; + margin-right: $spacing; + min-width: $spacing * 7 + 38px; + + .shader { + @include shader; + } + } + + .battery-progress { + label { + margin-top: $spacing; + color: $accent_fg; + font-size: $spacing * 2; + font-weight: bold; + } + + &.half label { + color: $fg_color; + } + + progressbar { + @include slider($width: $spacing * 3.4); + margin-top: $spacing; + min-height: 20px; + } + + &.low progressbar { + @include slider( + $width: $spacing * 3.4, + $gradient: linear-gradient(to right, $red, $red) + ); + margin-top: $spacing; + min-height: 20px; + } + } + + .system-box { + @include widget; + padding: $spacing; + + button, + .uptime { + @include button; + padding: $spacing; + font-weight: bold; + margin-left: $spacing; + &:first-child { + margin-left: 0; + } + min-height: 20px; + min-width: 20px; + + image { + font-size: 1.2em; + } + } + } + } + + .slider-box { + @include widget; + padding: $spacing; + + > box { + margin: 0; + } + + .slider > * { + margin-left: $spacing; + &:first-child { + margin-left: 0; + } + } + + button, + .icon { + @include button($flat: true); + padding: $spacing/2; + } + + scale { + @include slider; + + &:last-child { + margin-right: $spacing/2; + } + } + + .menu { + background-color: $bg_color; + border: $border_width solid $popover_border_color; + border-radius: $radii; + } + } + + .mixer-item { + margin: 0 $spacing; + scale { + @include slider($width: 7px); + } + > box { + padding: $spacing; + } + label:last-child { + min-width: 3em; + } + image { + font-size: 20px; + } + } + + .menu { + @include widget; + margin-top: $spacing; + padding: $spacing; + + separator { + background-color: $border_color; + margin: $spacing $spacing/2; + } + + label { + margin-left: $spacing; + } + + button { + @include button($flat: true); + padding: $spacing/2; + } + + switch { + @include switch; + } + } + + .toggle-button { + @include button; + margin-right: $spacing; + font-weight: bold; + + label { + margin-left: $spacing/2; + } + + button { + @include button($flat: true); + padding: $spacing; + + &: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: $spacing; + } + + .media .player { + @include media; + margin-top: $spacing; + } } diff --git a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/settings.scss b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/settings.scss index 23ec629c2..f796b3332 100644 --- a/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/settings.scss +++ b/home/isabel/programs/gui/confs/bars/ags/config/scss/widgets/settings.scss @@ -1,99 +1,111 @@ window#settings { - background-color: $bg_color; - color: $fg_color; - - scrolledwindow { - @include scrollbar; - } - - .settings { - .content { - padding: $popover_padding; - } - - .headerbar { - background-color: $widget_bg; - padding: $spacing/2; - border-bottom: $border; - } - - .tab { - @include button($flat: true); - margin: $spacing/2; - padding: $spacing/2; - } - - .wallpaper { - border-radius: max($radii - 1px, 0); - background-position: center; - border: $border - } - - button, entry { - @include button; - padding: $spacing*0.7; - } - - spinbutton, spinbutton:focus { - @include button; - - button, entry { - all: unset; - padding: $spacing*0.7; - - &:last-child { - border-radius: 0 $radii $radii 0; - } - - &:first-child { - border-top: none; - border-bottom: none; - } - } - } - - switch { - @include switch; - } - - .row { - margin-bottom: $spacing; - &:last-child{ margin-bottom: 0; } - - label:first-child { - margin-right: $spacing*5; - } - - .color entry { - margin-right: $spacing; - min-width: 20em; - } - - entry.text { - min-width: 22em; - } - - .text-spin { - @include widget; - - button { - @include button($flat: true); - border-radius: 0; - padding: $spacing/2; - margin: -$border_width; - - &:last-child { - border-radius: 0 $radii $radii 0; - } - } - label { margin: 0 $spacing/2; } - } - } - - .disclaimer { - padding: $spacing; - padding-top: 0; - color: transparentize($fg_color, 0.5); - } - } + background-color: $bg_color; + color: $fg_color; + + scrolledwindow { + @include scrollbar; + } + + .settings { + .content { + padding: $popover_padding; + } + + .headerbar { + background-color: $widget_bg; + padding: $spacing/2; + border-bottom: $border; + } + + .tab { + @include button($flat: true); + margin: $spacing/2; + padding: $spacing/2; + } + + .wallpaper { + border-radius: max($radii - 1px, 0); + background-position: center; + border: $border; + } + + button, + entry { + @include button; + padding: $spacing * 0.7; + } + + spinbutton, + spinbutton:focus { + @include button; + + button, + entry { + all: unset; + padding: $spacing * 0.7; + + &:last-child { + border-radius: 0 $radii $radii 0; + } + + &:first-child { + border-top: none; + border-bottom: none; + } + } + } + + switch { + @include switch; + } + + .row { + margin-bottom: $spacing; + &:last-child { + margin-bottom: 0; + } + + label:first-child { + margin-right: $spacing * 5; + } + + .color entry { + margin-right: $spacing; + min-width: 20em; + } + + entry.text { + min-width: 22em; + } + + .text-spin { + @include widget; + + button { + @include button($flat: true); + border-radius: 0; + padding: $spacing/2; + margin: -$border_width; + + &:last-child { + border-radius: 0 $radii $radii 0; + } + } + label { + margin: 0 $spacing/2; + } + } + + label, + entry { + font-size: $font_size; + } + } + + .disclaimer { + padding: $spacing; + padding-top: 0; + color: transparentize($fg_color, 0.5); + } + } } diff --git a/home/isabel/programs/gui/confs/bars/ags/config/theme/dialog.js b/home/isabel/programs/gui/confs/bars/ags/config/theme/dialog.js deleted file mode 100644 index aa1cac742..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/theme/dialog.js +++ /dev/null @@ -1,244 +0,0 @@ -import Gtk from 'gi://Gtk'; -import { Theme } from './theme.js'; -import themes from './themes.js'; -import { Wallpaper } from '../modules/wallpaper.js'; -const { Box, Stack, Label, Icon, Button, Scrollable, Entry, Widget } = ags.Widget; - -const Row = (title, child) => Box({ - className: 'row', - children: [Label(`${title}: `), child], -}); - -const Img = (title, prop) => Row(title, Widget({ - title, - type: Gtk.FileChooserButton, - hexpand: true, - halign: 'end', - connections: [['selection-changed', - w => Theme.setSetting(prop, w.get_uri().replace('file://', ''))]], -})); - -const SpinButton = (title, prop, max = 100, min = 0) => Row(title, Widget({ - type: Gtk.SpinButton, - setup: w => { - w.set_range(min, max); - w.set_increments(1, 1); - }, - hexpand: true, - halign: 'end', - connections: [ - ['value-changed', b => !b._block && Theme.setSetting(prop, b.value)], - [Theme, b => { - b._block = true; - b.value = Theme.getSetting(prop); - b._block = false; - }], - ], -})); - -const SwitchButton = (title, prop) => Row(title, Widget({ - type: Gtk.Switch, - halign: 'end', - hexpand: true, - connections: [ - [Theme, s => { - s._block = true; - s.active = Theme.getSetting(prop); - s._block = false; - }], - ['notify::active', s => !s._block && Theme.setSetting(prop, s.active)], - ], -})); - -const Color = (title, prop) => Row(title, Box({ - hexpand: true, - halign: 'end', - className: 'color', - children: [ - Entry({ - onAccept: ({ text }) => Theme.setSetting(prop, text), - valign: 'center', - connections: [[Theme, w => w.text = Theme.getSetting(prop)]], - }), - Widget({ - type: Gtk.ColorButton, - alpha: true, - valign: 'center', - connections: [ - ['color-set', w => { - w.get_parent().children[0].set_text(w.rgba.to_string()); - Theme.setSetting(prop, w.rgba.to_string()); - }], - ], - }), - ], -})); - -const Text = (title, prop) => Row(title, Entry({ - className: 'text', - hexpand: true, - halign: 'end', - connections: [[Theme, w => w.text = Theme.getSetting(prop)]], - onAccept: ({ text }) => Theme.setSetting(prop, text), -})); - -const TextSpinButton = (title, prop, list) => Row(title, Box({ - className: 'text-spin', - hexpand: true, - halign: 'end', - properties: [ - ['values', list], - ['step', (box, step) => { - const label = box.get_children()[0]; - const max = box._values.length - 1; - let index = box._values.indexOf(label.label) + step; - - if (index > max) - index = 0; - - if (index < 0) - index = max; - - const value = box._values[index]; - label.label = value; - Theme.setSetting(prop, value); - }], - ], - children: [ - Label({ - connections: [[Theme, label => label.label = Theme.getSetting(prop)]], - }), - Button({ - child: Icon('pan-down-symbolic'), - onClicked: btn => { - const box = btn.get_parent(); - box._step(box, -1); - }, - }), - Button({ - child: Icon('pan-up-symbolic'), - onClicked: btn => { - const box = btn.get_parent(); - box._step(box, +1); - }, - }), - ], -})); - -class Pages extends ags.Service { - static { ags.Service.register(this); } - static instance = new Pages(); - static page = '󰒓 General'; - static show(page) { - Pages.page = page; - Pages.instance.emit('changed'); - } -} - -const Tab = page => Button({ - hexpand: true, - className: 'tab', - onClicked: () => Pages.show(page), - child: Label(page), - connections: [[Pages, b => b.toggleClassName('active', Pages.page === page)]], -}); - -const Layout = pages => Box({ - vertical: true, - className: 'settings', - hexpand: false, - children: [ - Box({ - className: 'headerbar', - valign: 'start', - children: [Box({ - className: 'tabs', - children: [ - ...Object.keys(pages).map(page => Tab(page)), - Button({ - className: 'tab', - onClicked: Theme.reset, - child: Label('󰦛 Reset'), - hexpand: true, - }), - ], - })], - }), - Box({ - className: 'content', - children: [Stack({ - transition: 'slide_left_right', - items: Object.keys(pages).map(page => [page, pages[page]]), - connections: [[Pages, stack => { - stack.shown = Pages.page; - }]], - })], - }), - Label({ - wrap: true, - className: 'disclaimer', - label: 'These settings override all preset themes. ' + - 'To make them permanent: edit ~/.config/ags/theme/themes.js', - }), - ], -}); - -const Page = children => Scrollable({ - child: Box({ - vertical: true, - children, - }), -}); - -export const SettingsDialog = () => Widget({ - type: Gtk.Window, - name: 'settings', - child: Layout({ - '󰒓 General': Page([ - Wallpaper({ - className: 'row', - hexpand: true, - vexpand: true, - }), - Img('Wallpaper', 'wallpaper'), - Img('Avatar', 'avatar'), - SpinButton('Useless Gaps', 'wm_gaps', 128), - SpinButton('Spacing', 'spacing', 18), - SpinButton('Roundness', 'radii', 36), - TextSpinButton('Layout', 'layout', ['topbar', 'leftbar']), - TextSpinButton('Bar Style', 'bar_style', ['normal', 'floating', 'separated']), - SwitchButton('Screen Corners', 'screen_corners'), - ]), - '󰏘 Colors': Page([ - Color('Background Color', 'bg_color'), - Color('Foreground Color', 'fg_color'), - Color('Hovered Foreground Color', 'hover_fg'), - Color('Accent Color', 'accent'), - Color('Accent Foreground', 'accent_fg'), - Color('Widget Background', 'widget_bg'), - TextSpinButton('Color Theme', 'color_scheme', ['light', 'dark']), - ...['Red', 'Green', 'Yellow', 'Blue', 'Magenta', 'Teal', 'Orange'] - .map(c => Color(c, c.toLowerCase())), - ]), - '󰃟 Theme': Page([ - TextSpinButton('Theme', 'theme', themes.map(t => t.name)), - Text('Active Gradient', 'active_gradient'), - SpinButton('Widget Opacity', 'widget_opacity'), - Color('Border Color', 'border_color'), - SpinButton('Border Width', 'border_width'), - SpinButton('Border Opacity', 'border_opacity'), - ]), - '󰠱 Miscellaneous': Page([ - Color('Shadow', 'shadow'), - SwitchButton('Drop Shadow', 'drop_shadow'), - SpinButton('Transition', 'transition', 1000), - Text('Desktop Clock Position', 'desktop_clock'), - Color('Wallpaper Foreground Color', 'wallpaper_fg'), - ]), - }), - connections: [['delete-event', win => { - win.hide(); - return true; - }]], - setup: win => win.set_default_size(700, 600), -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/theme/hyprland.js b/home/isabel/programs/gui/confs/bars/ags/config/theme/hyprland.js deleted file mode 100644 index f4f1b6841..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/theme/hyprland.js +++ /dev/null @@ -1,23 +0,0 @@ -import App from 'resource:///com/github/Aylur/ags/app.js'; -import Service from 'resource:///com/github/Aylur/ags/service/service.js'; -import { execAsync } from 'resource:///com/github/Aylur/ags/utils.js'; - -export function setupHyprland() { - try { - App.instance.connect('config-parsed', () => { - for (const [name] of App.windows) { - if (!name.includes('desktop') && name !== 'verification' && name !== 'powermenu') { - execAsync(['hyprctl', 'keyword', 'layerrule', `unset, ${name}`]).then(() => { - execAsync(['hyprctl', 'keyword', 'layerrule', `blur, ${name}`]); - execAsync(['hyprctl', 'keyword', 'layerrule', `ignorealpha 0.6, ${name}`]); - }); - } - } - - for (const name of ['verification', 'powermenu']) - execAsync(['hyprctl', 'keyword', 'layerrule', `blur, ${name}`]); - }); - } catch (error) { - logError(error); - } -} diff --git a/home/isabel/programs/gui/confs/bars/ags/config/theme/theme.js b/home/isabel/programs/gui/confs/bars/ags/config/theme/theme.js deleted file mode 100644 index ccec51cd8..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/theme/theme.js +++ /dev/null @@ -1,165 +0,0 @@ -import { FontIcon } from '../modules/misc.js'; -import { setupScss } from './scss.js'; -import { setupHyprland } from './hyprland.js'; -import themes from './themes.js'; -import App from 'resource:///com/github/Aylur/ags/app.js'; -import Service from 'resource:///com/github/Aylur/ags/service/service.js'; -import { USER, exec, execAsync, readFile, writeFile } from 'resource:///com/github/Aylur/ags/utils.js'; -import { Stack, Box, Icon, Label, Button } from 'resource:///com/github/Aylur/ags/widget.js'; -import { SettingsDialog } from './dialog.js'; - -class ThemeService extends Service { - static { Service.register(this); } - - _settingsPath = App.configDir + '/settings.json'; - _defaultAvatar = `/home/${USER}/media/pictures/pfps/avatar`; - _defaultTheme = themes[0].name; - - constructor() { - super(); - exec('swww init'); - this.setup(); - } - - openSettings() { - if (!this._dialog) - this._dialog = SettingsDialog(); - - this._dialog.hide(); - this._dialog.show_all(); - } - - getTheme() { - return themes.find(({ name }) => name === this.getSetting('theme')); - } - - setup() { - const theme = { - ...this.getTheme(), - ...this.settings, - }; - setupScss(theme); - setupHyprland(); - this.setupOther(); - this.setupWallpaper(); - } - - setupOther() { - const darkmode = this.getSetting('color_scheme') === 'dark'; - - execAsync(`gsettings set org.gnome.desktop.interface color-scheme "prefer-${darkmode ? 'dark' : 'light'}"`).catch(print); - } - - setupWallpaper() { - execAsync([ - 'swww', 'img', - this.getSetting('wallpaper'), - ]).catch(print); - } - - reset() { - exec(`rm ${this._settingsPath}`); - this._settings = null; - this.setup(); - this.emit('changed'); - } - - get settings() { - if (this._settings) - return this._settings; - - try { - this._settings = JSON.parse(readFile(this._settingsPath)); - } catch (_) { - this._settings = {}; - } - - return this._settings; - } - - setSetting(prop, value) { - const settings = this.settings; - settings[prop] = value; - writeFile(JSON.stringify(settings, null, 2), this._settingsPath).catch(print); - this._settings = settings; - this.emit('changed'); - - if (prop === 'layout') { - if (!this._notiSent) { - this._notiSent = true; - execAsync(['notify-send', 'Layout Change Needs a Reload']); - } - return; - } - - this.setup(); - } - - getSetting(prop) { - if (prop === 'theme') - return this.settings.theme || this._defaultTheme; - - if (prop === 'avatar') - return this.settings.avatar || this._defaultAvatar; - - return this.settings[prop] !== undefined - ? this.settings[prop] - : this.getTheme()[prop]; - } -} - -export class Theme { - static { Service.export(this, 'Theme'); } - static instance = new ThemeService(); - static get themes() { return themes; } - - static reset() { Theme.instance.reset(); } - static openSettings() { Theme.instance.openSettings(); } - static getSetting(prop) { return Theme.instance.getSetting(prop); } - static setSetting(prop, value) { return Theme.instance.setSetting(prop, value); } -} - -export const Indicator = props => Stack({ - ...props, - transition: 'crossfade', - items: themes.map(({ name, icon }) => - [name, FontIcon({ icon })]), - connections: [[Theme, stack => stack.shown = Theme.getSetting('theme')]], -}); - -export const Toggle = props => Button({ - ...props, - className: 'active', - properties: [ - ['list', themes], - ['current', Theme.getSetting('theme')], - ], - onClicked: btn => { - let index = btn._list.indexOf(btn._current) + 1; - if (index > btn._list.length) - index = 0; - - btn._current = btn._list[index]; - Theme.setSetting('theme', btn._current); - }, -}); - -export const Selector = props => Box({ - ...props, - vertical: true, - children: themes.map(({ name, icon }) => Button({ - onClicked: () => Theme.setSetting('theme', name), - child: Box({ - children: [ - FontIcon({ icon }), - Label(name.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ')), - Icon({ - icon: 'object-select-symbolic', - hexpand: true, - halign: 'end', - connections: [[Theme, icon => icon.visible = Theme.getSetting('theme') === name]], - }), - ], - }), - })), -}); diff --git a/home/isabel/programs/gui/confs/bars/ags/config/theme/themes.js b/home/isabel/programs/gui/confs/bars/ags/config/theme/themes.js deleted file mode 100644 index a2d57ee26..000000000 --- a/home/isabel/programs/gui/confs/bars/ags/config/theme/themes.js +++ /dev/null @@ -1,77 +0,0 @@ -// common -const WP = `/home/${ags.Utils.USER}/media/pictures/wallpapers/`; - -const mocha_colors = { - bg_color: '#1e1e2e', - fg_color: '#cdd6f4', - hover_fg: '#cdd6f4', - red: '#f38ba8', - green: '#a6e3a1', - yellow: '#f9e2af', - blue: '#74c7ec', - magenta: '#cba6f7', - teal: '#94e2d5', - orange: '#fab387', -}; - -const latte_colors = { - bg_color: '#eff1f5', - fg_color: '#4c4f69', - hover_fg: '#4c4f69', - red: '#d20f39', - green: '#40a02b', - yellow: '#df8e1d', - blue: '#209fb5', - magenta: '#8839ef', - teal: '#179299', - orange: '#fe640b', -}; - -const settings = { - wm_gaps: 8, - radii: 9, - spacing: 9, - drop_shadow: true, - transition: 200, - screen_corners: false, - bar_style: 'normal', - layout: 'topbar', - border_opacity: 97, - border_width: 1, - widget_opacity: 94, -}; - -const misc_colors = { - shadow: 'rgba(0, 0, 0, .6)', - accent: '$blue', - accent_fg: '$bg_color', - widget_bg: '$fg_color', - active_gradient: 'to right, $accent, lighten($accent, 6%)', - border_color: '$fg_color', -}; - -// themes -const mocha = { - wallpaper: WP + 'tempest.png', - name: 'mocha', - color_scheme: 'dark', - icon: '', - ...mocha_colors, - ...settings, - ...misc_colors, -}; - -const latte = { - wallpaper: WP + 'coke.jpg', - name: 'latte', - color_scheme: 'light', - icon: '', - ...latte_colors, - ...settings, - ...misc_colors, -}; - -export default [ - mocha, - latte, -]; diff --git a/home/isabel/programs/gui/confs/bars/ags/default.nix b/home/isabel/programs/gui/confs/bars/ags/default.nix index c4b488fbd..17b2faa3c 100644 --- a/home/isabel/programs/gui/confs/bars/ags/default.nix +++ b/home/isabel/programs/gui/confs/bars/ags/default.nix @@ -4,31 +4,30 @@ config, osConfig, defaults, + inputs', ... }: let - inherit (lib) mkIf; - device = osConfig.modules.device; + inherit (osConfig.modules) system; acceptedTypes = ["desktop" "laptop" "hybrid"]; - programs = osConfig.modules.programs; - sys = osConfig.modules.system; in { - config = mkIf (builtins.elem device.type acceptedTypes && programs.gui.enable && sys.video.enable && defaults.bar == "ags") { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && (lib.isWayland osConfig) && osConfig.modules.programs.gui.enable && defaults.bar == "ags") { home = { packages = with pkgs; [ - nur.repos.bella.ags + inputs'.ags.packages.default socat sassc networkmanagerapplet + inotify-tools swww ]; }; xdg.configFile = let symlink = fileName: {recursive ? false}: { - source = config.lib.file.mkOutOfStoreSymlink "${sys.flakePath}/${fileName}"; + source = config.lib.file.mkOutOfStoreSymlink "${system.flakePath}/${fileName}"; inherit recursive; }; in { - "ags" = symlink "home/${sys.mainUser}/programs/gui/confs/bars/ags/config" { + "ags" = symlink "home/${system.mainUser}/programs/gui/confs/bars/ags/config" { recursive = true; }; }; diff --git a/home/isabel/programs/gui/confs/bars/eww/config/eww.scss b/home/isabel/programs/gui/confs/bars/eww/config/eww.scss index 2291604bf..5087cc383 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/eww.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/eww.scss @@ -26,5 +26,5 @@ @import "./scss/windows/screenshot.scss"; tooltip { - @include tooltip -} \ No newline at end of file + @include tooltip; +} diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/apps b/home/isabel/programs/gui/confs/bars/eww/config/scripts/apps index a8a348a00..a729cacb9 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/apps +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/apps @@ -1,11 +1,12 @@ #!/usr/bin/env bash function query { - dbus-send --session --type=method_call \ - --dest=com.github.isabel.host \ - /com/github/isabel/applications \ - com.github.isabel.applications.Query \ - string:$1 + dbus-send --session --type=method_call \ + --dest=com.github.isabel.host \ + /com/github/isabel/applications \ + com.github.isabel.applications.Query \ + string:$1 } if [[ $1 == 'query' ]]; then query $2; fi + diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/bluetooth b/home/isabel/programs/gui/confs/bars/eww/config/scripts/bluetooth index c0439eba3..e609f10d5 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/bluetooth +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/bluetooth @@ -1,14 +1,15 @@ #!/usr/bin/env bash function state { - STATE=$(bluetoothctl show | grep 'Powered' | awk '{print $2}') - if [[ $STATE == 'yes' ]]; then echo 'on' - else echo 'off'; fi + STATE=$(bluetoothctl show | grep 'Powered' | awk '{print $2}') + if [[ $STATE == 'yes' ]]; then echo 'on' + else echo 'off'; fi } function toggle { - if [[ $(state) = 'on' ]]; then bluetoothctl power off - else bluetoothctl power on; fi + if [[ $(state) = 'on' ]]; then bluetoothctl power off + else bluetoothctl power on; fi } -if [[ $1 == 'toggle' ]]; then toggle; fi \ No newline at end of file +if [[ $1 == 'toggle' ]]; then toggle; fi + diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/brightness b/home/isabel/programs/gui/confs/bars/eww/config/scripts/brightness index 057057331..a2702791c 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/brightness +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/brightness @@ -32,8 +32,8 @@ function set_screen { function get { echo "{ - \"screen\": { \"level\": \"$(screen_level)\", \"icon\": \"$(screen_icon)\" } - }" + \"screen\": { \"level\": \"$(screen_level)\", \"icon\": \"$(screen_icon)\" } + }" } if [[ $1 == 'get' ]]; then get; fi diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/events b/home/isabel/programs/gui/confs/bars/eww/config/scripts/events index 3204f407a..c858478fb 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/events +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/events @@ -1,14 +1,14 @@ #!/usr/bin/env bash if [ ! -f "$HOME/.local/bin/todo" ]; then - exit 0 + exit 0 fi if [[ $1 == 'get' ]]; then - $HOME/.local/bin/todo -j | jq -c + $HOME/.local/bin/todo -j | jq -c - while true; do - inotifywait -q -e modify $HOME/Documents/todos.json - $HOME/.local/bin/todo -j | jq -c - done + while true; do + inotifywait -q -e modify $HOME/Documents/todos.json + $HOME/.local/bin/todo -j | jq -c + done fi diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/apps.js b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/apps.js index cd430279c..1f81d0f28 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/apps.js +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/apps.js @@ -1,106 +1,119 @@ -import { ApplicationsIFace } from "./dbus.js" -import { MkDirectory, APPICON_CACHE_PATH } from './main.js' -import { Gio, GObject, Gtk } from './lib.js' - -export const Apps = GObject.registerClass({ - Signals: { 'sync': {} } -}, - class Apps extends GObject.Object { - constructor() { - super(); - - this._register(); - } - - get json() { - return this._list; - } - - _iconPath(icon) { - return APPICON_CACHE_PATH + icon + '.png'; - } - - init() { - this._initIcons(); - this.Query(''); - } - - _initIcons() { - MkDirectory(); - let icons = []; - Gio.AppInfo.get_all() - .forEach(app => { - if (!app.should_show() || !app.get_icon()) return; - if (typeof app.get_icon().get_names !== 'function') return; - app?.get_icon()?.get_names() - .forEach(icon => icons.push(icon)) - }); - - icons.forEach(icon => { - if (icon.includes('-symbolic')) return; - let iconInfo = Gtk.IconTheme.get_default() - .lookup_by_gicon( - Gio.Icon.new_for_string(icon), 128, null); - - if (!iconInfo) return; - - let output_stream = - Gio.File.new_for_path(this._iconPath(icon)) - .replace(null, false, Gio.FileCreateFlags.NONE, null); - - iconInfo.load_icon() - .save_to_streamv(output_stream, 'png', null, null, null); - - output_stream.close(null); - }) - } - - _appIconName(app) { - if (!app.get_icon()) - return ''; - - if (typeof app.get_icon().get_names !== 'function') - return ''; - - let name = app.get_icon().get_names()[0]; - return name ? this._iconPath(name) : ''; - } - - Query(search) { - let apps = Gio.AppInfo.get_all(); - let list = []; - apps.forEach(app => { - if (!app.should_show()) return; - if (app.get_name()?.toLowerCase().includes(search)) list.push(app); - else if (app.get_id()?.toLowerCase().includes(search)) list.push(app); - else if (app.get_executable()?.toLowerCase().includes(search)) list.push(app); - else if (app.get_description()?.toLowerCase().includes(search)) list.push(app); - }); - - let outList = []; - list.forEach(app => { - outList.push({ - name: app.get_name(), - desktop: app.get_id(), - description: app.get_description(), - icon: this._appIconName(app), - }) - }) - this._list = outList; - this.emit('sync'); - } - - _register() { - Gio.bus_own_name( - Gio.BusType.SESSION, - 'com.github.isabel.host', - Gio.BusNameOwnerFlags.NONE, - (connection, _) => { - this._dbus = Gio.DBusExportedObject.wrapJSObject(ApplicationsIFace, this); - this._dbus.export(connection, '/com/github/isabel/applications'); - }, - null, - null, - ); - } - }) +import { ApplicationsIFace } from "./dbus.js"; +import { MkDirectory, APPICON_CACHE_PATH } from "./main.js"; +import { Gio, GObject, Gtk } from "./lib.js"; + +export const Apps = GObject.registerClass( + { + Signals: { sync: {} }, + }, + class Apps extends GObject.Object { + constructor() { + super(); + + this._register(); + } + + get json() { + return this._list; + } + + _iconPath(icon) { + return APPICON_CACHE_PATH + icon + ".png"; + } + + init() { + this._initIcons(); + this.Query(""); + } + + _initIcons() { + MkDirectory(); + let icons = []; + Gio.AppInfo.get_all().forEach((app) => { + if (!app.should_show() || !app.get_icon()) return; + if (typeof app.get_icon().get_names !== "function") return; + app?.get_icon() + ?.get_names() + .forEach((icon) => icons.push(icon)); + }); + + icons.forEach((icon) => { + if (icon.includes("-symbolic")) return; + let iconInfo = Gtk.IconTheme.get_default().lookup_by_gicon( + Gio.Icon.new_for_string(icon), + 128, + null, + ); + + if (!iconInfo) return; + + let output_stream = Gio.File.new_for_path( + this._iconPath(icon), + ).replace(null, false, Gio.FileCreateFlags.NONE, null); + + iconInfo + .load_icon() + .save_to_streamv(output_stream, "png", null, null, null); + + output_stream.close(null); + }); + } + + _appIconName(app) { + if (!app.get_icon()) return ""; + + if (typeof app.get_icon().get_names !== "function") return ""; + + let name = app.get_icon().get_names()[0]; + return name ? this._iconPath(name) : ""; + } + + Query(search) { + let apps = Gio.AppInfo.get_all(); + let list = []; + apps.forEach((app) => { + if (!app.should_show()) return; + if (app.get_name()?.toLowerCase().includes(search)) + list.push(app); + else if (app.get_id()?.toLowerCase().includes(search)) + list.push(app); + else if (app.get_executable()?.toLowerCase().includes(search)) + list.push(app); + else if (app.get_description()?.toLowerCase().includes(search)) + list.push(app); + }); + + let outList = []; + list.forEach((app) => { + outList.push({ + name: app.get_name(), + desktop: app.get_id(), + description: app.get_description(), + icon: this._appIconName(app), + }); + }); + this._list = outList; + this.emit("sync"); + } + + _register() { + Gio.bus_own_name( + Gio.BusType.SESSION, + "com.github.isabel.host", + Gio.BusNameOwnerFlags.NONE, + (connection, _) => { + this._dbus = Gio.DBusExportedObject.wrapJSObject( + ApplicationsIFace, + this, + ); + this._dbus.export( + connection, + "/com/github/isabel/applications", + ); + }, + null, + null, + ); + } + }, +); diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/battery.js b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/battery.js index 098e293f8..f1b66690d 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/battery.js +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/battery.js @@ -1,62 +1,77 @@ -import { GObject, Gio, UPowerGlib } from './lib.js' -import { PowerManagerProxy } from './dbus.js' - -export const Battery = GObject.registerClass({ - Signals: { 'sync': {} } -}, -class Battery extends GObject.Object{ - constructor(){ - super(); - - this._json = {}; - this._proxy = new PowerManagerProxy( - Gio.DBus.system, - 'org.freedesktop.UPower', - '/org/freedesktop/UPower/devices/DisplayDevice', - () => { - this._proxy.connect( - 'g-properties-changed', () => this._sync() ); - this._sync(); - } - ); - } - - get json(){ - return this._json; - } - - _sync(){ - if(!this._proxy.IsPresent) return { available: false }; - - let percent = this._proxy.Percentage; - let charging = this._proxy.State === UPowerGlib.DeviceState.CHARGING; - let charged = - this._proxy.State === UPowerGlib.DeviceState.FULLY_CHARGED || - (this._proxy.State === UPowerGlib.DeviceState.CHARGING && percent === 100); - - - let icons = ['󰁺', '󰁻', '󰁼', '󰁽', '󰁾', '󰁿', '󰂀', '󰂁', '󰂂', '󰁹']; - let charging_icons = ['󰢜', '󰂆', '󰂇', '󰂈', '󰢝', '󰂉', '󰢞', '󰂊', '󰂋', '󰂅']; - let i = Math.round(percent / 10)-1; - if(i < 0) i = 0; - - let icon; - if(charged) icon = '󰂄'; - else if(charging) icon = charging_icons[i]; - else if(percent < 10) icon = '󱃍'; - else icon = icons[i]; - - let state = ''; - if(charged) state = 'charged'; - else if(charging) state = 'charging'; - else if(percent < 30) state = 'low'; - - this._json = { - available: true, - icon, - percent, - state - }; - this.emit('sync'); - } -}); +import { GObject, Gio, UPowerGlib } from "./lib.js"; +import { PowerManagerProxy } from "./dbus.js"; + +export const Battery = GObject.registerClass( + { + Signals: { sync: {} }, + }, + class Battery extends GObject.Object { + constructor() { + super(); + + this._json = {}; + this._proxy = new PowerManagerProxy( + Gio.DBus.system, + "org.freedesktop.UPower", + "/org/freedesktop/UPower/devices/DisplayDevice", + () => { + this._proxy.connect("g-properties-changed", () => + this._sync(), + ); + this._sync(); + }, + ); + } + + get json() { + return this._json; + } + + _sync() { + if (!this._proxy.IsPresent) return { available: false }; + + let percent = this._proxy.Percentage; + let charging = + this._proxy.State === UPowerGlib.DeviceState.CHARGING; + let charged = + this._proxy.State === UPowerGlib.DeviceState.FULLY_CHARGED || + (this._proxy.State === UPowerGlib.DeviceState.CHARGING && + percent === 100); + + let icons = ["󰁺", "󰁻", "󰁼", "󰁽", "󰁾", "󰁿", "󰂀", "󰂁", "󰂂", "󰁹"]; + let charging_icons = [ + "󰢜", + "󰂆", + "󰂇", + "󰂈", + "󰢝", + "󰂉", + "󰢞", + "󰂊", + "󰂋", + "󰂅", + ]; + let i = Math.round(percent / 10) - 1; + if (i < 0) i = 0; + + let icon; + if (charged) icon = "󰂄"; + else if (charging) icon = charging_icons[i]; + else if (percent < 10) icon = "󱃍"; + else icon = icons[i]; + + let state = ""; + if (charged) state = "charged"; + else if (charging) state = "charging"; + else if (percent < 30) state = "low"; + + this._json = { + available: true, + icon, + percent, + state, + }; + this.emit("sync"); + } + }, +); diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/bluetooth.js b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/bluetooth.js index c5c7a6279..f1d7d5517 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/bluetooth.js +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/bluetooth.js @@ -1,108 +1,122 @@ -import { GObject, GnomeBluetooth } from './lib.js' +import { GObject, GnomeBluetooth } from "./lib.js"; const STATES = { - [GnomeBluetooth.AdapterState.ABSENT]: 'absent', - [GnomeBluetooth.AdapterState.ON]: 'on', - [GnomeBluetooth.AdapterState.TURNING_ON]: 'on', - [GnomeBluetooth.AdapterState.OFF]: 'off', - [GnomeBluetooth.AdapterState.TURNING_OFF]: 'off', -} + [GnomeBluetooth.AdapterState.ABSENT]: "absent", + [GnomeBluetooth.AdapterState.ON]: "on", + [GnomeBluetooth.AdapterState.TURNING_ON]: "on", + [GnomeBluetooth.AdapterState.OFF]: "off", + [GnomeBluetooth.AdapterState.TURNING_OFF]: "off", +}; const ICONS = { - absent: '󰂲', - off: '󰂲', - on: '󰂯', - 'audio-headset': '󰋋', -} - -export const Bluetooth = GObject.registerClass({ - Signals: { 'sync': {} } -}, -class Bluetooth extends GObject.Object{ - constructor() { - super(); - - this._json = {}; - this._devices = new Map(); - this._connections = new Map(); - this._client = new GnomeBluetooth.Client(); - this._client.connect('notify::default-adapter-state', this._sync.bind(this)); - this._client.connect('device-added', this._deviceAdded.bind(this)); - this._client.connect('device-removed', this._deviceRemoved.bind(this)); - this._getDevices().forEach(device => this._deviceAdded(_, device)); - this._sync(); - } - - get json() { return this._json } - - _deviceAdded(_, device) { - if(this._devices.has(device.address)) return; - - let connections = []; - [ - 'address', - 'alias', - 'battery-level', - 'battery-percentage', - 'connected', - 'icon', - 'name', - 'paired', - 'truested' - ] - .forEach(prop => connections.push( - device.connect(`notify::${prop}`, this._sync.bind(this)) - )); - this._connections.set(device.address, connections); - - this._devices.set(device.address, device); - this._sync(); - } - - _deviceRemoved(_, device) { - if(!this._devices.has(device.address)) return; - - this._connections.get(device.address).forEach(id => device.disconnect(id)); - this._connections.delete(device.address); - this._devices.delete(device.address); - this._sync(); - } - - _getDevices() { - let devices = []; - const deviceStore = this._client.get_devices(); - - for(let i=0; i + this._deviceAdded(_, device), + ); + this._sync(); } - - return devices; - } - - _sync() { - this._json.state = STATES[this._client.default_adapter_state]; - this._json.icon = ICONS[this._json.state]; - this._json.connected_devices = []; - this._json.devices = []; - for (const [_, device] of this._devices) { - let item = { - address: device.address, - alias: device.alias, - battery_level: device.battery_level, - battery_percentage: device.battery_percentage, - connected: device.connected, - icon: ICONS[device.icon], - name: device.name, - paired: device.paired, - trusted: device.trusted - }; - this._json.devices.push(item); - if(device.connected) this._json.connected_devices.push(item); + + get json() { + return this._json; } - this.emit('sync'); - } -}) + _deviceAdded(_, device) { + if (this._devices.has(device.address)) return; + + let connections = []; + [ + "address", + "alias", + "battery-level", + "battery-percentage", + "connected", + "icon", + "name", + "paired", + "truested", + ].forEach((prop) => + connections.push( + device.connect(`notify::${prop}`, this._sync.bind(this)), + ), + ); + this._connections.set(device.address, connections); + + this._devices.set(device.address, device); + this._sync(); + } + + _deviceRemoved(_, device) { + if (!this._devices.has(device.address)) return; + + this._connections + .get(device.address) + .forEach((id) => device.disconnect(id)); + this._connections.delete(device.address); + this._devices.delete(device.address); + this._sync(); + } + + _getDevices() { + let devices = []; + const deviceStore = this._client.get_devices(); + + for (let i = 0; i < deviceStore.get_n_items(); ++i) { + const device = deviceStore.get_item(i); + + if (device.paired || device.trusted) devices.push(device); + } + + return devices; + } + + _sync() { + this._json.state = STATES[this._client.default_adapter_state]; + this._json.icon = ICONS[this._json.state]; + this._json.connected_devices = []; + this._json.devices = []; + for (const [_, device] of this._devices) { + let item = { + address: device.address, + alias: device.alias, + battery_level: device.battery_level, + battery_percentage: device.battery_percentage, + connected: device.connected, + icon: ICONS[device.icon], + name: device.name, + paired: device.paired, + trusted: device.trusted, + }; + this._json.devices.push(item); + if (device.connected) this._json.connected_devices.push(item); + } + + this.emit("sync"); + } + }, +); diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/dbus.js b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/dbus.js index 4e01573fc..30c6bbe8a 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/dbus.js +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/dbus.js @@ -1,7 +1,7 @@ -import { Gio } from './lib.js' +import { Gio } from "./lib.js"; export const MprisPlayerProxy = Gio.DBusProxy.makeProxyWrapper( - ` + ` @@ -15,11 +15,11 @@ export const MprisPlayerProxy = Gio.DBusProxy.makeProxyWrapper( -` +`, ); export const DBusProxy = Gio.DBusProxy.makeProxyWrapper( - ` + ` @@ -30,21 +30,20 @@ export const DBusProxy = Gio.DBusProxy.makeProxyWrapper( -` +`, ); export const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper( - ` + ` -` +`, ); -export const NotificationIFace = - ` +export const NotificationIFace = ` @@ -92,18 +91,16 @@ export const NotificationIFace = `; -export const BluetoothIFace = - ` +export const BluetoothIFace = ` -` +`; -export const ApplicationsIFace = - ` +export const ApplicationsIFace = ` -` +`; diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/host b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/host index f407433fa..b61a4add4 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/host +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/host @@ -13,15 +13,15 @@ imports.gi.versions.NM = '1.0' imports.gi.versions.GdkPixbuf = '2.0' imports.package.init({ - name: 'host', - version: '0.1.0', - prefix: '/usr/local', - libdir: '/run/current-system/sw/lib', + name: 'host', + version: '0.1.0', + prefix: '/usr/local', + libdir: '/run/current-system/sw/lib', }); imports.package.require({ - 'Gtk': '3.0', - 'Gio': '2.0' + 'Gtk': '3.0', + 'Gio': '2.0' }); main([programInvocationName, ...programArgs]) diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/lib.js b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/lib.js index 57babdb0e..3b8727d3d 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/lib.js +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/lib.js @@ -1,19 +1,19 @@ -imports.gi.versions.Gtk = '3.0' -imports.gi.versions.Gio = '2.0' -imports.gi.versions.GLib = '2.0' -imports.gi.versions.GObject = '2.0' -imports.gi.versions.UPowerGlib = '1.0' -imports.gi.versions.GnomeBluetooth = '3.0' -imports.gi.versions.NM = '1.0' -imports.gi.versions.GdkPixbuf = '2.0' +imports.gi.versions.Gtk = "3.0"; +imports.gi.versions.Gio = "2.0"; +imports.gi.versions.GLib = "2.0"; +imports.gi.versions.GObject = "2.0"; +imports.gi.versions.UPowerGlib = "1.0"; +imports.gi.versions.GnomeBluetooth = "3.0"; +imports.gi.versions.NM = "1.0"; +imports.gi.versions.GdkPixbuf = "2.0"; export const { - Gtk, - Gio, - GLib, - GObject, - UPowerGlib, - GnomeBluetooth, - NM, - GdkPixbuf, + Gtk, + Gio, + GLib, + GObject, + UPowerGlib, + GnomeBluetooth, + NM, + GdkPixbuf, } = imports.gi; diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/main.js b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/main.js index ced915c50..9a09cb8ce 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/main.js +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/main.js @@ -1,132 +1,164 @@ -import { Network } from './network.js' -import { Media } from './media.js' -import { Battery } from './battery.js' -import { Bluetooth } from './bluetooth.js' -import { Notifications } from './notifications.js' -import { Apps } from './apps.js' -import { GObject, Gio, GLib, Gtk } from './lib.js' - -const TICK_INTERVAL = 1000 //ms -export const NOTIFICATIONS_BANNER_TIME_OUT = 5000 -export const PREFERRED_PLAYER = 'spotify' -export const CACHE_PATH = GLib.get_user_cache_dir() + '/isabel/' -export const MEDIA_CACHE_PATH = CACHE_PATH + 'media/' -export const NOTIFICATIONS_CACHE_PATH = CACHE_PATH + 'notifications/' -export const APPICON_CACHE_PATH = CACHE_PATH + 'apps/' +import { Network } from "./network.js"; +import { Media } from "./media.js"; +import { Battery } from "./battery.js"; +import { Bluetooth } from "./bluetooth.js"; +import { Notifications } from "./notifications.js"; +import { Apps } from "./apps.js"; +import { GObject, Gio, GLib, Gtk } from "./lib.js"; + +const TICK_INTERVAL = 1000; //ms +export const NOTIFICATIONS_BANNER_TIME_OUT = 5000; +export const PREFERRED_PLAYER = "spotify"; +export const CACHE_PATH = GLib.get_user_cache_dir() + "/isabel/"; +export const MEDIA_CACHE_PATH = CACHE_PATH + "media/"; +export const NOTIFICATIONS_CACHE_PATH = CACHE_PATH + "notifications/"; +export const APPICON_CACHE_PATH = CACHE_PATH + "apps/"; export const PlayerIcons = { - 'deafult': '', //icon broken - 'spotify': '', - 'chromium': '', - 'mpv': '' -} + deafult: "", //icon broken + spotify: "", + chromium: "", + mpv: "", +}; export function MkDirectory() { - [ - CACHE_PATH, - MEDIA_CACHE_PATH, - NOTIFICATIONS_CACHE_PATH, - APPICON_CACHE_PATH, - ] - .forEach(path => { - if (!GLib.file_test(path, GLib.FileTest.EXISTS)) - Gio.File.new_for_path(path) - .make_directory(null); - }) + [ + CACHE_PATH, + MEDIA_CACHE_PATH, + NOTIFICATIONS_CACHE_PATH, + APPICON_CACHE_PATH, + ].forEach((path) => { + if (!GLib.file_test(path, GLib.FileTest.EXISTS)) + Gio.File.new_for_path(path).make_directory(null); + }); } const App = GObject.registerClass( - class App extends Gtk.Application { - constructor({ eww, file, stdout, fg_color }) { - super({ - application_id: 'com.github.isabel.host', - flags: Gio.ApplicationFlags.DEFAULT_FLAGS - }); - - MkDirectory(); - - this._eww = eww; - this._file = file; - this._stdout = stdout; - this._json = {}; - - this._notifications = new Notifications(fg_color); - this._battery = new Battery(); - this._network = new Network(); - this._bluetooth = new Bluetooth(); - this._media = new Media(); - this._apps = new Apps(); - - this.run(null); - } - - vfunc_activate() { - this.hold(); - - [ - 'notifications', 'battery', 'network', - 'bluetooth', 'apps', 'media' - ] - .forEach(m => this._output(this[`_${m}`].json, m)); - - this._notifications.connect('sync', o => this._output(o.json, 'notifications')); - this._battery.connect('sync', o => this._output(o.json, 'battery')); - this._network.connect('sync', o => this._output(o.json, 'network')); - this._bluetooth.connect('sync', o => this._output(o.json, 'bluetooth')); - this._apps.connect('sync', o => this._output(o.json, 'apps')); - this._apps.init(); - - this._media.connect('sync', o => this._output(o.json, 'media')); - this._media.connect('positions', o => this._output(o.positions, 'media_positions')); - GLib.timeout_add(GLib.PRIORITY_DEFAULT, TICK_INTERVAL, () => this._media.getPositions()); - } - - _output(json, name) { - if (!json) return; - if (this._file) { - const file = Gio.File.new_for_path(CACHE_PATH + name + '.json'); - - if (!GLib.file_test(file.get_path(), GLib.FileTest.EXISTS)) - file.create(Gio.FileCreateFlags.NONE, null); - - file.replace_contents(JSON.stringify(json, null, 2), null, false, - Gio.FileCreateFlags.REPLACE_DESTINATION, null); - } - - if (this._eww) { - GLib.spawn_command_line_async( - `eww update ${name}=${JSON.stringify(JSON.stringify(json))}` - ); - } - - if (this._stdout) { - this._json[name] = json; - print(JSON.stringify(this._json, null, 2)); - } - } - }) + class App extends Gtk.Application { + constructor({ eww, file, stdout, fg_color }) { + super({ + application_id: "com.github.isabel.host", + flags: Gio.ApplicationFlags.DEFAULT_FLAGS, + }); + + MkDirectory(); + + this._eww = eww; + this._file = file; + this._stdout = stdout; + this._json = {}; + + this._notifications = new Notifications(fg_color); + this._battery = new Battery(); + this._network = new Network(); + this._bluetooth = new Bluetooth(); + this._media = new Media(); + this._apps = new Apps(); + + this.run(null); + } + + vfunc_activate() { + this.hold(); + + [ + "notifications", + "battery", + "network", + "bluetooth", + "apps", + "media", + ].forEach((m) => this._output(this[`_${m}`].json, m)); + + this._notifications.connect("sync", (o) => + this._output(o.json, "notifications"), + ); + this._battery.connect("sync", (o) => + this._output(o.json, "battery"), + ); + this._network.connect("sync", (o) => + this._output(o.json, "network"), + ); + this._bluetooth.connect("sync", (o) => + this._output(o.json, "bluetooth"), + ); + this._apps.connect("sync", (o) => this._output(o.json, "apps")); + this._apps.init(); + + this._media.connect("sync", (o) => this._output(o.json, "media")); + this._media.connect("positions", (o) => + this._output(o.positions, "media_positions"), + ); + GLib.timeout_add(GLib.PRIORITY_DEFAULT, TICK_INTERVAL, () => + this._media.getPositions(), + ); + } + + _output(json, name) { + if (!json) return; + if (this._file) { + const file = Gio.File.new_for_path(CACHE_PATH + name + ".json"); + + if (!GLib.file_test(file.get_path(), GLib.FileTest.EXISTS)) + file.create(Gio.FileCreateFlags.NONE, null); + + file.replace_contents( + JSON.stringify(json, null, 2), + null, + false, + Gio.FileCreateFlags.REPLACE_DESTINATION, + null, + ); + } + + if (this._eww) { + GLib.spawn_command_line_async( + `eww update ${name}=${JSON.stringify( + JSON.stringify(json), + )}`, + ); + } + + if (this._stdout) { + this._json[name] = json; + print(JSON.stringify(this._json, null, 2)); + } + } + }, +); function parseArgs(argv) { - let args = {}; - for (let i = 0; i < argv.length; ++i) { - switch (argv[i]) { - case '--help': args.help = true; break; - case '--eww': args.eww = true; break; - case '--file': args.file = true; break; - case '--stdout': args.stdout = true; break; - case '--fg-color': args.fg_color = argv[i++]; break; - default: break; + let args = {}; + for (let i = 0; i < argv.length; ++i) { + switch (argv[i]) { + case "--help": + args.help = true; + break; + case "--eww": + args.eww = true; + break; + case "--file": + args.file = true; + break; + case "--stdout": + args.stdout = true; + break; + case "--fg-color": + args.fg_color = argv[i++]; + break; + default: + break; + } } - } - return args; + return args; } export function main(argv) { - let { help, eww, file, stdout, fg_color } = parseArgs(argv); - if ((!eww && !file && !stdout) || help) { - print('Usage:', argv[0], '[--eww] [--file] [--stdout]'); - return; - } - print('Cache directory:', CACHE_PATH); - new App({ eww, file, stdout, fg_color }); + let { help, eww, file, stdout, fg_color } = parseArgs(argv); + if ((!eww && !file && !stdout) || help) { + print("Usage:", argv[0], "[--eww] [--file] [--stdout]"); + return; + } + print("Cache directory:", CACHE_PATH); + new App({ eww, file, stdout, fg_color }); } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/media.js b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/media.js index 847e28d4c..3dc7712e7 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/media.js +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/media.js @@ -1,6 +1,11 @@ -import { MprisPlayerProxy, DBusProxy } from './dbus.js' -import { PlayerIcons, PREFERRED_PLAYER, MEDIA_CACHE_PATH, MkDirectory } from "./main.js"; -import { GObject, Gio, GLib } from './lib.js' +import { MprisPlayerProxy, DBusProxy } from "./dbus.js"; +import { + PlayerIcons, + PREFERRED_PLAYER, + MEDIA_CACHE_PATH, + MkDirectory, +} from "./main.js"; +import { GObject, Gio, GLib } from "./lib.js"; function _lengthStr(length) { let min = Math.floor(length / 60); @@ -10,270 +15,287 @@ function _lengthStr(length) { } function _getName(busName) { - return busName - .substring(23) - .split('.') - [0]; + return busName.substring(23).split(".")[0]; } -const MprisPlayer = GObject.registerClass({ - Signals: { 'changed' : {}, 'closed': {}, 'ready': {} } -}, -class MprisPlayer extends GObject.Object { - constructor(busName) { - super(); - - this._proxy = new MprisPlayerProxy(Gio.DBus.session, busName, - '/org/mpris/MediaPlayer2', - this._onPlayerProxyReady.bind(this)); - - this._busName = busName; - this._name = _getName(busName); - this._playerIcon = PlayerIcons?.[this._name] || PlayerIcons.deafult || ''; - this._trackArtists = []; - this._trackTitle = ''; - this._trackCoverUrl = ''; - this._coverPath = ''; - this._playBackStatus = ''; - this._canGoNext = false; - this._canGoPrev = false; - this._canPlay = false; - this._shuffle = false; - this._loopStatus = ''; - this._volume = -1; - this._length = -1; - this._position = -1; - } - - close() { - this._proxy.disconnect(this._playerBinding1); - this._proxy.disconnect(this._playerBinding2); - this._proxy = null; - - this.emit('closed'); - } - - _onPlayerProxyReady() { - this._playerBinding1 = this._proxy.connect('notify::g-name-owner', () => { - if (!this._proxy.g_name_owner) - this.close(); - }) - this._playerBinding2 = this._proxy.connect( - 'g-properties-changed', () => { - this._updateState(); - this._cacheCoverArt(); - this.emit('changed'); - } - ); - if (!this._proxy.g_name_owner) - this.close(); - - this._updateState(); - this._cacheCoverArt(); - this.emit('ready'); - } - - _updateState() { - let metadata = {}; - for (let prop in this._proxy.Metadata) - metadata[prop] = this._proxy.Metadata[prop].deep_unpack(); - - this._trackArtists = metadata['xesam:artist']; - if (!Array.isArray(this._trackArtists) || - !this._trackArtists.every(artist => typeof artist === 'string')) - this._trackArtists = ["Unknown artist"]; - - this._trackTitle = metadata['xesam:title']; - if (typeof this._trackTitle !== 'string') - this._trackTitle = "Unknown title"; - - this._trackCoverUrl = metadata['mpris:artUrl']; - if (typeof this._trackCoverUrl !== 'string') - this._trackCoverUrl = ''; - - this._length = metadata['mpris:length']; - if (typeof this._length !== 'number') - this._length = -1; - else - this._length = Number.parseInt(`${this._length}`.substring(0, 3)); +const MprisPlayer = GObject.registerClass( + { + Signals: { changed: {}, closed: {}, ready: {} }, + }, + class MprisPlayer extends GObject.Object { + constructor(busName) { + super(); + + this._proxy = new MprisPlayerProxy( + Gio.DBus.session, + busName, + "/org/mpris/MediaPlayer2", + this._onPlayerProxyReady.bind(this), + ); - this._position = this._proxy.Position; - if (typeof this._position !== 'number') + this._busName = busName; + this._name = _getName(busName); + this._playerIcon = + PlayerIcons?.[this._name] || PlayerIcons.deafult || ""; + this._trackArtists = []; + this._trackTitle = ""; + this._trackCoverUrl = ""; + this._coverPath = ""; + this._playBackStatus = ""; + this._canGoNext = false; + this._canGoPrev = false; + this._canPlay = false; + this._shuffle = false; + this._loopStatus = ""; + this._volume = -1; + this._length = -1; this._position = -1; - else - this._position = this._position/1000000; - - this._playBackStatus = this._proxy.PlaybackStatus; - this._canGoNext = this._proxy.CanGoNext; - this._canGoPrev = this._proxy.CanGoPrevious; - this._canPlay = this._proxy.CanPlay; - - this._shuffle = this._proxy.Shuffle; - if (typeof this._shuffle !== 'boolean') { - this._shuffle = null; } - this._loopStatus = this._proxy.LoopStatus; - if (typeof this._loopStatus !== 'string') { - this._loopStatus = null; + + close() { + this._proxy.disconnect(this._playerBinding1); + this._proxy.disconnect(this._playerBinding2); + this._proxy = null; + + this.emit("closed"); } - this._volume = this._proxy.Volume; - if(typeof this._volume !== 'number'){ - this._volume = -1; + + _onPlayerProxyReady() { + this._playerBinding1 = this._proxy.connect( + "notify::g-name-owner", + () => { + if (!this._proxy.g_name_owner) this.close(); + }, + ); + this._playerBinding2 = this._proxy.connect( + "g-properties-changed", + () => { + this._updateState(); + this._cacheCoverArt(); + this.emit("changed"); + }, + ); + if (!this._proxy.g_name_owner) this.close(); + + this._updateState(); + this._cacheCoverArt(); + this.emit("ready"); + } + + _updateState() { + let metadata = {}; + for (let prop in this._proxy.Metadata) + metadata[prop] = this._proxy.Metadata[prop].deep_unpack(); + + this._trackArtists = metadata["xesam:artist"]; + if ( + !Array.isArray(this._trackArtists) || + !this._trackArtists.every( + (artist) => typeof artist === "string", + ) + ) + this._trackArtists = ["Unknown artist"]; + + this._trackTitle = metadata["xesam:title"]; + if (typeof this._trackTitle !== "string") + this._trackTitle = "Unknown title"; + + this._trackCoverUrl = metadata["mpris:artUrl"]; + if (typeof this._trackCoverUrl !== "string") + this._trackCoverUrl = ""; + + this._length = metadata["mpris:length"]; + if (typeof this._length !== "number") this._length = -1; + else + this._length = Number.parseInt( + `${this._length}`.substring(0, 3), + ); + + this._position = this._proxy.Position; + if (typeof this._position !== "number") this._position = -1; + else this._position = this._position / 1000000; + + this._playBackStatus = this._proxy.PlaybackStatus; + this._canGoNext = this._proxy.CanGoNext; + this._canGoPrev = this._proxy.CanGoPrevious; + this._canPlay = this._proxy.CanPlay; + + this._shuffle = this._proxy.Shuffle; + if (typeof this._shuffle !== "boolean") { + this._shuffle = null; + } + this._loopStatus = this._proxy.LoopStatus; + if (typeof this._loopStatus !== "string") { + this._loopStatus = null; + } + this._volume = this._proxy.Volume; + if (typeof this._volume !== "number") { + this._volume = -1; + } + } + + _cacheCoverArt() { + this._coverPath = + MEDIA_CACHE_PATH + + `${this._trackArtists.join(", ")}_${this._trackTitle}`.replace( + /[\,\*\?\"\<\>\|\#\:\?\/\']/g, + "", + ); + + if (this._trackCoverUrl === "") return; + if (this._coverPath === "_") return; + if (GLib.file_test(this._coverPath, GLib.FileTest.EXISTS)) return; + + MkDirectory(); + + // Gio.File.new_for_uri(this._trackCoverUrl).copy_async( + // Gio.File.new_for_path(this._coverPath), + // Gio.FileCopyFlags.OVERWRITE, + // GLib.PRIORITY_DEFAULT, + // null, + // null, + // (source, result) => { + // try { source.copy_finish(result) } + // catch (e) { log(`failed to cache ${this._coverPath}`, e) } + // } + // ); + + try { + Gio.File.new_for_uri(this._trackCoverUrl).copy( + Gio.File.new_for_path(this._coverPath), + Gio.FileCopyFlags.OVERWRITE, + null, + null, + ); + } catch (e) { + log(`failed to cache ${this._coverPath}`, e); + } + } + + get json() { + return { + busName: this._busName, //busName + name: _getName(this._busName), + icon: this._playerIcon, + artist: this._trackArtists.join(", "), + title: this._trackTitle, + cover: this._coverPath, + status: this._playBackStatus, + canNext: this._canGoNext, + canPrev: this._canGoPrev, + canPlay: this._canPlay, + shuffle: this._shuffle, + loop: this._loopStatus, + volume: this._volume * 100, + length: this._length, + lengthStr: _lengthStr(this._length), + position: this._position, + }; } - } - - _cacheCoverArt(){ - this._coverPath = MEDIA_CACHE_PATH + `${this._trackArtists.join(', ')}_${this._trackTitle}` - .replace(/[\,\*\?\"\<\>\|\#\:\?\/\']/g, ''); - - if(this._trackCoverUrl === '') return; - if(this._coverPath === '_') return; - if(GLib.file_test(this._coverPath, GLib.FileTest.EXISTS)) return; - - MkDirectory(); - - // Gio.File.new_for_uri(this._trackCoverUrl).copy_async( - // Gio.File.new_for_path(this._coverPath), - // Gio.FileCopyFlags.OVERWRITE, - // GLib.PRIORITY_DEFAULT, - // null, - // null, - // (source, result) => { - // try { source.copy_finish(result) } - // catch (e) { log(`failed to cache ${this._coverPath}`, e) } - // } - // ); - - try { - Gio.File.new_for_uri(this._trackCoverUrl).copy( - Gio.File.new_for_path(this._coverPath), - Gio.FileCopyFlags.OVERWRITE, - null, null + }, +); + +export const Media = GObject.registerClass( + { + Signals: { sync: {}, positions: {} }, + }, + class Media extends GObject.Object { + _init() { + super._init(); + + this._json = {}; + this._positions = {}; + this._players = new Map(); + this._proxy = new DBusProxy( + Gio.DBus.session, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + this._onProxyReady.bind(this), ); - } catch(e) { - log(`failed to cache ${this._coverPath}`, e); - }; - } - - get json() { - return { - busName: this._busName, //busName - name: _getName(this._busName), - icon: this._playerIcon, - artist: this._trackArtists.join(', '), - title: this._trackTitle, - cover: this._coverPath, - status: this._playBackStatus, - canNext: this._canGoNext, - canPrev: this._canGoPrev, - canPlay: this._canPlay, - shuffle: this._shuffle, - loop: this._loopStatus, - volume: this._volume*100, - length: this._length, - lengthStr: _lengthStr(this._length), - position: this._position, - }; - } -}); - -export const Media = GObject.registerClass({ - Signals: { 'sync': {}, 'positions': {} } -}, -class Media extends GObject.Object{ - _init() { - super._init(); - - this._json = {}; - this._positions = {}; - this._players = new Map(); - this._proxy = new DBusProxy(Gio.DBus.session, - 'org.freedesktop.DBus', - '/org/freedesktop/DBus', - this._onProxyReady.bind(this)); - } - - get json() { return this._json } - get positions() { return this._positions } - - _addPlayer(busName) { - if (this._players.get(busName)) - return; - - let player = new MprisPlayer(busName); - player.connect('closed', () => { - this._players.delete(busName); - this._sync(); - }); - player.connect('changed', this._sync.bind(this)); - player.connect('ready', this._sync.bind(this)); - this._players.set(busName, player); - } - - _onProxyReady() { - this._proxy.ListNamesRemote(([names]) => { - names.forEach(name => { - if (name.startsWith('org.mpris.MediaPlayer2.')) - this._addPlayer(name); + } + + get json() { + return this._json; + } + get positions() { + return this._positions; + } + + _addPlayer(busName) { + if (this._players.get(busName)) return; + + let player = new MprisPlayer(busName); + player.connect("closed", () => { + this._players.delete(busName); + this._sync(); }); - }); - this._proxy.connectSignal( - 'NameOwnerChanged', - this._onNameOwnerChanged.bind(this) - ); - this._sync(); - } - - _onNameOwnerChanged(proxy, sender, [name, oldOwner, newOwner]) { - if (!name.startsWith('org.mpris.MediaPlayer2.')) - return; - - if (newOwner && !oldOwner) - this._addPlayer(name); - } - - _sync(){ - let preferred = null; - let players = []; - for (const [_, player] of this._players) { - if(player.json.busName.includes(PREFERRED_PLAYER)) - preferred = player.json - - players.push(player.json); + player.connect("changed", this._sync.bind(this)); + player.connect("ready", this._sync.bind(this)); + this._players.set(busName, player); } - if(this._players.size === 1) - preferred = players[0]; + _onProxyReady() { + this._proxy.ListNamesRemote(([names]) => { + names.forEach((name) => { + if (name.startsWith("org.mpris.MediaPlayer2.")) + this._addPlayer(name); + }); + }); + this._proxy.connectSignal( + "NameOwnerChanged", + this._onNameOwnerChanged.bind(this), + ); + this._sync(); + } + + _onNameOwnerChanged(proxy, sender, [name, oldOwner, newOwner]) { + if (!name.startsWith("org.mpris.MediaPlayer2.")) return; + + if (newOwner && !oldOwner) this._addPlayer(name); + } + + _sync() { + let preferred = null; + let players = []; + for (const [_, player] of this._players) { + if (player.json.busName.includes(PREFERRED_PLAYER)) + preferred = player.json; - this._json = { - preferred, - players + players.push(player.json); + } + + if (this._players.size === 1) preferred = players[0]; + + this._json = { + preferred, + players, + }; + this.emit("sync"); } - this.emit('sync'); - } - - getPositions(){ - if(this._players.size === 0) return; - let playersReady = 0; - let positions = {}; - for (const [busName, _] of this._players) { - new MprisPlayer(busName).connect('ready', mpris => { - positions[mpris.json.name] = { - length: mpris.json.length, - lengthStr: _lengthStr(mpris.json.length), - position: mpris.json.position, - positionStr: _lengthStr(mpris.json.position) - }; - playersReady++ - - if(playersReady === this._players.size) { - this._positions = positions; - this.emit('positions'); - } - - mpris.close(); - }) + + getPositions() { + if (this._players.size === 0) return; + let playersReady = 0; + let positions = {}; + for (const [busName, _] of this._players) { + new MprisPlayer(busName).connect("ready", (mpris) => { + positions[mpris.json.name] = { + length: mpris.json.length, + lengthStr: _lengthStr(mpris.json.length), + position: mpris.json.position, + positionStr: _lengthStr(mpris.json.position), + }; + playersReady++; + + if (playersReady === this._players.size) { + this._positions = positions; + this.emit("positions"); + } + + mpris.close(); + }); + } + return true; } - return true; - } -}) + }, +); diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/network.js b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/network.js index dd6579c14..7d150c304 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/network.js +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/network.js @@ -1,123 +1,154 @@ -import { NM, Gio, GObject } from './lib.js' +import { NM, Gio, GObject } from "./lib.js"; function showNotification(title, message) { - let notification = new Gio.Notification(); - notification.set_title(title); - notification.set_body(message); - notification.set_priority(Gio.NotificationPriority.NORMAL); - application.register(null); - application.send_notification(null, notification); - GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 2, () => { - application.quit(); - return GLib.SOURCE_REMOVE; - }); + let notification = new Gio.Notification(); + notification.set_title(title); + notification.set_body(message); + notification.set_priority(Gio.NotificationPriority.NORMAL); + application.register(null); + application.send_notification(null, notification); + GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 2, () => { + application.quit(); + return GLib.SOURCE_REMOVE; + }); } -Gio._promisify(NM.Client, 'new_async'); -Gio._promisify(NM.DeviceWifi.prototype, 'request_scan_async'); +Gio._promisify(NM.Client, "new_async"); +Gio._promisify(NM.DeviceWifi.prototype, "request_scan_async"); const WifiStyles = { - '󰪎': 'none', - '󰤮': 'low', - '󰤯': 'low', - '󰤟': 'low', - '󰤢': 'medium', - '󰤥': 'medium', - '󰤨': 'high' -} - -export const Network = GObject.registerClass({ - Signals: { 'sync': {} } -}, - class Network extends GObject.Object { - constructor() { - super(); - - this._json = {}; - this._getClient(); - } - - get json() { return this._json } - - _getDevice(devType) { - return this._client - .get_devices() - .find(device => device.get_device_type() === devType); - } - - async _getClient() { - this._client = await NM.Client.new_async(null); - this._client.connect('notify::wireless-enabled', this._sync.bind(this)); - this._client.connect('notify::connectivity', this._sync.bind(this)); - this._client.connect('notify::primary-connection', this._sync.bind(this)); - this._client.connect('notify::activating-connection', this._sync.bind(this)); - - this._wifi = this._getDevice(NM.DeviceType.WIFI); - if (this._wifi) { - this._wifi.connect('notify::active-access-point', this._activeAp.bind(this)); - //this._wifi.connect('access-point-added', (_, ap) => this._apAdded(ap)); - //this._wifi.connect('access-point-removed', (_, ap) => this._apRemoved(ap)); - } - - this._activeAp(); - this._sync(); - } - - //_apAdded(ap) { - // let ssid = NM.utils_ssid_to_utf8(ap.get_ssid().get_data()); - // showNotification('Access Point Added', `The access point "${ssid}" has been added.`); - // this._sync(); - //} - - //_apRemoved(ap) { - // let ssid = NM.utils_ssid_to_utf8(ap.get_ssid().get_data()); - // showNotification('Access Point Removed', `The access point "${ssid}" has been removed.`); - // this._sync(); - //} - - _activeAp() { - if (this._ap) this._ap.disconnect(this._apBind); - this._ap = this._wifi?.get_active_access_point(); - if (!this._ap) return; - this._apBind = this._ap.connect('notify::strength', this._sync.bind(this)); - this._sync(); - } - - _sync() { - const mainConnection = - this._client.get_primary_connection() || - this._client.get_activating_connection(); - - const primary_type = mainConnection?.type || null; // 802-11-wireless ; 802-3-ethernet - const internet = this._client.connectivity === NM.ConnectivityState.FULL; - - let wifi = { - primary: primary_type === '802-11-wireless', - enabled: this._client.wireless_enabled, - state: this._client.wireless_enabled ? 'on' : 'off', - ssid: this._ap && NM.utils_ssid_to_utf8( - this._ap.get_ssid().get_data()) || 'Unknown', - strength: this._client.wireless_enabled && mainConnection ? `${this._ap?.strength}%` : '󰂭', - icon: ['󰤮', '󰤯', '󰤟', '󰤢', '󰤥', '󰤨'][Math.ceil(this._ap?.strength / 20)] - }; - if (!internet) { - wifi.strength = '󰪎' - wifi.icon = '󰪎' - } - wifi.style = WifiStyles[wifi.icon]; - - let wired = { - primary: primary_type === '802-3-ethernet', - icon: internet ? '󰛳' : '󰪎' - } - - this._json = { - primary: { '802-3-ethernet': 'wired', '802-11-wireless': 'wifi' }[primary_type] || 'none', - none: { icon: '󰤮' }, - wifi, - wired, - }; - this.emit('sync') - } - - }) + "󰪎": "none", + "󰤮": "low", + "󰤯": "low", + "󰤟": "low", + "󰤢": "medium", + "󰤥": "medium", + "󰤨": "high", +}; + +export const Network = GObject.registerClass( + { + Signals: { sync: {} }, + }, + class Network extends GObject.Object { + constructor() { + super(); + + this._json = {}; + this._getClient(); + } + + get json() { + return this._json; + } + + _getDevice(devType) { + return this._client + .get_devices() + .find((device) => device.get_device_type() === devType); + } + + async _getClient() { + this._client = await NM.Client.new_async(null); + this._client.connect( + "notify::wireless-enabled", + this._sync.bind(this), + ); + this._client.connect("notify::connectivity", this._sync.bind(this)); + this._client.connect( + "notify::primary-connection", + this._sync.bind(this), + ); + this._client.connect( + "notify::activating-connection", + this._sync.bind(this), + ); + + this._wifi = this._getDevice(NM.DeviceType.WIFI); + if (this._wifi) { + this._wifi.connect( + "notify::active-access-point", + this._activeAp.bind(this), + ); + //this._wifi.connect('access-point-added', (_, ap) => this._apAdded(ap)); + //this._wifi.connect('access-point-removed', (_, ap) => this._apRemoved(ap)); + } + + this._activeAp(); + this._sync(); + } + + //_apAdded(ap) { + // let ssid = NM.utils_ssid_to_utf8(ap.get_ssid().get_data()); + // showNotification('Access Point Added', `The access point "${ssid}" has been added.`); + // this._sync(); + //} + + //_apRemoved(ap) { + // let ssid = NM.utils_ssid_to_utf8(ap.get_ssid().get_data()); + // showNotification('Access Point Removed', `The access point "${ssid}" has been removed.`); + // this._sync(); + //} + + _activeAp() { + if (this._ap) this._ap.disconnect(this._apBind); + this._ap = this._wifi?.get_active_access_point(); + if (!this._ap) return; + this._apBind = this._ap.connect( + "notify::strength", + this._sync.bind(this), + ); + this._sync(); + } + + _sync() { + const mainConnection = + this._client.get_primary_connection() || + this._client.get_activating_connection(); + + const primary_type = mainConnection?.type || null; // 802-11-wireless ; 802-3-ethernet + const internet = + this._client.connectivity === NM.ConnectivityState.FULL; + + let wifi = { + primary: primary_type === "802-11-wireless", + enabled: this._client.wireless_enabled, + state: this._client.wireless_enabled ? "on" : "off", + ssid: + (this._ap && + NM.utils_ssid_to_utf8( + this._ap.get_ssid().get_data(), + )) || + "Unknown", + strength: + this._client.wireless_enabled && mainConnection + ? `${this._ap?.strength}%` + : "󰂭", + icon: ["󰤮", "󰤯", "󰤟", "󰤢", "󰤥", "󰤨"][ + Math.ceil(this._ap?.strength / 20) + ], + }; + if (!internet) { + wifi.strength = "󰪎"; + wifi.icon = "󰪎"; + } + wifi.style = WifiStyles[wifi.icon]; + + let wired = { + primary: primary_type === "802-3-ethernet", + icon: internet ? "󰛳" : "󰪎", + }; + + this._json = { + primary: + { "802-3-ethernet": "wired", "802-11-wireless": "wifi" }[ + primary_type + ] || "none", + none: { icon: "󰤮" }, + wifi, + wired, + }; + this.emit("sync"); + } + }, +); diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/notifications.js b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/notifications.js index c66d512ce..b4de8c87b 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/notifications.js +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/host/notifications.js @@ -1,235 +1,286 @@ -import { NotificationIFace } from "./dbus.js" -import { NOTIFICATIONS_CACHE_PATH, NOTIFICATIONS_BANNER_TIME_OUT, MkDirectory, CACHE_PATH } from './main.js' -import { GObject, Gio, Gtk, GdkPixbuf, GLib } from './lib.js' - -export const Notifications = GObject.registerClass({ - Signals: { 'sync': {} } -}, - class Notifications extends GObject.Object { - constructor(fg_color = 'white') { - super(); - - this._fgColor = fg_color; - this._json = {}; - this._dnd = false; - this._idCound = 1; - this._notifications = new Map(); - this._popups = new Map(); - this._readFromFile(); - this._register(); - this._sync(); - } - - get json() { return this._json } - - get DoNotDisturb() { - return this._dnd; - } - - Clear() { - for (const [_, notification] of this._notifications) { - this.CloseNotification(notification.id); - } - } - - Notify(app_name, replaces_id, app_icon, summary, body, actions, hints, time_out) { - let acts = []; - for (let i = 0; i < actions.length; i += 2) { - if (actions[i + 1] !== '') - acts.push({ - label: actions[i + 1], - id: actions[i] - }) - } - let id = replaces_id || this._idCound++; - let date = new Date(); - let notification = { - id, - app_name, - app_icon, - summary, - body, - actions: acts, - time: { hour: date.getHours(), minute: date.getMinutes() > 9 ? date.getMinutes() : `0${date.getMinutes()}` }, - image: - this._parseImage(hints['image-data'], `${summary}${id}`) || - this._parseIcon(app_icon, `${summary}${id}`) || - this._parseIcon(app_name, `${summary}${id}`) - } - this._notifications.set(notification.id, notification); - if (!this._dnd) { - this._popups.set(notification.id, notification); - GLib.timeout_add(GLib.PRIORITY_DEFAULT, - time_out > 0 ? time_out : NOTIFICATIONS_BANNER_TIME_OUT, - () => { - if (!this._popups.has(id)) return; - this._popups.delete(notification.id); +import { NotificationIFace } from "./dbus.js"; +import { + NOTIFICATIONS_CACHE_PATH, + NOTIFICATIONS_BANNER_TIME_OUT, + MkDirectory, + CACHE_PATH, +} from "./main.js"; +import { GObject, Gio, Gtk, GdkPixbuf, GLib } from "./lib.js"; + +export const Notifications = GObject.registerClass( + { + Signals: { sync: {} }, + }, + class Notifications extends GObject.Object { + constructor(fg_color = "white") { + super(); + + this._fgColor = fg_color; + this._json = {}; + this._dnd = false; + this._idCound = 1; + this._notifications = new Map(); + this._popups = new Map(); + this._readFromFile(); + this._register(); this._sync(); - } - ); - } - this._sync(); - return notification.id; - } - - ToggleDND() { - this._dnd = !this._dnd; - this._sync(); - } - - DismissNotification(id) { - this._popups.delete(id); - this._sync(); - } - - DismissLatestNotification() { - this._popups.delete([...this._popups.keys()].pop()); - this._sync(); - } - - CloseNotification(id) { - if (!this._notifications.has(id)) return; - this._dbus.emit_signal('NotificationClosed', GLib.Variant.new('(uu)', [id, 2])); - this._notifications.delete(id); - this._popups.delete(id); - this._sync(); - } - - CloseLatestNotification() { - const latestNotificationId = [...this._notifications.keys()].pop(); - if (latestNotificationId) { - this.CloseNotification(latestNotificationId); - } - } - - InvokeAction(id, action) { - if (!this._notifications.has(id)) return; - this._dbus.emit_signal('ActionInvoked', GLib.Variant.new('(us)', [id, action])); - this._notifications.delete(id); - this._popups.delete(id); - this._sync(); - } - - GetCapabilities() { - return ['actions', 'body', 'icon-static', 'persistence']; - } - - GetServerInformation() { - return new GLib.Variant('(ssss)', [ - "host", - "isabel", - "0.1", - "1.2", - ]) - } - - _register() { - Gio.bus_own_name( - Gio.BusType.SESSION, - 'org.freedesktop.Notifications', - Gio.BusNameOwnerFlags.NONE, - (connection, _) => { - this._dbus = Gio.DBusExportedObject.wrapJSObject(NotificationIFace, this); - this._dbus.export(connection, '/org/freedesktop/Notifications'); - }, - null, - () => { - print('Another Notification Daemon is already running!') - } - ); - } - - _filterName(name) { - return NOTIFICATIONS_CACHE_PATH + name.replace(/[\ \,\*\?\"\<\>\|\#\:\?\/\!\']/g, '') + '.png'; - } - - _parseIcon(icon_name, name) { - if (!icon_name) return; - - MkDirectory(); - let fileName = this._filterName(name); - let iconInfo = Gtk.IconTheme.get_default() - .lookup_by_gicon( - Gio.Icon.new_for_string(icon_name), - 128, null); - - if (!iconInfo) return null; - - let output_stream = - Gio.File.new_for_path(fileName) - .replace(null, false, Gio.FileCreateFlags.NONE, null); - - iconInfo.load_icon() - .save_to_streamv(output_stream, 'png', null, null, null); - - output_stream.close(null); - - if (icon_name.includes('-symbolic')) - GLib.spawn_command_line_sync(`convert ${fileName} -alpha on + } + + get json() { + return this._json; + } + + get DoNotDisturb() { + return this._dnd; + } + + Clear() { + for (const [_, notification] of this._notifications) { + this.CloseNotification(notification.id); + } + } + + Notify( + app_name, + replaces_id, + app_icon, + summary, + body, + actions, + hints, + time_out, + ) { + let acts = []; + for (let i = 0; i < actions.length; i += 2) { + if (actions[i + 1] !== "") + acts.push({ + label: actions[i + 1], + id: actions[i], + }); + } + let id = replaces_id || this._idCound++; + let date = new Date(); + let notification = { + id, + app_name, + app_icon, + summary, + body, + actions: acts, + time: { + hour: date.getHours(), + minute: + date.getMinutes() > 9 + ? date.getMinutes() + : `0${date.getMinutes()}`, + }, + image: + this._parseImage(hints["image-data"], `${summary}${id}`) || + this._parseIcon(app_icon, `${summary}${id}`) || + this._parseIcon(app_name, `${summary}${id}`), + }; + this._notifications.set(notification.id, notification); + if (!this._dnd) { + this._popups.set(notification.id, notification); + GLib.timeout_add( + GLib.PRIORITY_DEFAULT, + time_out > 0 ? time_out : NOTIFICATIONS_BANNER_TIME_OUT, + () => { + if (!this._popups.has(id)) return; + this._popups.delete(notification.id); + this._sync(); + }, + ); + } + this._sync(); + return notification.id; + } + + ToggleDND() { + this._dnd = !this._dnd; + this._sync(); + } + + DismissNotification(id) { + this._popups.delete(id); + this._sync(); + } + + DismissLatestNotification() { + this._popups.delete([...this._popups.keys()].pop()); + this._sync(); + } + + CloseNotification(id) { + if (!this._notifications.has(id)) return; + this._dbus.emit_signal( + "NotificationClosed", + GLib.Variant.new("(uu)", [id, 2]), + ); + this._notifications.delete(id); + this._popups.delete(id); + this._sync(); + } + + CloseLatestNotification() { + const latestNotificationId = [...this._notifications.keys()].pop(); + if (latestNotificationId) { + this.CloseNotification(latestNotificationId); + } + } + + InvokeAction(id, action) { + if (!this._notifications.has(id)) return; + this._dbus.emit_signal( + "ActionInvoked", + GLib.Variant.new("(us)", [id, action]), + ); + this._notifications.delete(id); + this._popups.delete(id); + this._sync(); + } + + GetCapabilities() { + return ["actions", "body", "icon-static", "persistence"]; + } + + GetServerInformation() { + return new GLib.Variant("(ssss)", ["host", "isabel", "0.1", "1.2"]); + } + + _register() { + Gio.bus_own_name( + Gio.BusType.SESSION, + "org.freedesktop.Notifications", + Gio.BusNameOwnerFlags.NONE, + (connection, _) => { + this._dbus = Gio.DBusExportedObject.wrapJSObject( + NotificationIFace, + this, + ); + this._dbus.export( + connection, + "/org/freedesktop/Notifications", + ); + }, + null, + () => { + print("Another Notification Daemon is already running!"); + }, + ); + } + + _filterName(name) { + return ( + NOTIFICATIONS_CACHE_PATH + + name.replace(/[\ \,\*\?\"\<\>\|\#\:\?\/\!\']/g, "") + + ".png" + ); + } + + _parseIcon(icon_name, name) { + if (!icon_name) return; + + MkDirectory(); + let fileName = this._filterName(name); + let iconInfo = Gtk.IconTheme.get_default().lookup_by_gicon( + Gio.Icon.new_for_string(icon_name), + 128, + null, + ); + + if (!iconInfo) return null; + + let output_stream = Gio.File.new_for_path(fileName).replace( + null, + false, + Gio.FileCreateFlags.NONE, + null, + ); + + iconInfo + .load_icon() + .save_to_streamv(output_stream, "png", null, null, null); + + output_stream.close(null); + + if (icon_name.includes("-symbolic")) + GLib.spawn_command_line_sync(`convert ${fileName} -alpha on -fill ${this._fgColor} -colorize 100% -bordercolor transparent -border 16 ${fileName}`); - return fileName; - } - - _readFromFile() { - try { - const file = Gio.File.new_for_path(CACHE_PATH + 'notifications.json'); - const [, contents, etag] = file.load_contents(null); - const json = JSON.parse(new TextDecoder('utf-8').decode(contents)) - json.notifications.forEach(n => { - if (n.id > this._idCound) this._idCound = n.id + 1; - this._notifications.set(n.id, n); - }) - } catch (error) { - print('There were no cached notifications found!') - print('If you want your notifications to be cached run with --file flag'); - } - } - - _parseImage(image_data, name) { - if (!image_data) return; - MkDirectory(); - let fileName = this._filterName(name); - let image = image_data.recursiveUnpack(); - let pixbuf = GdkPixbuf.Pixbuf.new_from_bytes( - image[6], - GdkPixbuf.Colorspace.RGB, - image[3], - image[4], - image[0], - image[1], - image[2] - ); - - let output_stream = - Gio.File.new_for_path(fileName) - .replace(null, false, Gio.FileCreateFlags.NONE, null); - - pixbuf.save_to_streamv(output_stream, "png", null, null, null); - output_stream.close(null); - - return fileName; - } - - _sync() { - let notifications = [], popups = []; - for (const [_, notification] of this._notifications) - notifications.push(notification); - - for (const [_, notification] of this._popups) - popups.push(notification); - - this._json = { - dnd: { - enabled: this._dnd, - state: this._dnd ? 'on' : 'off', - icon: this._dnd ? '󰂛' : '󰂚', - }, - count: notifications.length, - icon: this._dnd ? '󰂛' : (notifications.length > 0 ? '󱅫' : '󰂚'), - notifications, - popups - } - this.emit('sync'); - } - }) + return fileName; + } + + _readFromFile() { + try { + const file = Gio.File.new_for_path( + CACHE_PATH + "notifications.json", + ); + const [, contents, etag] = file.load_contents(null); + const json = JSON.parse( + new TextDecoder("utf-8").decode(contents), + ); + json.notifications.forEach((n) => { + if (n.id > this._idCound) this._idCound = n.id + 1; + this._notifications.set(n.id, n); + }); + } catch (error) { + print("There were no cached notifications found!"); + print( + "If you want your notifications to be cached run with --file flag", + ); + } + } + + _parseImage(image_data, name) { + if (!image_data) return; + MkDirectory(); + let fileName = this._filterName(name); + let image = image_data.recursiveUnpack(); + let pixbuf = GdkPixbuf.Pixbuf.new_from_bytes( + image[6], + GdkPixbuf.Colorspace.RGB, + image[3], + image[4], + image[0], + image[1], + image[2], + ); + + let output_stream = Gio.File.new_for_path(fileName).replace( + null, + false, + Gio.FileCreateFlags.NONE, + null, + ); + + pixbuf.save_to_streamv(output_stream, "png", null, null, null); + output_stream.close(null); + + return fileName; + } + + _sync() { + let notifications = [], + popups = []; + for (const [_, notification] of this._notifications) + notifications.push(notification); + + for (const [_, notification] of this._popups) + popups.push(notification); + + this._json = { + dnd: { + enabled: this._dnd, + state: this._dnd ? "on" : "off", + icon: this._dnd ? "󰂛" : "󰂚", + }, + count: notifications.length, + icon: this._dnd ? "󰂛" : notifications.length > 0 ? "󱅫" : "󰂚", + notifications, + popups, + }; + this.emit("sync"); + } + }, +); diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/launcher b/home/isabel/programs/gui/confs/bars/eww/config/scripts/launcher index 47721b7c1..1d8b2130a 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/launcher +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/launcher @@ -1,44 +1,44 @@ #!/usr/bin/env bash function toggle_menu { - hyprctl keyword blurls "remove,gtk-layer-shell" - STATE=$(eww windows | grep $1 | awk '{print substr ($0, 0, 1)}') - if [[ $STATE == '*' ]]; then - # if [[ $1 == 'powermenu' ]]; then hyprctl keyword blurls "remove,gtk-layer-shell"; fi - eww close $1 - else - if [[ $1 == 'powermenu' ]]; then hyprctl keyword blurls "gtk-layer-shell"; fi - if [[ $1 == 'app_launcher' ]]; then $HOME/.config/eww/scripts/apps query ""; fi - eww open $1 - fi + hyprctl keyword blurls "remove,gtk-layer-shell" + STATE=$(eww windows | grep $1 | awk '{print substr ($0, 0, 1)}') + if [[ $STATE == '*' ]]; then + # if [[ $1 == 'powermenu' ]]; then hyprctl keyword blurls "remove,gtk-layer-shell"; fi + eww close $1 + else + if [[ $1 == 'powermenu' ]]; then hyprctl keyword blurls "gtk-layer-shell"; fi + if [[ $1 == 'app_launcher' ]]; then $HOME/.config/eww/scripts/apps query ""; fi + eww open $1 + fi } function colorpicker { - pkill hyprpicker - hyprpicker -n -a + pkill hyprpicker + hyprpicker -n -a } function network { - nm-connection-editor + nm-connection-editor } function screenlock { - STATE=$(eww windows | grep powermenu | awk '{print substr ($0, 0, 1)}') - if [[ $STATE == '*' ]]; then eww close powermenu; fi - swaylock + STATE=$(eww windows | grep powermenu | awk '{print substr ($0, 0, 1)}') + if [[ $STATE == '*' ]]; then eww close powermenu; fi + swaylock } function clipboard { - cliphist list | rofi -dmenu -p "Clipboard" | cliphist decode | wl-copy + cliphist list | rofi -dmenu -p "Clipboard" | cliphist decode | wl-copy } function config { - $VISUAL $HOME/.config/hypr + $VISUAL $HOME/.config/hypr } function powersettings { - alacritty --class Power --title Power --hold \ - --command auto-cpufreq --stats + alacritty --class Power --title Power --hold \ + --command auto-cpufreq --stats } if [[ $1 == 'applauncher' ]]; then rofi -show drun; fi diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/network b/home/isabel/programs/gui/confs/bars/eww/config/scripts/network index 8aa6b8be2..180522457 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/network +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/network @@ -1,9 +1,9 @@ #!/usr/bin/env bash function toggle { - STATE=$(nmcli radio wifi) - if [[ $STATE == 'enabled' ]]; then nmcli radio wifi off - else nmcli radio wifi on; fi + STATE=$(nmcli radio wifi) + if [[ $STATE == 'enabled' ]]; then nmcli radio wifi off + else nmcli radio wifi on; fi } if [[ $1 == 'toggle' ]]; then toggle; fi diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/night_light b/home/isabel/programs/gui/confs/bars/eww/config/scripts/night_light index 2216fecae..134b484cd 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/night_light +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/night_light @@ -1,31 +1,31 @@ #!/usr/bin/env bash function state { - STATE=$(pgrep wlsunset) - if [[ -z $STATE ]]; then echo 'off' - else echo 'on'; fi + STATE=$(pgrep wlsunset) + if [[ -z $STATE ]]; then echo 'off' + else echo 'on'; fi } function icon { - echo '󰖨' + echo '󰖨' } function toggle { - STATE=$(state) - if [[ $STATE == 'on' ]]; then - eww update night_light_state="{ \"state\": \"off\", \"icon\": \"$(icon)\"}" - pkill wlsunset - else - eww update night_light_state="{ \"state\": \"on\", \"icon\": \"$(icon)\"}" - wlsunset -t 3400 - fi + STATE=$(state) + if [[ $STATE == 'on' ]]; then + eww update night_light_state="{ \"state\": \"off\", \"icon\": \"$(icon)\"}" + pkill wlsunset + else + eww update night_light_state="{ \"state\": \"on\", \"icon\": \"$(icon)\"}" + wlsunset -t 3400 + fi } function get { - echo "{ - \"state\": \"$(state)\", - \"icon\": \"$(icon)\" - }" + echo "{ + \"state\": \"$(state)\", + \"icon\": \"$(icon)\" + }" } if [[ $1 == 'toggle' ]]; then toggle; fi diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/osd b/home/isabel/programs/gui/confs/bars/eww/config/scripts/osd index e9c468eac..eda244cc9 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/osd +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/osd @@ -3,10 +3,10 @@ STATE=$(eww windows | grep osd | awk '{print substr ($0, 0, 1)}') if [[ $1 == 'close' ]]; then - if [[ $STATE == '*' ]]; then eww close osd; fi + if [[ $STATE == '*' ]]; then eww close osd; fi else - eww update osd="{ \"icon\": \"$1\", \"value\": \"$2\" }" - if [[ $STATE != '*' ]]; then eww open osd; fi - sleep 4 - if [[ $STATE == '*' ]]; then eww close osd; fi -fi \ No newline at end of file + eww update osd="{ \"icon\": \"$1\", \"value\": \"$2\" }" + if [[ $STATE != '*' ]]; then eww open osd; fi + sleep 4 + if [[ $STATE == '*' ]]; then eww close osd; fi +fi diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/player b/home/isabel/programs/gui/confs/bars/eww/config/scripts/player index 53368cdda..b4359bfa2 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/player +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/player @@ -1,10 +1,10 @@ #!/usr/bin/env bash function loop { - LOOPSTATUS=$(playerctl -p $1 loop) - if [[ $LOOPSTATUS == 'None' ]]; then playerctl -p $1 loop Track; fi - if [[ $LOOPSTATUS == 'Track' ]]; then playerctl -p $1 loop Playlist; fi - if [[ $LOOPSTATUS == 'Playlist' ]]; then playerctl -p $1 loop None; fi + LOOPSTATUS=$(playerctl -p $1 loop) + if [[ $LOOPSTATUS == 'None' ]]; then playerctl -p $1 loop Track; fi + if [[ $LOOPSTATUS == 'Track' ]]; then playerctl -p $1 loop Playlist; fi + if [[ $LOOPSTATUS == 'Playlist' ]]; then playerctl -p $1 loop None; fi } if [[ $2 == 'up' ]]; then playerctl -p $1 next; fi diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/power b/home/isabel/programs/gui/confs/bars/eww/config/scripts/power index 8c468eabc..d995ae843 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/power +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/power @@ -36,9 +36,9 @@ function toggle { function get { echo "{ - \"state\": \"$(state)\", - \"icon\": \"$(icon)\" -}" + \"state\": \"$(state)\", + \"icon\": \"$(icon)\" + }" } if [[ $1 == 'get' ]]; then get; fi diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/screenshot b/home/isabel/programs/gui/confs/bars/eww/config/scripts/screenshot index 4fae01841..25470ae9c 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/screenshot +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/screenshot @@ -4,35 +4,35 @@ screenshot=/tmp/screenshot.png path=~/media/pictures/screenshots window() { - grimblast save active $screenshot + grimblast save active $screenshot } area() { - grim -g "$(slurp)" $screenshot + grim -g "$(slurp)" $screenshot } screen() { - grim $screenshot + grim $screenshot } preview() { - $HOME/.config/eww/scripts/launcher toggle_menu previewshot + $HOME/.config/eww/scripts/launcher toggle_menu previewshot } discard() { - rm "${screenshot}" + rm "${screenshot}" } save() { - name="screenshot-$(date +%h-%m-%s_%d-%m-%y).png" - mkdir -p $path - cp $screenshot $path/$name - notify-send "screenshot saved!" "saved to ${path}/${name}" -i $screenshot + name="screenshot-$(date +%h-%m-%s_%d-%m-%y).png" + mkdir -p $path + cp $screenshot $path/$name + notify-send "screenshot saved!" "saved to ${path}/${name}" -i $screenshot } copy() { - wl-copy <$screenshot - notify-send "screenshot copied!" -i $screenshot + wl-copy <$screenshot + notify-send "screenshot copied!" -i $screenshot } case $1 in diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/theme b/home/isabel/programs/gui/confs/bars/eww/config/scripts/theme index ce77467d8..8e2dfee14 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/theme +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/theme @@ -23,9 +23,9 @@ function get { icon='󱎖' if [[ $(state) == 'on' ]]; then icon='󰃛'; fi echo "{ - \"state\": \"$(state)\", - \"icon\": \"$icon\" - }" + \"state\": \"$(state)\", + \"icon\": \"$icon\" + }" } if [[ $1 == 'toggle' ]]; then toggle; fi diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/todo b/home/isabel/programs/gui/confs/bars/eww/config/scripts/todo index 54c33d433..26ee77125 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/todo +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/todo @@ -1,367 +1,434 @@ #!/usr/bin/env gjs -'use strict' +"use strict"; const { Gio, GLib } = imports.gi; -const SUBSTITUTES_PATH = GLib.get_home_dir() + '/.local/share/todo/substitutes.json'; -const TASKS_PATH = GLib.get_home_dir() + '/Documents/tasks.json'; +const SUBSTITUTES_PATH = + GLib.get_home_dir() + "/.local/share/todo/substitutes.json"; +const TASKS_PATH = GLib.get_home_dir() + "/Documents/tasks.json"; const TERMINAL_WIDTH = 50; function getSubstitutes() { - try { - let file = Gio.File.new_for_path(SUBSTITUTES_PATH); - let [, contents,] = file.load_contents(null); - return JSON.parse(new TextDecoder().decode(contents)); - } - catch { - return { days: [], months: [] }; - } + try { + let file = Gio.File.new_for_path(SUBSTITUTES_PATH); + let [, contents] = file.load_contents(null); + return JSON.parse(new TextDecoder().decode(contents)); + } catch { + return { days: [], months: [] }; + } } function getTasks() { - try { - let file = Gio.File.new_for_path(TASKS_PATH); - let [, contents,] = file.load_contents(null); - let list = JSON.parse(new TextDecoder().decode(contents)); - let tasks = []; - list.forEach(t => tasks.push(new Task(t))); - return tasks; - } - catch { - return []; - } + try { + let file = Gio.File.new_for_path(TASKS_PATH); + let [, contents] = file.load_contents(null); + let list = JSON.parse(new TextDecoder().decode(contents)); + let tasks = []; + list.forEach((t) => tasks.push(new Task(t))); + return tasks; + } catch { + return []; + } } function writeFile(tasks) { - let file = Gio.File.new_for_path(TASKS_PATH); - if (!GLib.file_test(TASKS_PATH, GLib.FileTest.EXISTS)) - file.create(Gio.FileCreateFlags.NONE, null); - - file.replace_contents( - JSON.stringify(tasks, null, 4), - null, false, - Gio.FileCreateFlags.REPLACE_DESTINATION, null - ); + let file = Gio.File.new_for_path(TASKS_PATH); + if (!GLib.file_test(TASKS_PATH, GLib.FileTest.EXISTS)) + file.create(Gio.FileCreateFlags.NONE, null); + + file.replace_contents( + JSON.stringify(tasks, null, 4), + null, + false, + Gio.FileCreateFlags.REPLACE_DESTINATION, + null, + ); } class Date { - constructor(p) { - this.year = p?.year; - this.month = p?.month; - this.day = p?.day; - this.hour = p?.hour; - this.minutes = p?.minutes; - this.asap = p?.asap || false; - - if (typeof p === 'string') - this.fromString(p); - } - - isEmpty() { - return !this.year && !this.month && !this.day && !this.hour && !this.minutes - } - - isLate() { - let d = GLib.DateTime.new_now_local(); - if (this.compare(new Date({ - year: d.get_year(), - month: d.get_month(), - day: d.get_day_of_month(), - hour: d.get_hour(), - minutes: d.get_minute() - })) < 0) { - return true; - } - return false; - } - - isToday() { - let now = GLib.DateTime.new_now_local(); - return this.month === now.get_month() && - this.day === now.get_day_of_month(); - } - - toString() { - if (this.asap) - return ' asap! '; - - let m, d, h, min, md, hm; - if (this.month) - m = `${this.month < 10 ? `0${this.month}` : this.month}` - else m = '--'; - - if (this.day) - d = `${this.day < 10 ? `0${this.day}` : this.day}`; - else d = '--'; - - if (this.hour) - h = `${this.hour < 10 ? `0${this.hour}` : this.hour}` - else h = '--'; - - if (this.minutes) - min = `${this.minutes < 10 ? `0${this.minutes}` : this.minutes}` - else min = '00'; - - md = `${m}/${d}`; - hm = `${h}:${min}` - if (!this.month && !this.day) md = ' '; - if (!this.hour && !this.minutes) hm = ' '; - if (md === ' ' && (this.hour || this.minutes)) md = 'today'; - if (this.isToday()) md = 'today'; - - return `${md} ${hm}`; - } - - valid() { - let now = GLib.DateTime.new_now_local(); - let year = this?.year || now.get_year(); - let month = this?.month || now.get_month(); - let day = this?.day || now.get_day_of_month(); - let hour = this?.hour || now.get_hour(); - let minutes = this?.minutes || now.get_minute(); - return GLib.DateTime.new_local(year, month, day, hour, minutes, 0); - } - - compare(d2) { - if (this.asap) return -1; - if (d2.asap) return 1; - if (this.isEmpty() && d2.isEmpty()) return 0; - if (this.isEmpty()) return 1; - if (d2.isEmpty()) return -1; - - if (this.year > d2.year) - return 1; - else if (this.year < d2.year) - return -1 - else if (this.month > d2.month) - return 1; - else if (this.month < d2.month) - return -1 - else if (this.day > d2.day) - return 1; - else if (this.day < d2.day) - return -1; - else if (this.hour > d2.hour) - return 1; - else if (this.hour < d2.hour) - return -1; - else if (this.minutes > d2.minutes) - return 1; - else if (this.minutes < d2.minutes) - return -1; - - return 0; - } - - fromString(str) { - let substitutes = getSubstitutes(); - let days = substitutes.days; - let months = substitutes.months; - - str.split(' ').forEach(e => { - if (e.toLowerCase() === 'asap') this.asap = true; - if (days[e]) this.day = days[e]; - if (months[e]) this.month = months[e]; - let md = e.split('/'); - if (md.length === 2) { - this.month = Number(md[0]); - this.day = Number(md[1]); - } - let hm = e.split(':') - if (hm.length === 2) { - this.hour = Number(hm[0]); - this.minutes = Number(hm[1]); - } - let ymd = e.split('/'); - if (ymd.length === 3) { - this.year = Number(md[0]); - this.month = Number(md[1]); - this.day = Number(md[2]); - } - if (e.toLowerCase() === "today") { - let now = GLib.DateTime.new_now_local(); - this.month = now.get_month(); - this.day = now.get_day_of_month(); - } - }) - - if (this.year == NaN) this.year = undefined; - if (this.month == NaN) this.month = undefined; - if (this.day == NaN) this.day = undefined; - if (this.hour == NaN) this.hour = undefined; - if (this.minutes == NaN) this.minutes = undefined; - - if (!this.valid()) { throw new Error('Wrong date') } - - return this; - } + constructor(p) { + this.year = p?.year; + this.month = p?.month; + this.day = p?.day; + this.hour = p?.hour; + this.minutes = p?.minutes; + this.asap = p?.asap || false; + + if (typeof p === "string") this.fromString(p); + } + + isEmpty() { + return ( + !this.year && + !this.month && + !this.day && + !this.hour && + !this.minutes + ); + } + + isLate() { + let d = GLib.DateTime.new_now_local(); + if ( + this.compare( + new Date({ + year: d.get_year(), + month: d.get_month(), + day: d.get_day_of_month(), + hour: d.get_hour(), + minutes: d.get_minute(), + }), + ) < 0 + ) { + return true; + } + return false; + } + + isToday() { + let now = GLib.DateTime.new_now_local(); + return ( + this.month === now.get_month() && + this.day === now.get_day_of_month() + ); + } + + toString() { + if (this.asap) return " asap! "; + + let m, d, h, min, md, hm; + if (this.month) + m = `${this.month < 10 ? `0${this.month}` : this.month}`; + else m = "--"; + + if (this.day) d = `${this.day < 10 ? `0${this.day}` : this.day}`; + else d = "--"; + + if (this.hour) h = `${this.hour < 10 ? `0${this.hour}` : this.hour}`; + else h = "--"; + + if (this.minutes) + min = `${this.minutes < 10 ? `0${this.minutes}` : this.minutes}`; + else min = "00"; + + md = `${m}/${d}`; + hm = `${h}:${min}`; + if (!this.month && !this.day) md = " "; + if (!this.hour && !this.minutes) hm = " "; + if (md === " " && (this.hour || this.minutes)) md = "today"; + if (this.isToday()) md = "today"; + + return `${md} ${hm}`; + } + + valid() { + let now = GLib.DateTime.new_now_local(); + let year = this?.year || now.get_year(); + let month = this?.month || now.get_month(); + let day = this?.day || now.get_day_of_month(); + let hour = this?.hour || now.get_hour(); + let minutes = this?.minutes || now.get_minute(); + return GLib.DateTime.new_local(year, month, day, hour, minutes, 0); + } + + compare(d2) { + if (this.asap) return -1; + if (d2.asap) return 1; + if (this.isEmpty() && d2.isEmpty()) return 0; + if (this.isEmpty()) return 1; + if (d2.isEmpty()) return -1; + + if (this.year > d2.year) return 1; + else if (this.year < d2.year) return -1; + else if (this.month > d2.month) return 1; + else if (this.month < d2.month) return -1; + else if (this.day > d2.day) return 1; + else if (this.day < d2.day) return -1; + else if (this.hour > d2.hour) return 1; + else if (this.hour < d2.hour) return -1; + else if (this.minutes > d2.minutes) return 1; + else if (this.minutes < d2.minutes) return -1; + + return 0; + } + + fromString(str) { + let substitutes = getSubstitutes(); + let days = substitutes.days; + let months = substitutes.months; + + str.split(" ").forEach((e) => { + if (e.toLowerCase() === "asap") this.asap = true; + if (days[e]) this.day = days[e]; + if (months[e]) this.month = months[e]; + let md = e.split("/"); + if (md.length === 2) { + this.month = Number(md[0]); + this.day = Number(md[1]); + } + let hm = e.split(":"); + if (hm.length === 2) { + this.hour = Number(hm[0]); + this.minutes = Number(hm[1]); + } + let ymd = e.split("/"); + if (ymd.length === 3) { + this.year = Number(md[0]); + this.month = Number(md[1]); + this.day = Number(md[2]); + } + if (e.toLowerCase() === "today") { + let now = GLib.DateTime.new_now_local(); + this.month = now.get_month(); + this.day = now.get_day_of_month(); + } + }); + + if (this.year == NaN) this.year = undefined; + if (this.month == NaN) this.month = undefined; + if (this.day == NaN) this.day = undefined; + if (this.hour == NaN) this.hour = undefined; + if (this.minutes == NaN) this.minutes = undefined; + + if (!this.valid()) { + throw new Error("Wrong date"); + } + + return this; + } } class Task { - constructor(p) { - this.title = p?.title, - this.desc = p?.desc, - this.date = new Date(p?.date) - } - - parseDate(date) { this.date.fromString(date); } + constructor(p) { + (this.title = p?.title), + (this.desc = p?.desc), + (this.date = new Date(p?.date)); + } + + parseDate(date) { + this.date.fromString(date); + } } function add(input = {}) { - if (!input.title) throw new Error('Needs a title'); - let tasks = getTasks(); - tasks.push(new Task(input)); - tasks.sort((a, b) => a.date.compare(b.date)); - writeFile(tasks); + if (!input.title) throw new Error("Needs a title"); + let tasks = getTasks(); + tasks.push(new Task(input)); + tasks.sort((a, b) => a.date.compare(b.date)); + writeFile(tasks); } function remove(input = {}) { - let tasks = getTasks(); - input.remove.split(' ').forEach(i => { - if (!tasks[i - 1]) throw new Error('Index not found.'); - tasks[i - 1] = null - }); - writeFile(tasks.filter(t => t != null)); + let tasks = getTasks(); + input.remove.split(" ").forEach((i) => { + if (!tasks[i - 1]) throw new Error("Index not found."); + tasks[i - 1] = null; + }); + writeFile(tasks.filter((t) => t != null)); } function mod(input = {}) { - let tasks = getTasks(); + let tasks = getTasks(); - if (isNaN(Number(input.mod)) || !tasks[Number(input.mod) - 1]) - throw new Error('Index not found.'); + if (isNaN(Number(input.mod)) || !tasks[Number(input.mod) - 1]) + throw new Error("Index not found."); - let task = tasks[Number(input.mod) - 1] - if (input.title) task.title = input.title; - if (input.date) task.date = (new Date()).fromString(input.date); - if (input.desc) task.desc = input.desc; - tasks.sort((a, b) => a.date.compare(b.date)); - writeFile(tasks); + let task = tasks[Number(input.mod) - 1]; + if (input.title) task.title = input.title; + if (input.date) task.date = new Date().fromString(input.date); + if (input.desc) task.desc = input.desc; + tasks.sort((a, b) => a.date.compare(b.date)); + writeFile(tasks); } function printTasks(input = {}) { - let width = input.terminal_width || TERMINAL_WIDTH - let sepLine = '', sepSpace = ''; - for (let i = 0; i < width; i++) { - sepLine += '─'; - sepSpace += ' '; - } - let tasks = getTasks(); - - print('') - print(` ╭${sepLine.substring(3)}╮`) - print(` │ Deadline Task${sepSpace.substring(27)}│`); - print(` ├${sepLine.substring(3)}┤`); - for (let i = 0; i < tasks.length; ++i) { - let title = tasks[i].title; - let date = tasks[i].date.toString(); - let w = width - 24; - - print(` │ ${date} ${i + 1}.${i < 9 ? ' ' : ''} ${title.substring(0, w)}${sepSpace.substring(title.length + 24)} │`); - - // line break if title exceeds width - title = title.substring(w) - for (let i = 0; i < Math.floor(title.length / (w)) + 1; ++i) { - if (title[i * (w)] === ' ') //dont start line with space - title = title.substring(0, i * (w) - 1) + title.substring(i * (w)) - - let line = title.substring(i * (w), (i + 1) * (w)); - let spaceBefore = sepSpace.substring(0, width - w - 6); - if (line !== '') - print(` │ ${spaceBefore} ${line}${sepSpace.substring(spaceBefore.length + line.length + 6)} │`); - } - } - print(` ╰${sepLine.substring(3)}╯`) + let width = input.terminal_width || TERMINAL_WIDTH; + let sepLine = "", + sepSpace = ""; + for (let i = 0; i < width; i++) { + sepLine += "─"; + sepSpace += " "; + } + let tasks = getTasks(); + + print(""); + print(` ╭${sepLine.substring(3)}╮`); + print(` │ Deadline Task${sepSpace.substring(27)}│`); + print(` ├${sepLine.substring(3)}┤`); + for (let i = 0; i < tasks.length; ++i) { + let title = tasks[i].title; + let date = tasks[i].date.toString(); + let w = width - 24; + + print( + ` │ ${date} ${i + 1}.${i < 9 ? " " : ""} ${title.substring( + 0, + w, + )}${sepSpace.substring(title.length + 24)} │`, + ); + + // line break if title exceeds width + title = title.substring(w); + for (let i = 0; i < Math.floor(title.length / w) + 1; ++i) { + if (title[i * w] === " ") + //dont start line with space + title = title.substring(0, i * w - 1) + title.substring(i * w); + + let line = title.substring(i * w, (i + 1) * w); + let spaceBefore = sepSpace.substring(0, width - w - 6); + if (line !== "") + print( + ` │ ${spaceBefore} ${line}${sepSpace.substring( + spaceBefore.length + line.length + 6, + )} │`, + ); + } + } + print(` ╰${sepLine.substring(3)}╯`); } function eww() { - let out = [], id = 1; - let tasks = getTasks(); - tasks.forEach(t => t.id = id++); - tasks.filter(t => t.date.month || t.date.day || t.date.hour || t.date.asap) - .forEach(t => out.push({ - asap: t.date.asap || t.date.isLate(), - date: t.date.toString(), - title: t.title, - id: t.id - })) - - print(JSON.stringify(out, null, 3)); + let out = [], + id = 1; + let tasks = getTasks(); + tasks.forEach((t) => (t.id = id++)); + tasks + .filter((t) => t.date.month || t.date.day || t.date.hour || t.date.asap) + .forEach((t) => + out.push({ + asap: t.date.asap || t.date.isLate(), + date: t.date.toString(), + title: t.title, + id: t.id, + }), + ); + + print(JSON.stringify(out, null, 3)); } function getDesc(input = {}) { - let tasks = getTasks(); - if (!tasks[input.get_desc - 1]) throw new Error('Index not found.'); - - let width = input.terminal_width || TERMINAL_WIDTH - let sepLine = '', sepSpace = ''; - for (let i = 0; i < width; i++) { - sepLine += '─'; - sepSpace += ' '; - } - - let title = tasks[input.get_desc - 1].title - let desc = tasks[input.get_desc - 1].desc || "No description for this task." - print('') - print(` ╭${sepLine.substring(3)}╮`) - print(` │ ${title}${sepSpace.substring(title.length + 4)}│`); - print(` ├${sepLine.substring(3)}┤`); - - let w = width - 5; - for (let i = 0; i < Math.floor(desc.length / (w)) + 1; ++i) { - if (desc[i * (w)] === ' ') //dont start line with space - desc = desc.substring(0, i * (w) - 1) + desc.substring(i * (w)) - - let line = desc.substring(i * (w), (i + 1) * (w)); - print(` │ ${line}${sepSpace.substring(line.length + 4)}│`); - } - print(` ╰${sepLine.substring(3)}╯`) + let tasks = getTasks(); + if (!tasks[input.get_desc - 1]) throw new Error("Index not found."); + + let width = input.terminal_width || TERMINAL_WIDTH; + let sepLine = "", + sepSpace = ""; + for (let i = 0; i < width; i++) { + sepLine += "─"; + sepSpace += " "; + } + + let title = tasks[input.get_desc - 1].title; + let desc = + tasks[input.get_desc - 1].desc || "No description for this task."; + print(""); + print(` ╭${sepLine.substring(3)}╮`); + print(` │ ${title}${sepSpace.substring(title.length + 4)}│`); + print(` ├${sepLine.substring(3)}┤`); + + let w = width - 5; + for (let i = 0; i < Math.floor(desc.length / w) + 1; ++i) { + if (desc[i * w] === " ") + //dont start line with space + desc = desc.substring(0, i * w - 1) + desc.substring(i * w); + + let line = desc.substring(i * w, (i + 1) * w); + print(` │ ${line}${sepSpace.substring(line.length + 4)}│`); + } + print(` ╰${sepLine.substring(3)}╯`); } function main() { - if (!ARGV[0]) return printTasks(); - - let input = {}; - - for (let i = 0; i < ARGV.length; ++i) { - - let arg = []; let cmd = ARGV[i]; - for (let j = i + 1; j < ARGV.length && ARGV[j][0] !== '-'; ++j) - arg.push(ARGV[j]); - - switch (cmd) { - case '--eww': input.eww = true; break; - case '-m': input.mod = arg.join(' '); break; - case '--mod': input.mod = arg.join(' '); break; - case '-t': input.title = arg.join(' '); break; - case '--title': input.title = arg.join(' '); break; - case '-a': input.title = arg.join(' '); break; - case '--add': input.title = arg.join(' '); break; - case '-D': input.desc = arg.join(' '); break; - case '--description': input.desc = arg.join(' '); break; - case '--desc': input.desc = arg.join(' '); break; - case '-d': input.date = arg.join(' '); break; - case '--date': input.date = arg.join(' '); break; - case '--due': input.date = arg.join(' '); break; - case '-r': input.remove = arg.join(' '); break; - case '--remove': input.remove = arg.join(' '); break; - case '--rem': input.remove = arg.join(' '); break; - case '-w': input.terminal_width = arg.join(' '); break; - case '--width': input.terminal_width = arg.join(' '); break; - case '-w': input.terminal_width = arg.join(' '); break; - case '--width': input.terminal_width = arg.join(' '); break; - case '-g': input.get_desc = arg.join(' '); break; - case '--get-desc': input.get_desc = arg.join(' '); break; - default: input.title = cmd + ' ' + arg.join(' '); break; - } - i += arg.length; - } - - if (input.remove) remove(input); - else if (input.mod) mod(input); - else if (input.eww) eww(); - else if (input.get_desc) getDesc(input); - else if (input.title) add(input); - - if (!input.eww && !input.get_desc) printTasks(input); + if (!ARGV[0]) return printTasks(); + + let input = {}; + + for (let i = 0; i < ARGV.length; ++i) { + let arg = []; + let cmd = ARGV[i]; + for (let j = i + 1; j < ARGV.length && ARGV[j][0] !== "-"; ++j) + arg.push(ARGV[j]); + + switch (cmd) { + case "--eww": + input.eww = true; + break; + case "-m": + input.mod = arg.join(" "); + break; + case "--mod": + input.mod = arg.join(" "); + break; + case "-t": + input.title = arg.join(" "); + break; + case "--title": + input.title = arg.join(" "); + break; + case "-a": + input.title = arg.join(" "); + break; + case "--add": + input.title = arg.join(" "); + break; + case "-D": + input.desc = arg.join(" "); + break; + case "--description": + input.desc = arg.join(" "); + break; + case "--desc": + input.desc = arg.join(" "); + break; + case "-d": + input.date = arg.join(" "); + break; + case "--date": + input.date = arg.join(" "); + break; + case "--due": + input.date = arg.join(" "); + break; + case "-r": + input.remove = arg.join(" "); + break; + case "--remove": + input.remove = arg.join(" "); + break; + case "--rem": + input.remove = arg.join(" "); + break; + case "-w": + input.terminal_width = arg.join(" "); + break; + case "--width": + input.terminal_width = arg.join(" "); + break; + case "-w": + input.terminal_width = arg.join(" "); + break; + case "--width": + input.terminal_width = arg.join(" "); + break; + case "-g": + input.get_desc = arg.join(" "); + break; + case "--get-desc": + input.get_desc = arg.join(" "); + break; + default: + input.title = cmd + " " + arg.join(" "); + break; + } + i += arg.length; + } + + if (input.remove) remove(input); + else if (input.mod) mod(input); + else if (input.eww) eww(); + else if (input.get_desc) getDesc(input); + else if (input.title) add(input); + + if (!input.eww && !input.get_desc) printTasks(input); } -main() +main(); diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scripts/volume b/home/isabel/programs/gui/confs/bars/eww/config/scripts/volume index e5e3af273..4aeae8952 100755 --- a/home/isabel/programs/gui/confs/bars/eww/config/scripts/volume +++ b/home/isabel/programs/gui/confs/bars/eww/config/scripts/volume @@ -3,89 +3,89 @@ VOLUME=$(pamixer --get-volume) MUTED=$(pamixer --get-mute) function icon { - if [[ $MUTED == false ]]; then - if [[ $VOLUME -ge 66 ]]; then - echo '󰕾' - elif [[ $VOLUME -ge 33 ]]; then - echo '󰖀' - elif [[ $VOLUME -ge 1 ]]; then - echo '󰕿' - else - echo '󰝟' - fi - else - echo '󰝟' - fi + if [[ $MUTED == false ]]; then + if [[ $VOLUME -ge 66 ]]; then + echo '󰕾' + elif [[ $VOLUME -ge 33 ]]; then + echo '󰖀' + elif [[ $VOLUME -ge 1 ]]; then + echo '󰕿' + else + echo '󰝟' + fi + else + echo '󰝟' + fi } function level { - if [[ $MUTED == true ]]; then - echo 0 - else - echo $VOLUME - fi + if [[ $MUTED == true ]]; then + echo 0 + else + echo $VOLUME + fi } function lower { - pamixer -d 5 - update + pamixer -d 5 + update } function raise { - pamixer -i 5 - update + pamixer -i 5 + update } function mute { - pamixer --toggle-mute + pamixer --toggle-mute } function update { - eww update volume="$(get)" - ~/.config/eww/scripts/osd $(icon) $(level) + eww update volume="$(get)" + ~/.config/eww/scripts/osd $(icon) $(level) } function type_icon { - echo "󰋋" - #else - # echo "󰓃" - #fi + echo "󰋋" + #else + # echo "󰓃" + #fi } function mic_mute_state { - STATE=$(pamixer --default-source --get-mute) - if [[ $STATE == false ]]; then - echo 'off' - else echo 'on'; fi + STATE=$(pamixer --default-source --get-mute) + if [[ $STATE == false ]]; then + echo 'off' + else echo 'on'; fi } function mic_mute_icon { - STATE=$(mic_mute_state) - if [[ $STATE == 'off' ]]; then - echo '󰍬' - else echo '󰍭'; fi + STATE=$(mic_mute_state) + if [[ $STATE == 'off' ]]; then + echo '󰍬' + else echo '󰍭'; fi } function mute_mic { - pamixer --default-source -t - eww update volume="$(get)" + pamixer --default-source -t + eww update volume="$(get)" } function set { - pamixer --set-volume $1 - eww update volume="$(get)" + pamixer --set-volume $1 + eww update volume="$(get)" } function get { - echo "{ - \"level\": \"$(level)\", - \"icon\": \"$(icon)\", - \"type_icon\": \"$(type_icon)\", - \"mute\": { - \"state\": \"$(mic_mute_state)\", - \"icon\": \"$(mic_mute_icon)\" -} -}" + echo "{ + \"level\": \"$(level)\", + \"icon\": \"$(icon)\", + \"type_icon\": \"$(type_icon)\", + \"mute\": { + \"state\": \"$(mic_mute_state)\", + \"icon\": \"$(mic_mute_icon)\" + } + }" } if [[ $1 == 'mute_mic' ]]; then mute_mic; fi diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/colors.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/colors.scss index 9c68e6070..2d24d3a05 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/colors.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/colors.scss @@ -1,4 +1,4 @@ -$theme: 'dark'; +$theme: "dark"; $red: #f38ba8; $green: #f38ba8; @@ -12,4 +12,4 @@ $bg_color: #1e1e2e; $fg_color: #cdd6f4; $hover_fg: #cdd6f4; $accent_fg: #11111b; -$accent: #75c7ec; \ No newline at end of file +$accent: #75c7ec; diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/colors_dark.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/colors_dark.scss index 9c68e6070..2d24d3a05 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/colors_dark.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/colors_dark.scss @@ -1,4 +1,4 @@ -$theme: 'dark'; +$theme: "dark"; $red: #f38ba8; $green: #f38ba8; @@ -12,4 +12,4 @@ $bg_color: #1e1e2e; $fg_color: #cdd6f4; $hover_fg: #cdd6f4; $accent_fg: #11111b; -$accent: #75c7ec; \ No newline at end of file +$accent: #75c7ec; diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/colors_light.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/colors_light.scss index 6e79d13dc..0d8698e71 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/colors_light.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/colors_light.scss @@ -1,4 +1,4 @@ -$theme: 'light'; +$theme: "light"; $red: #d20f39; $green: #40a02b; @@ -12,4 +12,4 @@ $bg_color: #eff1f5; $fg_color: #4c4f69; $hover_fg: #4c4f69; $accent_fg: #dce0e8; -$accent: #209fb5; \ No newline at end of file +$accent: #209fb5; diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/common.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/common.scss index 2756b95ff..a8ed1e49b 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/common.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/common.scss @@ -1,149 +1,162 @@ @mixin widget($radii: $widget_radius) { - border-radius: $radii; - color: $fg_color; - background-color: $widget_bg; - box-shadow: inset 0 0 0 $border_width $border_color; + border-radius: $radii; + color: $fg_color; + background-color: $widget_bg; + box-shadow: inset 0 0 0 $border_width $border_color; } -@mixin button($flat: false, $interactive: true, $radii: $radii, $focusable: false) { - border-radius: $radii; - color: $fg_color; - - @if $flat { - background-color: transparent; - background-image: none; - box-shadow: none; - } - - @else { - background-color: $button_bg; - box-shadow: inset 0 0 0 $border_width $border_color; - } - - @if $interactive { - @if $focusable { - &:focus { - box-shadow: inset 0 0 0 $border_width $accent; - background-color: $hover; - color: $hover_fg; - } - } - - &:hover { - box-shadow: inset 0 0 0 $border_width $border_color; - background-color: $hover; - color: $hover_fg; - } - - &:active { - box-shadow: inset 0 0 0 $border_width $border_color; - background-color: $accent; - color: $accent_fg; - } - } +@mixin button( + $flat: false, + $interactive: true, + $radii: $radii, + $focusable: false +) { + border-radius: $radii; + color: $fg_color; + + @if $flat { + background-color: transparent; + background-image: none; + box-shadow: none; + } @else { + background-color: $button_bg; + box-shadow: inset 0 0 0 $border_width $border_color; + } + + @if $interactive { + @if $focusable { + &:focus { + box-shadow: inset 0 0 0 $border_width $accent; + background-color: $hover; + color: $hover_fg; + } + } + + &:hover { + box-shadow: inset 0 0 0 $border_width $border_color; + background-color: $hover; + color: $hover_fg; + } + + &:active { + box-shadow: inset 0 0 0 $border_width $border_color; + background-color: $accent; + color: $accent_fg; + } + } } @mixin floating_widget($shadow: true, $padding: $popover_padding) { - @if $shadow { - box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.6), - inset 0 0 0 $border_width $popover_border_color; - } - - @else { - box-shadow: inset 0 0 0 $border_width $popover_border_color; - } - - border-radius: $popover_radius; - margin: $wm_gaps; - background-color: $bg_color; - color: $fg_color; - padding: $padding; + @if $shadow { + box-shadow: + 0 0 5px 0 rgba(0, 0, 0, 0.6), + inset 0 0 0 $border_width $popover_border_color; + } @else { + box-shadow: inset 0 0 0 $border_width $popover_border_color; + } + + border-radius: $popover_radius; + margin: $wm_gaps; + background-color: $bg_color; + color: $fg_color; + padding: $padding; } -@mixin slider($width: .4em, $color: $accent, $slider: true, $focusable: false) { - trough { - border-radius: $button_radius; - border: $border; - background-color: $button_bg; - min-height: $width; - min-width: $width; - - highlight, - progress { - border-radius: $popover_radius*0.8; - background-color: $color; - min-height: $width; - min-width: $width; - } - - slider { - @if $slider { - background-color: $fg_color; - border-radius: $button_radius; - border: $border; - min-height: $width; - min-width: $width; - } - } - } - - &:hover trough { - background-color: $hover; - } - - @if $focusable { - trough:focus { - background-color: $hover; - box-shadow: inset 0 0 0 $border_width $accent; - - highlight, - progress { - background-color: transparentize($color, 0.3); - } - } - } +@mixin slider( + $width: 0.4em, + $color: $accent, + $slider: true, + $focusable: false +) { + trough { + border-radius: $button_radius; + border: $border; + background-color: $button_bg; + min-height: $width; + min-width: $width; + + highlight, + progress { + border-radius: $popover_radius * 0.8; + background-color: $color; + min-height: $width; + min-width: $width; + } + + slider { + @if $slider { + background-color: $fg_color; + border-radius: $button_radius; + border: $border; + min-height: $width; + min-width: $width; + } + } + } + + &:hover trough { + background-color: $hover; + } + + @if $focusable { + trough:focus { + background-color: $hover; + box-shadow: inset 0 0 0 $border_width $accent; + + highlight, + progress { + background-color: transparentize($color, 0.3); + } + } + } } @mixin darkened($radii: 0) { - border-radius: $radii*0.99; + border-radius: $radii * 0.99; - @if $theme =='dark' { - box-shadow: inset 0 0 3em 1em transparentize($bg_color, 0.1); - } + @if $theme == "dark" { + box-shadow: inset 0 0 3em 1em transparentize($bg_color, 0.1); + } - @if $theme =='light' { - background-color: transparentize($bg_color, 0.5); - } + @if $theme == "light" { + background-color: transparentize($bg_color, 0.5); + } } @mixin tooltip { - >*>* { - background-color: $bg_color; - border-radius: $button_radius; - border: $border_width solid $popover_border_color; - color: $fg_color; - padding: 8px; - margin: 4px; - box-shadow: 0 0 3px 0 rgba(0, 0, 0, 0.4); - } + > * > * { + background-color: $bg_color; + border-radius: $button_radius; + border: $border_width solid $popover_border_color; + color: $fg_color; + padding: 8px; + margin: 4px; + box-shadow: 0 0 3px 0 rgba(0, 0, 0, 0.4); + } } -@mixin scrollbar{ - scrollbar.vertical{ - slider{ - background: $widget_bg; - border-radius: $radii; - min-width: .6em; - min-height: 2em; - } - } - overshoot{ - border-radius: $radii; - &.top{ - background: linear-gradient(transparentize($bg_color, 0.6), transparent); - } - &.bottom{ - background: linear-gradient(transparent,transparentize($bg_color, 0.6)); - } - } +@mixin scrollbar { + scrollbar.vertical { + slider { + background: $widget_bg; + border-radius: $radii; + min-width: 0.6em; + min-height: 2em; + } + } + overshoot { + border-radius: $radii; + &.top { + background: linear-gradient( + transparentize($bg_color, 0.6), + transparent + ); + } + &.bottom { + background: linear-gradient( + transparent, + transparentize($bg_color, 0.6) + ); + } + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/variables.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/variables.scss index 31b07a4fa..c1fdadb54 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/variables.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/variables.scss @@ -1,7 +1,7 @@ -$assets: './assets/'; -$pic_dir = '/home/isabel/media/pictures/'; -$wallpaper: $pic_dir + 'wallpapers/tempest.png'; -$avatar: $pic_dir + 'pfps/avatar'; +$assets: "./assets/"; +$pic_dir: "/home/isabel/media/pictures/"; +$wallpaper: $pic_dir + "wallpapers/tempest.png"; +$avatar: $pic_dir + "pfps/avatar"; $hover: transparentize($fg_color, 0.84); @@ -31,10 +31,10 @@ $popover_border_color: rgba(255, 255, 255, 0.02); $popover_padding: 14px; * { - all: unset; - font-size: 14px; - font-family: 'Ubuntu Nerd Font'; - transition: 200ms; + all: unset; + font-size: 14px; + font-family: "Ubuntu Nerd Font"; + transition: 200ms; } -$mono_font: 'mononoki Nerd Font'; +$mono_font: "mononoki Nerd Font"; diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/bar_widget.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/bar_widget.scss index 5b85d5e95..691410b56 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/bar_widget.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/bar_widget.scss @@ -1,61 +1,102 @@ @mixin system-indicators($orientation) { - @include button($flat: false, $radii: $panel_button_radius); - .reveal{ - @if $orientation == 'v' { padding-top: .5em; } - @if $orientation == 'h' { padding-left: .2em;} - } - .slider{ - @include slider($width: 1em, $slider: false); - @if $orientation == 'v' { > * { min-height: 80px; } } - @if $orientation == 'h' { > * { min-width: 90px; } } - } - .icon{ - margin: .1em 0; - &.battery{ - &.low{ color: $destructive; } - &.charging{ color: $succes; } - &.charged{ color: $succes; } - } - &.notifications.active{ - color: $yellow; - } - &.network{ - &.none, &.low{ color: $red; } - &.medium{} - &.high{ color: $blue; } - } - &.bluetooth, &.bt_speaker{ - color: $blue; - } - } + @include button($flat: false, $radii: $panel_button_radius); + .reveal { + @if $orientation == "v" { + padding-top: 0.5em; + } + @if $orientation == "h" { + padding-left: 0.2em; + } + } + .slider { + @include slider($width: 1em, $slider: false); + @if $orientation == "v" { + > * { + min-height: 80px; + } + } + @if $orientation == "h" { + > * { + min-width: 90px; + } + } + } + .icon { + margin: 0.1em 0; + &.battery { + &.low { + color: $destructive; + } + &.charging { + color: $succes; + } + &.charged { + color: $succes; + } + } + &.notifications.active { + color: $yellow; + } + &.network { + &.none, + &.low { + color: $red; + } + &.medium { + } + &.high { + color: $blue; + } + } + &.bluetooth, + &.bt_speaker { + color: $blue; + } + } } @mixin panel_media() { - .player{ - @include button($flat: true, $radii: $panel_button_radius); - } - .controls{ - @include button($radii: $panel_button_radius); - button { - &.prev, &.next, &.play-pause{ - color: transparentize($fg_color, 0.3); - &:hover{ color: transparentize($fg_color, 0.15) } - &:active{ color: $fg_color } - } - } - } - .icon{ - &.spotify{ color: $green; } - &.firefox{ color: $orange; } - &.mpv{ color: $magenta; } - } + .player { + @include button($flat: true, $radii: $panel_button_radius); + } + .controls { + @include button($radii: $panel_button_radius); + button { + &.prev, + &.next, + &.play-pause { + color: transparentize($fg_color, 0.3); + &:hover { + color: transparentize($fg_color, 0.15); + } + &:active { + color: $fg_color; + } + } + } + } + .icon { + &.spotify { + color: $green; + } + &.firefox { + color: $orange; + } + &.mpv { + color: $magenta; + } + } } @mixin workspaces() { - @include button($flat: false, $radii: $panel_button_radius); - .workspace-btn{ - color: $fg_color; - .focus{ color: $accent; } - &:hover{ color: darken($fg_color, 0.3); } - } + @include button($flat: false, $radii: $panel_button_radius); + .workspace-btn { + color: $fg_color; + .focus { + color: $accent; + } + &:hover { + color: darken($fg_color, 0.3); + } + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/calendar.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/calendar.scss index 992cd8c53..6f79c2095 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/calendar.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/calendar.scss @@ -1,31 +1,31 @@ @mixin calendar() { - calendar { - &.button { - @include button($flat: true); - margin: 1em; - } + calendar { + &.button { + @include button($flat: true); + margin: 1em; + } - &:selected { - border: 2px solid $accent; - border-radius: $button_radius; - } + &:selected { + border: 2px solid $accent; + border-radius: $button_radius; + } - &.header { - background-color: transparent; - border: none; - color: transparentize($fg_color, 0.5); - } + &.header { + background-color: transparent; + border: none; + color: transparentize($fg_color, 0.5); + } - &.highlight { - background-color: transparent; - color: transparentize($accent, 0.5); - } + &.highlight { + background-color: transparent; + color: transparentize($accent, 0.5); + } - &:indeterminate { - color: transparentize($fg_color, 0.9); - } + &:indeterminate { + color: transparentize($fg_color, 0.9); + } - font-size: 1.2em; - padding: .2em; - } -} \ No newline at end of file + font-size: 1.2em; + padding: 0.2em; + } +} diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/events.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/events.scss index 0cdac1fca..7590101bc 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/events.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/events.scss @@ -1,24 +1,49 @@ -@mixin events{ - label{ font-size: 1.1em; } - .title-box{ - padding: $spacing; - border-bottom: 1px solid transparentize($fg_color, 0.9); - label{ font-size: 1.1em; } - } - .events-box{ padding: $spacing; } - .event{ - .deadline{ - color: transparentize($fg_color, 0.5); - font-family: $mono_font; - } - &.done{ - label{ text-decoration: line-through }; - .title{ color: $green } - .deadline{ color: transparentize($green ,0.5) } - } - &.upcoming{ - .title{ color: $red } - .deadline{ color: transparentize($red ,0.5) } - } - } +@mixin events { + label { + font-size: 1.1em; + } + + .title-box { + padding: $spacing; + border-bottom: 1px solid transparentize($fg_color, 0.9); + + label { + font-size: 1.1em; + } + } + + .events-box { + padding: $spacing; + } + + .event { + .deadline { + color: transparentize($fg_color, 0.5); + font-family: $mono_font; + } + + &.done { + label { + text-decoration: line-through; + } + + .title { + color: $green; + } + + .deadline { + color: transparentize($green, 0.5); + } + } + + &.upcoming { + .title { + color: $red; + } + + .deadline { + color: transparentize($red, 0.5); + } + } + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/media.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/media.scss index 3c6a0152e..c640a1434 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/media.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/media.scss @@ -1,94 +1,150 @@ -@mixin media($style: 'widget', $height: 12em) { - @if $style == 'widget' { @include widget; } - @if $style == 'popover' { @include floating_widget; } - border-radius: $radii; - margin: $spacing; - min-height: $height; - padding: 0; - text-shadow: $text_shadow; - .cover{ - @if $style == 'widget' { @include widget; } - @if $style == 'popover' { border-radius: $radii; } - background-size: cover; - background-position: center; - .darkened{ - @if $style == 'widget' { @include darkened($radii: $button_radius); } - @if $style == 'popover' { @include darkened($radii: $radii); } - } - .slider{ - @include slider($width: .4em, $slider: false, $color: transparentize($fg_color, 0.3)); - scale > contents{ - trough{ - border-radius: 0; - border: 0; - highlight{ - border-radius: 0; - } - } - } - } - .box{ margin: $spacing; } - .artist{ font-size: 1.2em; } - .title, .position{ color: transparentize($fg_color, 0.2);} - .icon.player{ - font-size: 1.4em; - margin-left: .6em; - } - .controls{ - margin: $spacing; - button{ - label{ font-size: 2em; } - &.loop, &.shuffle{ - label{ font-size: 1.2em; } - } - color: transparentize($fg_color, 0.3); - &:hover{ color: $fg_color; } - &.active{ color: $accent; } - &.inactive{ - color: transparentize($fg_color, 0.7); - text-shadow: none; - } - &.loop{ - &.Playlist{ color: transparentize($accent, 0.2); } - &.Track{ color: $accent; } - } - } - } - } - .sidebar{ - .slider{ @include slider($width: .6em, $slider: false); } - margin: $spacing*2; - } +@mixin media($style: "widget", $height: 12em) { + @if $style == "widget" { + @include widget; + } + @if $style == "popover" { + @include floating_widget; + } + border-radius: $radii; + margin: $spacing; + min-height: $height; + padding: 0; + text-shadow: $text_shadow; + .cover { + @if $style == "widget" { + @include widget; + } + @if $style == "popover" { + border-radius: $radii; + } + background-size: cover; + background-position: center; + .darkened { + @if $style == "widget" { + @include darkened($radii: $button_radius); + } + @if $style == "popover" { + @include darkened($radii: $radii); + } + } + .slider { + @include slider( + $width: 0.4em, + $slider: false, + $color: transparentize($fg_color, 0.3) + ); + scale > contents { + trough { + border-radius: 0; + border: 0; + highlight { + border-radius: 0; + } + } + } + } + .box { + margin: $spacing; + } + .artist { + font-size: 1.2em; + } + .title, + .position { + color: transparentize($fg_color, 0.2); + } + .icon.player { + font-size: 1.4em; + margin-left: 0.6em; + } + .controls { + margin: $spacing; + button { + label { + font-size: 2em; + } + &.loop, + &.shuffle { + label { + font-size: 1.2em; + } + } + color: transparentize($fg_color, 0.3); + &:hover { + color: $fg_color; + } + &.active { + color: $accent; + } + &.inactive { + color: transparentize($fg_color, 0.7); + text-shadow: none; + } + &.loop { + &.Playlist { + color: transparentize($accent, 0.2); + } + &.Track { + color: $accent; + } + } + } + } + } + .sidebar { + .slider { + @include slider($width: 0.6em, $slider: false); + } + margin: $spacing * 2; + } - &.spotify{ - .icon.player{ color: $green; } - .sidebar .slider{ - @include slider($width: .6em, $slider: false, $color: $green); - } - .controls button{ - &.active{ color: $green; } - &.loop{ - &.Playlist{ color: transparentize($green, 0.2); } - &.Track{ color: $green; } - } - } - } + &.spotify { + .icon.player { + color: $green; + } + .sidebar .slider { + @include slider($width: 0.6em, $slider: false, $color: $green); + } + .controls button { + &.active { + color: $green; + } + &.loop { + &.Playlist { + color: transparentize($green, 0.2); + } + &.Track { + color: $green; + } + } + } + } - &.firefox{ - .icon.player{ color: $orange; } - } + &.firefox { + .icon.player { + color: $orange; + } + } - &.mpv{ - .icon.player{ color: $magenta; } - .sidebar .slider{ - @include slider($width: .6em, $slider: false, $color: $magenta); - } - .controls button{ - &.active{ color: $magenta; } - &.loop{ - &.Playlist{ color: transparentize($magenta, 0.2); } - &.Track{ color: $magenta; } - } - } - } + &.mpv { + .icon.player { + color: $magenta; + } + .sidebar .slider { + @include slider($width: 0.6em, $slider: false, $color: $magenta); + } + .controls button { + &.active { + color: $magenta; + } + &.loop { + &.Playlist { + color: transparentize($magenta, 0.2); + } + &.Track { + color: $magenta; + } + } + } + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/notification.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/notification.scss index 80313253e..5d779bb7c 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/notification.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/notification.scss @@ -1,56 +1,56 @@ @mixin notification() { - .notification-content{ - padding: $popover_padding; - .title{ - font-size: 1.2em; - font-weight: 600; - margin-bottom: $popover_padding/2; - } - .image{ - min-width: 80px; - min-height: 80px; - background-size: cover; - margin-right: $popover_padding; - border-radius: $button_radius; - } - .action-button{ - @include button; - font-size: 1.1em; - font-weight: 500; - padding: .5em; - margin-top: $popover_padding; - &:first-child{ - margin-right: $popover_padding/2; - } - &:last-child{ - margin-left: $popover_padding/2; - } - &:first-child:last-child{ - margin-left: 0; - margin-right: 0; - } - } - .close-button{ - min-width: 1.4em; - min-height: 1.4em; - } - .time{ - color: transparentize($fg_color, 0.4); - margin-right: .4em; - } - } - &:hover{ - .notification-content{ - .close-button{ - @include button; - background-color: transparentize($red, 0.5); - &:hover{ - background-color: transparentize($red, 0.3); - } - &:active{ - background-color: transparentize($red, 0.1); - } - } - } - } + .notification-content { + padding: $popover_padding; + .title { + font-size: 1.2em; + font-weight: 600; + margin-bottom: $popover_padding/2; + } + .image { + min-width: 80px; + min-height: 80px; + background-size: cover; + margin-right: $popover_padding; + border-radius: $button_radius; + } + .action-button { + @include button; + font-size: 1.1em; + font-weight: 500; + padding: 0.5em; + margin-top: $popover_padding; + &:first-child { + margin-right: $popover_padding/2; + } + &:last-child { + margin-left: $popover_padding/2; + } + &:first-child:last-child { + margin-left: 0; + margin-right: 0; + } + } + .close-button { + min-width: 1.4em; + min-height: 1.4em; + } + .time { + color: transparentize($fg_color, 0.4); + margin-right: 0.4em; + } + } + &:hover { + .notification-content { + .close-button { + @include button; + background-color: transparentize($red, 0.5); + &:hover { + background-color: transparentize($red, 0.3); + } + &:active { + background-color: transparentize($red, 0.1); + } + } + } + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/sys_sliders.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/sys_sliders.scss index 2a9ba7984..d9f572971 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/sys_sliders.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/sys_sliders.scss @@ -1,16 +1,22 @@ -@mixin sys-sliders () { - .slider{ @include slider($width: .8em, $slider: false); } - .percent{ - margin: $spacing; - min-width: 2.6em; - } - .icon{ - margin: $spacing; - &:first-child{ font-size: 1.4em; } - } - button{ - @include button($flat: true); - margin-right: $spacing; - .icon{ margin: 0; } - } +@mixin sys-sliders() { + .slider { + @include slider($width: 0.8em, $slider: false); + } + .percent { + margin: $spacing; + min-width: 2.6em; + } + .icon { + margin: $spacing; + &:first-child { + font-size: 1.4em; + } + } + button { + @include button($flat: true); + margin-right: $spacing; + .icon { + margin: 0; + } + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/toggle_button.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/toggle_button.scss index ad1f3480d..e211e15f8 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/toggle_button.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/toggle_button.scss @@ -1,34 +1,50 @@ -@mixin toggle_button($toggle_radius: $radii*2.4) { - @include button($radii: $toggle_radius); - &.small{ @include button($radii: $toggle_radius*1.1); } - margin: $spacing; - .separator{ - background-color: $fg_color; - min-width: 2px; - min-height: 1.4em; - } - .half{ - @include button($flat: true); - min-height: 3.4em; - &:first-child{ border-radius: $toggle_radius 0 0 $toggle_radius } - &:last-child{ border-radius: 0 $toggle_radius $toggle_radius 0 } - &:hover{ background-color: $hover } - } - &.active{ - * { color: $accent_fg; } - background-color: $accent; - .separator{ background-color: $accent_fg; } - &:hover{ - background-color: transparentize($accent, 0.15); - *{ color: $accent_fg} - } - &:focus{ - background-color: transparentize($accent, 0.4); - box-shadow: inset 0 0 0 $border_width*2 $accent; - } - } - .icon{ - font-size: 2em; - &.arrow{ font-size: 1.8em; } - } +@mixin toggle_button($toggle_radius: $radii * 2.4) { + @include button($radii: $toggle_radius); + &.small { + @include button($radii: $toggle_radius * 1.1); + } + margin: $spacing; + .separator { + background-color: $fg_color; + min-width: 2px; + min-height: 1.4em; + } + .half { + @include button($flat: true); + min-height: 3.4em; + &:first-child { + border-radius: $toggle_radius 0 0 $toggle_radius; + } + &:last-child { + border-radius: 0 $toggle_radius $toggle_radius 0; + } + &:hover { + background-color: $hover; + } + } + &.active { + * { + color: $accent_fg; + } + background-color: $accent; + .separator { + background-color: $accent_fg; + } + &:hover { + background-color: transparentize($accent, 0.15); + * { + color: $accent_fg; + } + } + &:focus { + background-color: transparentize($accent, 0.4); + box-shadow: inset 0 0 0 $border_width * 2 $accent; + } + } + .icon { + font-size: 2em; + &.arrow { + font-size: 1.8em; + } + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/user.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/user.scss index ec3e4a8cd..c3582bbbd 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/user.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/user.scss @@ -1,26 +1,26 @@ @mixin user($width: 10em, $height: 10em) { - padding: 0; - min-height: 10em; - min-width: 10em; - background-image: url($avatar); - background-size: cover; + padding: 0; + min-height: 10em; + min-width: 10em; + background-image: url($avatar); + background-size: cover; - .darkened { - @include darkened($radii: $button_radius); - padding: .3em; + .darkened { + @include darkened($radii: $button_radius); + padding: 0.3em; - label { - text-shadow: $text_shadow; + label { + text-shadow: $text_shadow; - &:first-child { - color: transparentize($fg_color, 0.1); - font-size: 1.3em; - } + &:first-child { + color: transparentize($fg_color, 0.1); + font-size: 1.3em; + } - &:last-child { - color: transparentize($fg_color, 0.3); - font-size: 1.1em; - } - } - } -} \ No newline at end of file + &:last-child { + color: transparentize($fg_color, 0.3); + font-size: 1.1em; + } + } + } +} diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/weather.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/weather.scss index 306946c37..97765577e 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/weather.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/widgets/weather.scss @@ -1,29 +1,50 @@ @mixin weather { - .info{ - .place{ - label{ font-size: 1.2em } - .icon{ - font-size: .9em; - margin-right: .2em; - color: transparentize($accent, 0); - } - } - .feels{ color: transparentize($fg_color, 0.3); } - .temp{ font-size: 1.2em; } - } - .icon{ - font-size: 2.6em; + .info { + .place { + label { + font-size: 1.2em; + } + .icon { + font-size: 0.9em; + margin-right: 0.2em; + color: transparentize($accent, 0); + } + } + .feels { + color: transparentize($fg_color, 0.3); + } + .temp { + font-size: 1.2em; + } + } + .icon { + font-size: 2.6em; - &.clear.d{ color: transparentize($yellow, 0.6); } - &.clear.n{ color: transparentize($blue, 0.6); } + &.clear.d { + color: transparentize($yellow, 0.6); + } + &.clear.n { + color: transparentize($blue, 0.6); + } - &.clouds.d{ color: transparentize($fg_color, 0.6); } - &.clouds.n{ color: transparentize($blue, 0.6); } - - &.rain{ color: transparentize($blue, 0.6); } - &.thunderstorm{ color: transparentize($yellow, 0.6); } - &.snow{ color: transparentize($fg_color, 0.6); } - &.mist{ color: transparentize($teal, 0.6); } - } + &.clouds.d { + color: transparentize($fg_color, 0.6); + } + &.clouds.n { + color: transparentize($blue, 0.6); + } + &.rain { + color: transparentize($blue, 0.6); + } + &.thunderstorm { + color: transparentize($yellow, 0.6); + } + &.snow { + color: transparentize($fg_color, 0.6); + } + &.mist { + color: transparentize($teal, 0.6); + } + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/app_laucher.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/app_laucher.scss index 79776f7f3..94eea77fe 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/app_laucher.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/app_laucher.scss @@ -1,53 +1,58 @@ -.app-launcher{ - @include floating_widget; - min-height: 530px; - min-width: 530px; - padding: 3em; +.app-launcher { + @include floating_widget; + min-height: 530px; + min-width: 530px; + padding: 3em; - .search{ - min-height: 1.4em; - padding: 2em; - border-radius: $radii; - background-image: url($wallpaper); - background-size: cover; - background-position: right bottom; - margin-bottom: 3em; - .icon, .input { - @include button; - background-color: transparentize($bg_color, 0.1); - box-shadow: 0 0 5px 0 rgba(0,0,0,0.4); - } - .icon { - min-width: 2.4em; - margin-right: $spacing - } - .input{ - padding: .6em .8em; - } - } + .search { + min-height: 1.4em; + padding: 2em; + border-radius: $radii; + background-image: url($wallpaper); + background-size: cover; + background-position: right bottom; + margin-bottom: 3em; + .icon, + .input { + @include button; + background-color: transparentize($bg_color, 0.1); + box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.4); + } + .icon { + min-width: 2.4em; + margin-right: $spacing; + } + .input { + padding: 0.6em 0.8em; + } + } - .separator{ - min-height: 1px; - background-color: transparentize($fg_color, 0.94); - margin: .2em; - } + .separator { + min-height: 1px; + background-color: transparentize($fg_color, 0.94); + margin: 0.2em; + } - .app{ - @include button($flat: true, $focusable: true); - .app-content{ - .name{ font-size: 1.1em } - .description{ color: transparentize($fg_color, 0.3) } - .appicon{ - background-size: cover; - min-width: 2.4em; - min-height: 2.4em; - margin-right: 1em; - } - padding: .6em; - } - } + .app { + @include button($flat: true, $focusable: true); + .app-content { + .name { + font-size: 1.1em; + } + .description { + color: transparentize($fg_color, 0.3); + } + .appicon { + background-size: cover; + min-width: 2.4em; + min-height: 2.4em; + margin-right: 1em; + } + padding: 0.6em; + } + } - .scroll { - @include scrollbar; - } + .scroll { + @include scrollbar; + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/datemenu.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/datemenu.scss index 23e76021e..404cba280 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/datemenu.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/datemenu.scss @@ -1,66 +1,70 @@ -.datemenu{ - @include floating_widget; +.datemenu { + @include floating_widget; - .widget{ - @include widget; - margin: $spacing; - padding: $spacing; - } + .widget { + @include widget; + margin: $spacing; + padding: $spacing; + } - .clock *{ - margin-top: $spacing; - text-shadow: $text_shadow; - font-size: 7em; - } + .clock * { + margin-top: $spacing; + text-shadow: $text_shadow; + font-size: 7em; + } - .uptime{ - margin-bottom: $spacing*2; - font-size: 1.1em; - text-shadow: $text_shadow; - color: transparentize($fg_color, 0.3) - } - - .calendar-bin{ - padding: 1em 2em .4em 2em; - @include calendar; - } + .uptime { + margin-bottom: $spacing * 2; + font-size: 1.1em; + text-shadow: $text_shadow; + color: transparentize($fg_color, 0.3); + } - .system{ - > * { - @include widget; - margin: $spacing; - padding: 5px; - min-width: 3.4em; - min-height: 3.4em; - } - circular-progress{ - background-color: $bg_color; - color: $accent; - &.battery{ - &.low{ color: $red } - } - .icon{ font-size: 1.3em; } - } - } + .calendar-bin { + padding: 1em 2em 0.4em 2em; + @include calendar; + } - .media{ - @include media($style: 'widget') - } + .system { + > * { + @include widget; + margin: $spacing; + padding: 5px; + min-width: 3.4em; + min-height: 3.4em; + } + circular-progress { + background-color: $bg_color; + color: $accent; + &.battery { + &.low { + color: $red; + } + } + .icon { + font-size: 1.3em; + } + } + } - .events.widget { - padding: 0; - .events{ - @include events; - } - } - - .weather{ - @include weather; - } + .media { + @include media($style: "widget"); + } - .wallpaper{ - min-height: 13em; - background-image: url($assets+'wallpaper.png'); - background-size: cover; - } + .events.widget { + padding: 0; + .events { + @include events; + } + } + + .weather { + @include weather; + } + + .wallpaper { + min-height: 13em; + background-image: url($assets + "wallpaper.png"); + background-size: cover; + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/desktop.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/desktop.scss index ae4769f97..4be309c22 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/desktop.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/desktop.scss @@ -1,48 +1,48 @@ .desktop { - background-image: url($wallpaper); - background-size: cover; - - .clock { - color: white; - text-shadow: 4px 4px 4px black; - - .time { - border: 3px solid $fg_color; - box-shadow: inset 0 0 0 3px $bg_color; - border-radius: $popover_radius; - padding: .5em 1.3em; - - .hour, - .minutes, - .separator { - font-size: 10em; - font-family: $mono_font; - } - } - - .date { - font-size: 2em; - } - } - - .system { - >* { - padding: 8px; - } - - circular-progress { - background-color: transparentize($bg_color, 0.5); - color: $fg_color; - - &.battery { - &.low { - color: $red - } - } - - .icon { - font-size: 3em; - } - } - } -} \ No newline at end of file + background-image: url($wallpaper); + background-size: cover; + + .clock { + color: white; + text-shadow: 4px 4px 4px black; + + .time { + border: 3px solid $fg_color; + box-shadow: inset 0 0 0 3px $bg_color; + border-radius: $popover_radius; + padding: 0.5em 1.3em; + + .hour, + .minutes, + .separator { + font-size: 10em; + font-family: $mono_font; + } + } + + .date { + font-size: 2em; + } + } + + .system { + > * { + padding: 8px; + } + + circular-progress { + background-color: transparentize($bg_color, 0.5); + color: $fg_color; + + &.battery { + &.low { + color: $red; + } + } + + .icon { + font-size: 3em; + } + } + } +} diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/dock.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/dock.scss index ff643ca4f..020e07aa0 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/dock.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/dock.scss @@ -1,55 +1,76 @@ $dock_icon_size: 6em; -.dock{ - .container{ - min-width: $dock_icon_size*11.5; - min-height: $dock_icon_size*1.3; - &.hovered{ - min-width: $dock_icon_size*11.7; - } - } +.dock { + .container { + min-width: $dock_icon_size * 11.5; + min-height: $dock_icon_size * 1.3; + &.hovered { + min-width: $dock_icon_size * 11.7; + } + } - .foot{ - @include floating_widget; - margin: 0 1.5em; - padding: 0; - border-radius: $popover_radius $popover_radius 0 0; - border-bottom: none; - min-height: 1.5em; //footer height - } + .foot { + @include floating_widget; + margin: 0 1.5em; + padding: 0; + border-radius: $popover_radius $popover_radius 0 0; + border-bottom: none; + min-height: 1.5em; //footer height + } - .laucher{ - .indicator{ - min-height: .4em; //indicator height - min-width: 2em; //indicator width - border-radius: $button_radius; - } - .icon{ - min-width: $dock_icon_size; - min-height: $dock_icon_size; - background-size: contain; - background-repeat: no-repeat; - } - &:hover{ - background-image: linear-gradient(transparent, transparentize($fg_color, 0.94)); - .icon{ - min-width: $dock_icon_size*1.2; - min-height: $dock_icon_size*1.2; - } - } - &:active{ - .indicator{ - background-color: $accent; - } - } - &.firefox .icon{ background-image: url($assets+'apps/firefox.png'); } - &.terminal .icon{ background-image: url($assets+'apps/terminal.png'); } - &.file-manager .icon{ background-image: url($assets+'apps/file-manager.png'); } - &.editor .icon{ background-image: url($assets+'apps/editor.png'); } - &.spotify .icon{ background-image: url($assets+'apps/spotify.png'); } - &.caprine .icon{ background-image: url($assets+'apps/caprine.png'); } - &.bitwig .icon{ background-image: url($assets+'apps/bitwig.png'); } - &.battle .icon{ background-image: url($assets+'apps/battle.png'); } - &.bottles .icon{ background-image: url($assets+'apps/bottles.png'); } - } + .laucher { + .indicator { + min-height: 0.4em; //indicator height + min-width: 2em; //indicator width + border-radius: $button_radius; + } + .icon { + min-width: $dock_icon_size; + min-height: $dock_icon_size; + background-size: contain; + background-repeat: no-repeat; + } + &:hover { + background-image: linear-gradient( + transparent, + transparentize($fg_color, 0.94) + ); + .icon { + min-width: $dock_icon_size * 1.2; + min-height: $dock_icon_size * 1.2; + } + } + &:active { + .indicator { + background-color: $accent; + } + } + &.firefox .icon { + background-image: url($assets + "apps/firefox.png"); + } + &.terminal .icon { + background-image: url($assets + "apps/terminal.png"); + } + &.file-manager .icon { + background-image: url($assets + "apps/file-manager.png"); + } + &.editor .icon { + background-image: url($assets + "apps/editor.png"); + } + &.spotify .icon { + background-image: url($assets + "apps/spotify.png"); + } + &.caprine .icon { + background-image: url($assets + "apps/caprine.png"); + } + &.bitwig .icon { + background-image: url($assets + "apps/bitwig.png"); + } + &.battle .icon { + background-image: url($assets + "apps/battle.png"); + } + &.bottles .icon { + background-image: url($assets + "apps/bottles.png"); + } + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/hbar.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/hbar.scss index 949752194..28569f5b2 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/hbar.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/hbar.scss @@ -1,113 +1,113 @@ .hpanel { - min-height: 2.2em; - font-weight: bold; - font-size: 1.1em; - color: $fg_color; - background-color: transparent; - border-bottom: $border_width solid $popover_border_color; - box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.8); - - .button-bin { - margin: 3px 2px; - background-color: $bg_color; - border-radius: $button_radius; - - &.launcher { - margin-left: 4px - } - - &.powermenu { - margin-right: 4px - } - } - - .button { - .icon { - font-size: 1.2em; - } - - @include button($flat: true, $radii: $panel_button_radius); - - >* { - padding: 0 .7em - } - - &.launcher { - color: $accent; - } - - &.powermenu { - color: $red; - } - - &.window { - @include button($flat: true, $interactive: false) - } - - &.workspaces { - @include button($flat: false, $radii: $panel_button_radius); - background-color: $bg_color; - border-radius: $button_radius; - - .workspace-btn { - label { - font-size: 1.2em; - } - - margin: 2px; - - &.empty { - color: transparentize($fg_color, 0.34); - } - - &.occupied { - color: transparentize($fg_color, 0.18); - } - - &.active { - color: $fg_color; - } - - &:hover { - &.empty { - color: transparentize($fg_color, 0.18); - } - - &.occupied { - color: $fg_color; - } - } - - &:active { - color: $accent; - } - } - } - - &.system-indicators { - @include system-indicators($orientation: 'h'); - - >*>*>* { - padding: 0 .3em; - } - } - - &.media { - .icon { - margin-right: .2em; - - &.spotify { - color: $green; - } - - &.firefox { - color: $orange; - } - - &.mpv { - color: $magenta; - } - } - } - } -} \ No newline at end of file + min-height: 2.2em; + font-weight: bold; + font-size: 1.1em; + color: $fg_color; + background-color: transparent; + border-bottom: $border_width solid $popover_border_color; + box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.8); + + .button-bin { + margin: 3px 2px; + background-color: $bg_color; + border-radius: $button_radius; + + &.launcher { + margin-left: 4px; + } + + &.powermenu { + margin-right: 4px; + } + } + + .button { + .icon { + font-size: 1.2em; + } + + @include button($flat: true, $radii: $panel_button_radius); + + > * { + padding: 0 0.7em; + } + + &.launcher { + color: $accent; + } + + &.powermenu { + color: $red; + } + + &.window { + @include button($flat: true, $interactive: false); + } + + &.workspaces { + @include button($flat: false, $radii: $panel_button_radius); + background-color: $bg_color; + border-radius: $button_radius; + + .workspace-btn { + label { + font-size: 1.2em; + } + + margin: 2px; + + &.empty { + color: transparentize($fg_color, 0.34); + } + + &.occupied { + color: transparentize($fg_color, 0.18); + } + + &.active { + color: $fg_color; + } + + &:hover { + &.empty { + color: transparentize($fg_color, 0.18); + } + + &.occupied { + color: $fg_color; + } + } + + &:active { + color: $accent; + } + } + } + + &.system-indicators { + @include system-indicators($orientation: "h"); + + > * > * > * { + padding: 0 0.3em; + } + } + + &.media { + .icon { + margin-right: 0.2em; + + &.spotify { + color: $green; + } + + &.firefox { + color: $orange; + } + + &.mpv { + color: $magenta; + } + } + } + } +} diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/media.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/media.scss index a55f3b694..0284dcef1 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/media.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/media.scss @@ -1,10 +1,10 @@ -.media-window{ - padding: 0; - .media{ - @include media($height: 20em, $style: 'popover'); - padding: 0; - .cover{ - min-width: 20em; - } - } +.media-window { + padding: 0; + .media { + @include media($height: 20em, $style: "popover"); + padding: 0; + .cover { + min-width: 20em; + } + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/noti_center.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/noti_center.scss index 1ae2109dd..91e668731 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/noti_center.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/noti_center.scss @@ -1,47 +1,72 @@ -.notification-center{ - min-width: 400px; - @include floating_widget; - .title{ - button{ - font-size: 1.0em; - padding: .4em 1em; - @include button; - } - label{ font-size: 1.4em } - margin-bottom: $spacing; - } - .notifications-list{ - @include scrollbar; - .placeholder{ - .icon{ font-size: 8em; } - label{ font-size: 2em; } - } - .notification{ - @include notification; - .notification-content{ - @include widget; - margin-bottom: $spacing; - border-radius: $widget_radius*0.3; - } - &:first-child .notification-content{ - border-radius: $widget_radius $widget_radius $widget_radius*0.3 $widget_radius*0.3; - } - &:last-child .notification-content{ - border-radius: $widget_radius*0.3 $widget_radius*0.3 $widget_radius $widget_radius; - } - &:first-child:last-child .notification-content{ - border-radius: $widget_radius; - } - } - margin-bottom: $spacing; - } - .controls{ - @include widget; - padding: $popover_padding * 0.5; - .sys-sliders{ @include sys-sliders; } - .toggle { - min-height: 3.4em; - @include toggle_button($toggle_radius: $radii*1.4); - } - } +.notification-center { + min-width: 400px; + @include floating_widget; + + .title { + button { + font-size: 1em; + padding: 0.4em 1em; + @include button; + } + + label { + font-size: 1.4em; + } + + margin-bottom: $spacing; + } + + .notifications-list { + @include scrollbar; + + .placeholder { + .icon { + font-size: 8em; + } + + label { + font-size: 2em; + } + } + + .notification { + @include notification; + + .notification-content { + @include widget; + margin-bottom: $spacing; + border-radius: $widget_radius * 0.3; + } + + &:first-child .notification-content { + border-radius: $widget_radius $widget_radius $widget_radius * + 0.3 $widget_radius * 0.3; + } + + &:last-child .notification-content { + border-radius: $widget_radius * 0.3 $widget_radius * 0.3 + $widget_radius $widget_radius; + } + + &:first-child:last-child .notification-content { + border-radius: $widget_radius; + } + } + + margin-bottom: $spacing; + } + + .controls { + @include widget; + padding: $popover_padding * 0.5; + + .sys-sliders { + @include sys-sliders; + } + + .toggle { + min-height: 3.4em; + @include toggle_button($toggle_radius: $radii * 1.4); + } + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/notifications.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/notifications.scss index 76bc3d39a..f0225e6d1 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/notifications.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/notifications.scss @@ -1,9 +1,9 @@ -.notifications-window-box{ - .notification{ - @include notification; - .notification-content{ - min-width: 450px; - @include floating_widget; - } - } +.notifications-window-box { + .notification { + @include notification; + .notification-content { + min-width: 450px; + @include floating_widget; + } + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/osd.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/osd.scss index 56f2c44e4..528570099 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/osd.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/osd.scss @@ -1,18 +1,18 @@ -.osd-widget{ - @include floating_widget; - padding: .3em; - .icon{ - font-size: 40px; - color: $accent_fg; - min-width: 30px; - min-height: 30px; - } - .scale{ - min-height: 14em; - @include slider($width: 3em); - trough{ - background-color: transparent; - border: none; - } - } -} \ No newline at end of file +.osd-widget { + @include floating_widget; + padding: 0.3em; + .icon { + font-size: 40px; + color: $accent_fg; + min-width: 30px; + min-height: 30px; + } + .scale { + min-height: 14em; + @include slider($width: 3em); + trough { + background-color: transparent; + border: none; + } + } +} diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/powermenu.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/powermenu.scss index b098ccdab..721d26796 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/powermenu.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/powermenu.scss @@ -1,49 +1,75 @@ -.background.powermenu{ - background-color: rgba(0,0,0,0.5); - .content{ - @include floating_widget; - .user{ @include user; } - .clock{ - text-shadow: $text_shadow; - margin-bottom: 2.2em; - .hour *{ font-size: 9em } - .date{ font-size: 2em } - } - .power-menu{ - border-radius: $radii*3; - padding: 15px; - } - .button-bin{ - margin: 15px; - margin-bottom: 0; - .button{ - @include button($focusable: true); - border-radius: $radii*2.4; - font-size: 60px; - min-width: 130px; - min-height: 130px; - .icon{ - background-size: contain; - margin: 24px; - @if $theme == 'light' { - &.shutdown{ background-image: url($assets+'powermenu/light-shutdown.png'); } - &.reboot{ background-image: url($assets+'powermenu/light-reboot.png'); } - &.logout{ background-image: url($assets+'powermenu/light-logout.png'); } - &.suspend{ background-image: url($assets+'powermenu/light-suspend.png'); } - &.lock{ background-image: url($assets+'powermenu/light-lock.png'); } - }@else{ - &.shutdown{ background-image: url($assets+'powermenu/shutdown.png'); } - &.reboot{ background-image: url($assets+'powermenu/reboot.png'); } - &.logout{ background-image: url($assets+'powermenu/logout.png'); } - &.suspend{ background-image: url($assets+'powermenu/suspend.png'); } - &.lock{ background-image: url($assets+'powermenu/lock.png'); } - } - } - } - .label{ - font-size: 20px; - margin: 8px 0; - } - } - } +.background.powermenu { + background-color: rgba(0, 0, 0, 0.5); + .content { + @include floating_widget; + .user { + @include user; + } + .clock { + text-shadow: $text_shadow; + margin-bottom: 2.2em; + .hour * { + font-size: 9em; + } + .date { + font-size: 2em; + } + } + .power-menu { + border-radius: $radii * 3; + padding: 15px; + } + .button-bin { + margin: 15px; + margin-bottom: 0; + .button { + @include button($focusable: true); + border-radius: $radii * 2.4; + font-size: 60px; + min-width: 130px; + min-height: 130px; + .icon { + background-size: contain; + margin: 24px; + @if $theme == "light" { + &.shutdown { + background-image: url($assets + "powermenu/light-shutdown.png"); + } + &.reboot { + background-image: url($assets + "powermenu/light-reboot.png"); + } + &.logout { + background-image: url($assets + "powermenu/light-logout.png"); + } + &.suspend { + background-image: url($assets + "powermenu/light-suspend.png"); + } + &.lock { + background-image: url($assets + "powermenu/light-lock.png"); + } + } @else { + &.shutdown { + background-image: url($assets + "powermenu/shutdown.png"); + } + &.reboot { + background-image: url($assets + "powermenu/reboot.png"); + } + &.logout { + background-image: url($assets + "powermenu/logout.png"); + } + &.suspend { + background-image: url($assets + "powermenu/suspend.png"); + } + &.lock { + background-image: url($assets + "powermenu/lock.png"); + } + } + } + } + .label { + font-size: 20px; + margin: 8px 0; + } + } + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/quicksettings.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/quicksettings.scss index 4c6a69d04..ea749ef6d 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/quicksettings.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/quicksettings.scss @@ -1,54 +1,66 @@ -.quick-settings{ - @include floating_widget; +.quick-settings { + @include floating_widget; - .widget{ - @include widget; - margin: $spacing; - padding: $spacing; - } + .widget { + @include widget; + margin: $spacing; + padding: $spacing; + } - .sys-sliders{ @include sys-sliders; } + .sys-sliders { + @include sys-sliders; + } - .sys-actions{ - .user{ @include user; } - .sysactions{ - button{ - @include button($radii: 40%); - margin: $spacing; - padding: .4em; - label{ font-size: 2.4em } - &.power{ color: $red; } - } - .uptime{ - font-size: 1.3em; - color: transparentize($fg_color, 0.5); - } - } - } + .sys-actions { + .user { + @include user; + } + .sysactions { + button { + @include button($radii: 40%); + margin: $spacing; + padding: 0.4em; + label { + font-size: 2.4em; + } + &.power { + color: $red; + } + } + .uptime { + font-size: 1.3em; + color: transparentize($fg_color, 0.5); + } + } + } - .system{ - > * > *{ - @include widget; - margin: $spacing; - padding: 8px; - min-width: 4.4em; - min-height: 4.4em; - } - circular-progress{ - background-color: $bg_color; - color: $accent; - &.battery{ - &.low{ color: $red } - } - .icon{ font-size: 1.8em; } - } - } + .system { + > * > * { + @include widget; + margin: $spacing; + padding: 8px; + min-width: 4.4em; + min-height: 4.4em; + } + circular-progress { + background-color: $bg_color; + color: $accent; + &.battery { + &.low { + color: $red; + } + } + .icon { + font-size: 1.8em; + } + } + } - .toggles .toggle{ - @include toggle_button($toggle_radius: $radii*2.4); - } + .toggles .toggle { + @include toggle_button($toggle_radius: $radii * 2.4); + } - .media{ - @include media($height: 12em); - } + .media { + @include media($height: 12em); + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/screenshot.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/screenshot.scss index 163e36c9b..b67d501d6 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/screenshot.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/screenshot.scss @@ -1,99 +1,99 @@ .background.takeshot { - background-color: rgba(0, 0, 0, 0.5); - - .content { - @include floating_widget; - - .takeshot-menu { - border-radius: $radii*3; - padding: 15px; - } - - .button-bin { - margin: 15px; - margin-bottom: 0; - margin-top: 0; - - .button { - @include button($focusable: true); - border-radius: $radii*2.4; - min-width: 130px; - min-height: 130px; - } - - .label { - font-size: 20px; - margin: 8px 0; - } - } - - .icon { - font-size: 5rem; - } - - .blue { - color: $blue; - } - - .red { - color: $red; - } - - .green { - color: $green; - } - } + background-color: rgba(0, 0, 0, 0.5); + + .content { + @include floating_widget; + + .takeshot-menu { + border-radius: $radii * 3; + padding: 15px; + } + + .button-bin { + margin: 15px; + margin-bottom: 0; + margin-top: 0; + + .button { + @include button($focusable: true); + border-radius: $radii * 2.4; + min-width: 130px; + min-height: 130px; + } + + .label { + font-size: 20px; + margin: 8px 0; + } + } + + .icon { + font-size: 5rem; + } + + .blue { + color: $blue; + } + + .red { + color: $red; + } + + .green { + color: $green; + } + } } .background.previewshot { - .content { - @include floating_widget; - - .previewshot-menu { - border-radius: $radii*3; - padding: 15px; - } - - .button-bin { - margin: 15px; - margin-bottom: 0; - margin-top: 0; - - .button { - @include button($focusable: true); - border-radius: $radii; - min-width: 15px; - min-height: 50px; - } - - .label { - font-size: 15px; - margin: 8px 0; - } - } - - .icon { - font-size: 1.5rem; - } - - .blue { - color: $blue; - } - - .red { - color: $red; - } - - .green { - color: $green; - } - } - - .preview { - background-image: url("/tmp/screenshot.png"); - background-size: contain; - background-repeat: no-repeat; - background-position: center; - margin: 1rem; - } -} \ No newline at end of file + .content { + @include floating_widget; + + .previewshot-menu { + border-radius: $radii * 3; + padding: 15px; + } + + .button-bin { + margin: 15px; + margin-bottom: 0; + margin-top: 0; + + .button { + @include button($focusable: true); + border-radius: $radii; + min-width: 15px; + min-height: 50px; + } + + .label { + font-size: 15px; + margin: 8px 0; + } + } + + .icon { + font-size: 1.5rem; + } + + .blue { + color: $blue; + } + + .red { + color: $red; + } + + .green { + color: $green; + } + } + + .preview { + background-image: url("/tmp/screenshot.png"); + background-size: contain; + background-repeat: no-repeat; + background-position: center; + margin: 1rem; + } +} diff --git a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/vbar.scss b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/vbar.scss index 9f5123d82..f3c572307 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/vbar.scss +++ b/home/isabel/programs/gui/confs/bars/eww/config/scss/windows/vbar.scss @@ -1,71 +1,83 @@ .vpanel { - min-width: 2.2em; - font-weight: bold; - color: $fg_color; - background-color: $bg_color; + min-width: 2.2em; + font-weight: bold; + color: $fg_color; + background-color: $bg_color; - // &.floating { - margin: $wm_gaps; - border-radius: $panel_radius; - box-shadow: 0 0 5px rgba(0,0,0,0.3); - border: $border_width solid $popover_border_color; - // } + // &.floating { + margin: $wm_gaps; + border-radius: $panel_radius; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); + border: $border_width solid $popover_border_color; + // } - .leftBar .button-bin { - margin: .4em .4em 0 .4em; - } - .centerBar .button-bin { - margin: .2em .4em; - } - .rightBar .button-bin { - margin: 0 .4em .4em .4em; - } + .leftBar .button-bin { + margin: 0.4em 0.4em 0 0.4em; + } + .centerBar .button-bin { + margin: 0.2em 0.4em; + } + .rightBar .button-bin { + margin: 0 0.4em 0.4em 0.4em; + } - .media{ - @include panel_media(); - .player{ min-height: 2.6em; } - } + .media { + @include panel_media(); + .player { + min-height: 2.6em; + } + } - .icon{ font-size: 1.3em;} - .button{ - @include button($flat: true, $radii: $panel_button_radius); - > * { padding: .4em } + .icon { + font-size: 1.3em; + } + .button { + @include button($flat: true, $radii: $panel_button_radius); + > * { + padding: 0.4em; + } - &.launcher{ color: $blue; } - &.powermenu{ color: $red; } + &.launcher { + color: $blue; + } + &.powermenu { + color: $red; + } - &.clock{ - @include button($flat: false, $interactive: true); - label{ font-size: 1.4em;} - .separator{ - min-height: 0.2em; - padding: 0 .3em; - .dot{ - min-height: .15em; - min-width: .15em; - border-radius: $radii; - background-color: $fg_color; - } - } - } + &.clock { + @include button($flat: false, $interactive: true); + label { + font-size: 1.4em; + } + .separator { + min-height: 0.2em; + padding: 0 0.3em; + .dot { + min-height: 0.15em; + min-width: 0.15em; + border-radius: $radii; + background-color: $fg_color; + } + } + } - &.workspaces{ - @include workspaces; - } + &.workspaces { + @include workspaces; + } - &.system-indicators{ - @include system-indicators($orientation: 'v'); - } - } + &.system-indicators { + @include system-indicators($orientation: "v"); + } + } - > * > .separator{ - margin: .3em 0; - padding: 0 .8em; - .dot{ - min-height: .3em; - min-width: .3em; - border-radius: $radii; - background-color: transparentize($fg_color, 0.6); - } - } + > * > .separator { + margin: 0.3em 0; + padding: 0 0.8em; + .dot { + min-height: 0.3em; + min-width: 0.3em; + border-radius: $radii; + background-color: transparentize($fg_color, 0.6); + } + } } diff --git a/home/isabel/programs/gui/confs/bars/eww/config/yuck/windows.yuck b/home/isabel/programs/gui/confs/bars/eww/config/yuck/windows.yuck index 20b13445a..01be61d8a 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/yuck/windows.yuck +++ b/home/isabel/programs/gui/confs/bars/eww/config/yuck/windows.yuck @@ -8,4 +8,4 @@ (include "./yuck/windows/noti_center.yuck") (include "./yuck/windows/media.yuck") (include "./yuck/windows/app_launcher.yuck") -(include "./yuck/windows/screenshot.yuck") \ No newline at end of file +(include "./yuck/windows/screenshot.yuck") diff --git a/home/isabel/programs/gui/confs/bars/eww/config/yuck/windows/screenshot.yuck b/home/isabel/programs/gui/confs/bars/eww/config/yuck/windows/screenshot.yuck index 1d36ee4a7..27b5a9571 100644 --- a/home/isabel/programs/gui/confs/bars/eww/config/yuck/windows/screenshot.yuck +++ b/home/isabel/programs/gui/confs/bars/eww/config/yuck/windows/screenshot.yuck @@ -85,4 +85,4 @@ ) (box :class "preview" :vexpand true :hexpand true) ) -) \ No newline at end of file +) diff --git a/home/isabel/programs/gui/confs/bars/eww/default.nix b/home/isabel/programs/gui/confs/bars/eww/default.nix index 1bcb9e066..2c4bb3581 100644 --- a/home/isabel/programs/gui/confs/bars/eww/default.nix +++ b/home/isabel/programs/gui/confs/bars/eww/default.nix @@ -1,25 +1,21 @@ { - config, lib, + self', pkgs, osConfig, defaults, ... }: let - inherit (lib) mkIf; + inherit (lib) isWayland; ewwPackage = - if env.isWayland + if isWayland osConfig then pkgs.eww-wayland else pkgs.eww; - device = osConfig.modules.device; - env = osConfig.modules.usrEnv; acceptedTypes = ["desktop" "laptop" "hybrid"]; - programs = osConfig.modules.programs; - sys = osConfig.modules.system; in { - config = mkIf (builtins.elem device.type acceptedTypes && programs.gui.enable && sys.video.enable && defaults.bar == "eww") { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && (isWayland osConfig) && osConfig.modules.programs.gui.enable && defaults.bar == "eww") { home.packages = with pkgs; [ socat jaq @@ -35,7 +31,7 @@ in { harfbuzz gdk-pixbuf glib - nur.repos.bella.gjs # patched gjs version + self'.packages.gjs # patched gjs version ]; programs.eww = { diff --git a/home/isabel/programs/gui/confs/bars/waybar/default.nix b/home/isabel/programs/gui/confs/bars/waybar/default.nix index 5fe29b75b..2ac1137c5 100644 --- a/home/isabel/programs/gui/confs/bars/waybar/default.nix +++ b/home/isabel/programs/gui/confs/bars/waybar/default.nix @@ -1,22 +1,23 @@ { - config, pkgs, lib, osConfig, defaults, ... }: let - inherit (lib) mkIf; - env = osConfig.modules.usrEnv; - acceptedTypes = ["desktop" "laptop" "hybrid"]; - inherit (osConfig.modules) programs device; + inherit (lib) optionalString; sys = osConfig.modules.system; + cfg = osConfig.modules.programs; + acceptedTypes = ["desktop" "laptop" "hybrid"]; in { - config = mkIf (builtins.elem device.type acceptedTypes && programs.gui.enable && sys.video.enable && env.isWayland && defaults.bar == "waybar") { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && lib.isWayland osConfig && defaults.bar == "waybar") { home.packages = with pkgs; [wlogout]; + programs.waybar = { enable = true; package = pkgs.waybar; + systemd.enable = true; + style = import ./style.nix {}; settings = { mainBar = { layer = "top"; @@ -31,12 +32,13 @@ in { "custom/launcher" ]; modules-center = [ - "wlr/workspaces" + "hyprland/workspaces" ]; modules-right = [ "tray" "backlight" - "bluetooth" + (optionalString sys.bluetooth.enable "bluetooth") + (optionalString cfg.gaming.enable "gamemode") "pulseaudio" "battery" "clock" @@ -51,7 +53,7 @@ in { "on-click-middle" = "close"; "on-click-right" = "activate"; }; - "wlr/workspaces" = { + "hyprland/workspaces" = { disable-scroll = true; all-outputs = true; sort-by-number = true; @@ -183,9 +185,20 @@ in { on-click = "rofi -show drun"; on-click-right = "rofi -show drun"; }; + gamemode = { + format = "󰊴"; + format-alt = "{glyph}"; + glyph = "󰊴"; + hide-not-running = true; + use-icon = true; + icon-name = "input-gaming-symbolic"; + icon-spacing = 4; + icon-size = 20; + tooltip = true; + tooltip-format = "Games running: {count}"; + }; }; }; - style = builtins.readFile ./style.css; }; }; } diff --git a/home/isabel/programs/gui/confs/bars/waybar/style.css b/home/isabel/programs/gui/confs/bars/waybar/style.css deleted file mode 100644 index 85b94589b..000000000 --- a/home/isabel/programs/gui/confs/bars/waybar/style.css +++ /dev/null @@ -1,191 +0,0 @@ -@define-color base #1e1e2e; -@define-color mantle #181825; -@define-color crust #11111b; - -@define-color text #cdd6f4; -@define-color subtext0 #a6adc8; -@define-color subtext1 #bac2de; - -@define-color surface0 #313244; -@define-color surface1 #45475a; -@define-color surface2 #585b70; - -@define-color overlay0 #6c7086; -@define-color overlay1 #7f849c; -@define-color overlay2 #9399b2; - -@define-color blue #89b4fa; -@define-color lavender #b4befe; -@define-color sapphire #74c7ec; -@define-color sky #89dceb; -@define-color teal #94e2d5; -@define-color green #a6e3a1; -@define-color yellow #f9e2af; -@define-color peach #fab387; -@define-color maroon #eba0ac; -@define-color red #f38ba8; -@define-color mauve #cba6f7; -@define-color pink #f5c2e7; -@define-color flamingo #f2cdcd; -@define-color rosewater #f5e0dc; - -@define-color white #ffffff; - -* { - border: none; - border-radius: 0; - font-family: RobotoMono Nerd Font, monospace, Noto Sans CJK JP; - font-weight: normal; - font-size: 14px; - min-height: 0; -} - -window#waybar { - background: rgba(21, 18, 27, 0); - color: #cdd6f4; -} - -tooltip { - background: #1e1e2e; - border-radius: 10px; - border-width: 2px; - border-style: solid; - border-color: #11111b; -} - -#workspaces button { - padding: 5px; - color: #313244; - margin-right: 5px; -} - -#workspaces button.active { - color: #a6adc8; -} - -#workspaces button.focused { - color: #a6adc8; - background: #eba0ac; - border-radius: 10px; -} - -#workspaces button.urgent { - color: #11111b; - background: #a6e3a1; - border-radius: 10px; -} - -#workspaces button:hover { - background: #11111b; - color: #cdd6f4; - border-radius: 10px; -} - -#custom-language, -#custom-logout, -#custom-updates, -#custom-caffeine, -#custom-weather, -#taskbar, -#window, -#clock, -#battery, -#pulseaudio, -#network, -#workspaces, -#tray, -#battery, -#custom-launcher, -#backlight { - background: #1e1e2e; - padding: 0px 10px; - margin: 3px 0px; - margin-top: 10px; - border: 1px solid #181825; - color: @white; -} - - -#backlight { - border-radius: 10px 0px 0px 10px; - border-right: 0px; - margin-left: 0px; -} - -#tray { - border-radius: 10px; - margin-right: 10px; -} - -#workspaces { - border-radius: 10px; - margin-left: 10px; - padding-right: 0px; - padding-left: 5px; -} - -#custom-language { - border-left: 0px; - border-right: 0px; -} - -#custom-updates { - border-radius: 10px; - margin-right: 10px; -} - -#window { - border-radius: 10px; - margin-left: 60px; - margin-right: 60px; -} - -#clock { - margin-left: 0px; - border-right: 0px; -} - -#network { - border-left: 0px; - border-right: 0px; -} - -#pulseaudio { - border-left: 0px; - border-right: 0px; -} - -#pulseaudio.microphone { - border-left: 0px; - border-right: 0px; -} - -#battery { - margin-right: 0px; - border-left: 0px; -} - -#taskbar { - border-radius: 10px; - margin-right: 10px; -} - -#custom-weather { - border-radius: 0px 10px 10px 0px; - border-right: 0px; - margin-left: 0px; -} - -#custom-logout { - border-radius: 0px 10px 10px 0px; - border-right: 0px; - margin-left: 0px; -} - -#custom-launcher { - border-radius: 10px 10px 10px 10px; - margin-right: 10px; - margin-left: 10px; - padding-right: 12.5px; - padding-left: 12.5px; -} diff --git a/home/isabel/programs/gui/confs/bars/waybar/style.nix b/home/isabel/programs/gui/confs/bars/waybar/style.nix new file mode 100644 index 000000000..180888a5c --- /dev/null +++ b/home/isabel/programs/gui/confs/bars/waybar/style.nix @@ -0,0 +1,193 @@ +_: '' + @define-color base #1e1e2e; + @define-color mantle #181825; + @define-color crust #11111b; + + @define-color text #cdd6f4; + @define-color subtext0 #a6adc8; + @define-color subtext1 #bac2de; + + @define-color surface0 #313244; + @define-color surface1 #45475a; + @define-color surface2 #585b70; + + @define-color overlay0 #6c7086; + @define-color overlay1 #7f849c; + @define-color overlay2 #9399b2; + + @define-color blue #89b4fa; + @define-color lavender #b4befe; + @define-color sapphire #74c7ec; + @define-color sky #89dceb; + @define-color teal #94e2d5; + @define-color green #a6e3a1; + @define-color yellow #f9e2af; + @define-color peach #fab387; + @define-color maroon #eba0ac; + @define-color red #f38ba8; + @define-color mauve #cba6f7; + @define-color pink #f5c2e7; + @define-color flamingo #f2cdcd; + @define-color rosewater #f5e0dc; + + @define-color white #ffffff; + + * { + border: none; + border-radius: 0; + font-family: RobotoMono Nerd Font, monospace, Noto Sans CJK JP; + font-weight: normal; + font-size: 14px; + min-height: 0; + } + + window#waybar { + background: rgba(21, 18, 27, 0); + color: #cdd6f4; + } + + tooltip { + background: #1e1e2e; + border-radius: 10px; + border-width: 2px; + border-style: solid; + border-color: #11111b; + } + + #workspaces button { + padding: 5px; + color: #313244; + margin-right: 5px; + } + + #workspaces button.active { + color: #a6adc8; + } + + #workspaces button.focused { + color: #a6adc8; + background: #eba0ac; + border-radius: 10px; + } + + #workspaces button.urgent { + color: #11111b; + background: #a6e3a1; + border-radius: 10px; + } + + #workspaces button:hover { + background: #11111b; + color: #cdd6f4; + border-radius: 10px; + } + + #custom-language, + #custom-logout, + #custom-updates, + #custom-caffeine, + #custom-weather, + #taskbar, + #window, + #clock, + #battery, + #pulseaudio, + #network, + #workspaces, + #tray, + #battery, + #custom-launcher, + #backlight { + background: #1e1e2e; + padding: 0px 10px; + margin: 3px 0px; + margin-top: 10px; + border: 1px solid #181825; + color: @white; + } + + + #backlight { + border-radius: 10px 0px 0px 10px; + border-right: 0px; + margin-left: 0px; + } + + #tray { + border-radius: 10px; + margin-right: 10px; + } + + #workspaces { + border-radius: 10px; + margin-left: 10px; + padding-right: 0px; + padding-left: 5px; + } + + #custom-language { + border-left: 0px; + border-right: 0px; + } + + #custom-updates { + border-radius: 10px; + margin-right: 10px; + } + + #window { + border-radius: 10px; + margin-left: 60px; + margin-right: 60px; + } + + #clock { + margin-left: 0px; + border-right: 0px; + } + + #network { + border-left: 0px; + border-right: 0px; + } + + #pulseaudio { + border-left: 0px; + border-right: 0px; + } + + #pulseaudio.microphone { + border-left: 0px; + border-right: 0px; + } + + #battery { + margin-right: 0px; + border-left: 0px; + } + + #taskbar { + border-radius: 10px; + margin-right: 10px; + } + + #custom-weather { + border-radius: 0px 10px 10px 0px; + border-right: 0px; + margin-left: 0px; + } + + #custom-logout { + border-radius: 0px 10px 10px 0px; + border-right: 0px; + margin-left: 0px; + } + + #custom-launcher { + border-radius: 10px 10px 10px 10px; + margin-right: 10px; + margin-left: 10px; + padding-right: 12.5px; + padding-left: 12.5px; + } +'' diff --git a/home/isabel/programs/gui/confs/browsers/chromium.nix b/home/isabel/programs/gui/confs/browsers/chromium.nix index 44df0d83c..cee94b349 100644 --- a/home/isabel/programs/gui/confs/browsers/chromium.nix +++ b/home/isabel/programs/gui/confs/browsers/chromium.nix @@ -5,13 +5,10 @@ defaults, ... }: let - inherit (lib) mkIf optionals; - inherit (osConfig.modules) device programs; - sys = osConfig.modules.system; - env = osConfig.modules.usrEnv; + inherit (osConfig.modules.system) video; acceptedTypes = ["laptop" "desktop" "hybrid"]; in { - config = mkIf (builtins.elem device.type acceptedTypes && programs.gui.enable && sys.video.enable && defaults.browser == "chromium") { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && osConfig.modules.programs.gui.enable && video.enable && defaults.browser == "chromium") { programs.chromium = { enable = true; extensions = [ @@ -23,7 +20,7 @@ in { "jghecgabfgfdldnmbfkhmffcabddioke" # Volume Master "emffkefkbkpkgpdeeooapgaicgmcbolj" # Wikiwand ]; - package = pkgs.chromium.override { + package = pkgs.ungoogled-chromium.override { nss = pkgs.nss_latest; commandLineArgs = [ @@ -53,7 +50,7 @@ in { "--disable-speech-api" "--disable-speech-synthesis-api" ] - ++ optionals (env.isWayland) [ + ++ lib.optionals (lib.isWayland osConfig) [ # Wayland # Disabled because hardware acceleration doesn't work # when disabling --use-gl=egl, it's not gonna show any emoji diff --git a/home/isabel/programs/gui/confs/browsers/default.nix b/home/isabel/programs/gui/confs/browsers/default.nix index 381947f32..f4d7c836c 100644 --- a/home/isabel/programs/gui/confs/browsers/default.nix +++ b/home/isabel/programs/gui/confs/browsers/default.nix @@ -1,6 +1,6 @@ _: { imports = [ ./chromium.nix - ./firefox.nix + ./schizofox.nix ]; } diff --git a/home/isabel/programs/gui/confs/browsers/firefox.nix b/home/isabel/programs/gui/confs/browsers/schizofox.nix similarity index 62% rename from home/isabel/programs/gui/confs/browsers/firefox.nix rename to home/isabel/programs/gui/confs/browsers/schizofox.nix index 20bbe37f9..9c60aaca6 100644 --- a/home/isabel/programs/gui/confs/browsers/firefox.nix +++ b/home/isabel/programs/gui/confs/browsers/schizofox.nix @@ -1,26 +1,34 @@ { - config, lib, inputs, osConfig, defaults, ... -}: -with lib; let - inherit (osConfig.modules) device programs system; +}: let + inherit (osConfig.modules.system) video; acceptedTypes = ["desktop" "laptop" "hybrid"]; in { imports = [inputs.schizofox.homeManagerModule]; - config = mkIf (builtins.elem device.type acceptedTypes && programs.gui.enable && system.video.enable && defaults.browser == "firefox") { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && osConfig.modules.programs.gui.enable && video.enable && defaults.browser == "schizofox") { programs.schizofox = { enable = true; - package = "firefox-esr-115-unwrapped"; + + theme = { + background-darker = "181825"; + background = "1e1e2e"; + foreground = "cdd6f4"; + font = "RobotoMono Nerd Font"; + simplefox.enable = true; + darkreader.enable = true; + extraCss = '' + ''; + }; search = { defaultSearchEngine = "Searx"; removeEngines = ["Google" "Bing" "Amazon.com" "eBay" "Twitter" "Wikipedia"]; searxUrl = "https://search.isabelroses.com"; - searxQuery = "https://search.isabelroses.com/search?q={searchTerms}&categories=general"; + # searxQuery = "https://search.isabelroses.com/search?q={searchTerms}&categories=general"; addEngines = []; }; @@ -33,17 +41,15 @@ in { misc = { drmFix = true; disableWebgl = false; - #startPageURL = "file://${./startpage.html}"; + startPageURL = "https://dash.isabelroses.com"; }; extensions.extraExtensions = { # Addon IDs are in manifest.json or manifest-firefox.json "{446900e4-71c2-419f-a6a7-df9c091e268b}".install_url = "https://addons.mozilla.org/firefox/downloads/latest/bitwarden-password-manager/latest.xpi"; - "{b6129aa9-e45d-4280-aac8-3654e9d89d21}".install_url = "https://github.com/catppuccin/firefox/releases/download/old/catppuccin_mocha_sapphire.xpi"; "sponsorBlocker@ajay.app".install_url = "https://addons.mozilla.org/firefox/downloads/latest/sponsorblock/latest.xpi"; - "1018e4d6-728f-4b20-ad56-37578a4de76".install_url = "https://addons.mozilla.org/firefox/downloads/latest/flagfox/latest.xpi"; "{a4c4eda4-fb84-4a84-b4a1-f7c1cbf2a1ad}".install_url = "https://addons.mozilla.org/firefox/downloads/latest/refined-github-/latest.xpi"; - "{7a7a4a92-a2a0-41d1-9fd7-1e92480d612d}".install_url = "https://addons.mozilla.org/firefox/downloads/latest/stylus/latest.xpi"; + "{7a7a4a92-a2a0-41d1-9fd7-1e92480d612d}".install_url = "https://addons.mozilla.org/firefox/downloads/latest/styl-us/latest.xpi"; }; }; }; diff --git a/home/isabel/programs/gui/confs/default.nix b/home/isabel/programs/gui/confs/default.nix index c121861f3..e47e90a64 100644 --- a/home/isabel/programs/gui/confs/default.nix +++ b/home/isabel/programs/gui/confs/default.nix @@ -2,6 +2,7 @@ _: { imports = [ ./bars ./browsers + ./fileMangers ./launchers ./terminals diff --git a/home/isabel/programs/gui/confs/discord.nix b/home/isabel/programs/gui/confs/discord.nix index 63a9f1f10..b9d56111e 100644 --- a/home/isabel/programs/gui/confs/discord.nix +++ b/home/isabel/programs/gui/confs/discord.nix @@ -2,19 +2,19 @@ osConfig, lib, pkgs, + self, ... -}: -with lib; let - device = osConfig.modules.device; - programs = osConfig.modules.programs; - sys = osConfig.modules.system; +}: let + inherit (osConfig.modules.system) video; acceptedTypes = ["laptop" "desktop" "hybrid"]; in { - config = mkIf (builtins.elem device.type acceptedTypes && programs.gui.enable && sys.video.enable) { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && osConfig.modules.programs.gui.enable && video.enable) { home.packages = with pkgs; [ ((discord.override { + nss = pkgs.nss_latest; withOpenASAR = true; withVencord = true; + withTTS = false; }) .overrideAttrs (old: { libPath = old.libPath + ":${pkgs.libglvnd}/lib"; diff --git a/home/isabel/programs/gui/confs/fileMangers/default.nix b/home/isabel/programs/gui/confs/fileMangers/default.nix new file mode 100644 index 000000000..1feef033f --- /dev/null +++ b/home/isabel/programs/gui/confs/fileMangers/default.nix @@ -0,0 +1,6 @@ +_: { + imports = [ + ./dolphin.nix + ./nemo.nix + ]; +} diff --git a/home/isabel/programs/gui/confs/fileMangers/dolphin.nix b/home/isabel/programs/gui/confs/fileMangers/dolphin.nix new file mode 100644 index 000000000..e5491ba2d --- /dev/null +++ b/home/isabel/programs/gui/confs/fileMangers/dolphin.nix @@ -0,0 +1,17 @@ +{ + osConfig, + lib, + pkgs, + defaults, + ... +}: let + inherit (osConfig.modules.system) video; + + acceptedTypes = ["laptop" "desktop" "hybrid"]; +in { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && osConfig.modules.programs.gui.enable && video.enable && defaults.fileManager == "dolphin") { + home.packages = with pkgs; [ + libsForQt5.dolphin + ]; + }; +} diff --git a/home/isabel/programs/gui/confs/fileMangers/nemo.nix b/home/isabel/programs/gui/confs/fileMangers/nemo.nix new file mode 100644 index 000000000..42262c899 --- /dev/null +++ b/home/isabel/programs/gui/confs/fileMangers/nemo.nix @@ -0,0 +1,18 @@ +{ + osConfig, + lib, + pkgs, + defaults, + ... +}: let + inherit (osConfig.modules.system) video; + acceptedTypes = ["laptop" "desktop" "hybrid"]; +in { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && osConfig.modules.programs.gui.enable && video.enable && defaults.fileManager == "nemo") { + home.packages = with pkgs; [ + cinnamon.nemo-with-extensions + cinnamon.nemo-fileroller + cinnamon.nemo-emblems + ]; + }; +} diff --git a/home/isabel/programs/gui/confs/launchers/rofi/config.nix b/home/isabel/programs/gui/confs/launchers/rofi/config.nix index 7b74cb8ff..5335a316f 100644 --- a/home/isabel/programs/gui/confs/launchers/rofi/config.nix +++ b/home/isabel/programs/gui/confs/launchers/rofi/config.nix @@ -1,10 +1,14 @@ -{config, ...}: { +{ + config, + defaults, + ... +}: { programs.rofi = { extraConfig = { modi = "drun"; icon-theme = "Papirus-Dark"; show-icons = true; - terminal = "alacritty"; + terminal = defaults.terminal; location = 0; disable-history = false; hide-scrollbar = true; diff --git a/home/isabel/programs/gui/confs/launchers/rofi/default.nix b/home/isabel/programs/gui/confs/launchers/rofi/default.nix index 4122a9a13..b517295c6 100644 --- a/home/isabel/programs/gui/confs/launchers/rofi/default.nix +++ b/home/isabel/programs/gui/confs/launchers/rofi/default.nix @@ -5,20 +5,17 @@ osConfig, defaults, ... -}: -with lib; let - device = osConfig.modules.device; +}: let acceptedTypes = ["laptop" "desktop" "hybrid" "lite"]; - sys = osConfig.modules.system; - programs = osConfig.modules.programs; rofiPackage = - if osConfig.modules.usrEnv.isWayland + if lib.isWayland osConfig then pkgs.rofi-wayland else pkgs.rofi; in { imports = [./config.nix]; - config = mkIf (builtins.elem device.type acceptedTypes && sys.video.enable && programs.gui.enable && defaults.launcher == "rofi") { + + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && osConfig.modules.programs.gui.enable && defaults.launcher == "rofi") { programs.rofi = { enable = true; package = rofiPackage.override { diff --git a/home/isabel/programs/gui/confs/launchers/wofi/default.nix b/home/isabel/programs/gui/confs/launchers/wofi/default.nix index 1287ec33c..64cba0070 100644 --- a/home/isabel/programs/gui/confs/launchers/wofi/default.nix +++ b/home/isabel/programs/gui/confs/launchers/wofi/default.nix @@ -4,15 +4,11 @@ osConfig, defaults, ... -}: -with lib; let - device = osConfig.modules.device; +}: let acceptedTypes = ["laptop" "desktop" "hybrid" "lite"]; - sys = osConfig.modules.system; - programs = osConfig.modules.programs; in { imports = [./config.nix]; - config = mkIf (builtins.elem device.type acceptedTypes && sys.video.enable && programs.gui.enable && defaults.launcher == "wofi") { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && (lib.isWayland osConfig) && osConfig.modules.programs.gui.enable && defaults.launcher == "wofi") { programs.wofi.enable = true; }; } diff --git a/home/isabel/programs/gui/confs/steam.nix b/home/isabel/programs/gui/confs/steam.nix deleted file mode 100644 index 9d0180620..000000000 --- a/home/isabel/programs/gui/confs/steam.nix +++ /dev/null @@ -1,27 +0,0 @@ -{lib, ...}: { - nixpkgs.config.allowUnfreePredicate = pkg: - builtins.elem (lib.getName pkg) [ - "steam" - "steam-original" - "steam-runtime" - ]; - - nixpkgs.config.packageOverrides = pkgs: { - steam = pkgs.steam.override { - extraPkgs = pkgs: - with pkgs; [ - libgdiplus - keyutils - libkrb5 - libpng - libpulseaudio - libvorbis - stdenv.cc.cc.lib - xorg.libXcursor - xorg.libXi - xorg.libXinerama - xorg.libXScrnSaver - ]; - }; - }; -} diff --git a/home/isabel/programs/gui/confs/terminals/alacritty.nix b/home/isabel/programs/gui/confs/terminals/alacritty.nix index 5efcf096b..6d5000ce5 100644 --- a/home/isabel/programs/gui/confs/terminals/alacritty.nix +++ b/home/isabel/programs/gui/confs/terminals/alacritty.nix @@ -4,12 +4,10 @@ defaults, ... }: let - inherit (lib) mkIf; - inherit (osConfig.modules) device programs; - sys = osConfig.modules.system; + inherit (osConfig.modules.system) video; acceptedTypes = ["laptop" "desktop" "hybrid"]; in { - config = mkIf (builtins.elem device.type acceptedTypes && programs.gui.enable && sys.video.enable && defaults.terminal == "alacritty") { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && osConfig.modules.programs.gui.enable && video.enable && defaults.terminal == "alacritty") { programs.alacritty = { enable = true; catppuccin.enable = true; diff --git a/home/isabel/programs/gui/confs/terminals/kitty.nix b/home/isabel/programs/gui/confs/terminals/kitty.nix index 564e137d2..0970bc4ce 100644 --- a/home/isabel/programs/gui/confs/terminals/kitty.nix +++ b/home/isabel/programs/gui/confs/terminals/kitty.nix @@ -1,23 +1,19 @@ { - config, lib, osConfig, defaults, ... }: let - inherit (lib) mkIf; - inherit (osConfig.modules) device programs; - sys = osConfig.modules.system; + inherit (osConfig.modules.system) video; acceptedTypes = ["laptop" "desktop" "hybrid"]; in { - config = mkIf (builtins.elem device.type acceptedTypes && programs.gui.enable && sys.video.enable && defaults.terminal == "kitty") { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && osConfig.modules.programs.gui.enable && video.enable && defaults.terminal == "kitty") { programs.kitty = { enable = true; catppuccin.enable = true; settings = { - # General background_opacity = "0.85"; - font_family = "monospace"; + font_family = "RobotoMono Nerd Font"; font_size = 13; disable_ligatures = "never"; cursor_shape = "beam"; diff --git a/home/isabel/programs/gui/confs/zathura.nix b/home/isabel/programs/gui/confs/zathura.nix index 42cf29470..0be41d509 100644 --- a/home/isabel/programs/gui/confs/zathura.nix +++ b/home/isabel/programs/gui/confs/zathura.nix @@ -4,14 +4,8 @@ pkgs, osConfig, ... -}: -with lib; let - device = osConfig.modules.device; - programs = osConfig.modules.programs; - sys = osConfig.modules.system; - acceptedTypes = ["laptop" "desktop" "hybrid" "lite"]; -in { - config = mkIf (builtins.elem device.type acceptedTypes && programs.gui.enable && sys.video.enable) { +}: { + config = lib.mkIf (osConfig.modules.programs.zathura.enable) { xdg.configFile."zathura/catppuccin-mocha".source = pkgs.fetchurl { url = "https://raw.githubusercontent.com/catppuccin/zathura/main/src/catppuccin-mocha"; hash = "sha256-/HXecio3My2eXTpY7JoYiN9mnXsps4PAThDPs4OCsAk="; diff --git a/home/isabel/programs/gui/gaming/default.nix b/home/isabel/programs/gui/gaming/default.nix new file mode 100644 index 000000000..edcc23c5d --- /dev/null +++ b/home/isabel/programs/gui/gaming/default.nix @@ -0,0 +1,29 @@ +{ + lib, + pkgs, + osConfig, + ... +}: let + inherit (osConfig.modules) programs; + acceptedTypes = ["laptop" "desktop" "lite"]; +in { + imports = [ + ./minecraft + ]; + + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && programs.gaming.enable) { + home = { + packages = with pkgs; [ + gamescope + legendary-gl + mono + winetricks + mangohud + lutris + #dolphin-emu # cool emulator + #yuzu # switch emulator + dotnet-runtime_6 # needed by terraria + ]; + }; + }; +} diff --git a/home/isabel/programs/gui/gaming/minecraft/default.nix b/home/isabel/programs/gui/gaming/minecraft/default.nix new file mode 100644 index 000000000..0e26105c0 --- /dev/null +++ b/home/isabel/programs/gui/gaming/minecraft/default.nix @@ -0,0 +1,41 @@ +{ + lib, + pkgs, + osConfig, + ... +}: let + catppuccin-mocha = pkgs.fetchzip { + url = "https://raw.githubusercontent.com/catppuccin/prismlauncher/main/themes/Mocha/Catppuccin-Mocha.zip"; + sha256 = "8uRqCoe9iSIwNnK13d6S4XSX945g88mVyoY+LZSPBtQ="; + }; + + javaPackages = with pkgs; [ + # Java 8 + temurin-jre-bin-8 + zulu8 + # Java 11 + temurin-jre-bin-11 + # Java 17 + temurin-jre-bin-17 + # Latest + temurin-jre-bin + zulu + graalvm-ce + ]; +in { + config = lib.mkIf osConfig.modules.programs.gaming.minecraft.enable { + home = { + # PrismLauncher now with a cool theme + file.".local/share/PrismLauncher/themes/mocha" = { + source = catppuccin-mocha; + recursive = true; + }; + + packages = [ + (pkgs.prismlauncher.override { + jdks = javaPackages; + }) + ]; + }; + }; +} diff --git a/home/isabel/programs/gui/shared.nix b/home/isabel/programs/gui/shared.nix index b00f5c795..5504deea0 100644 --- a/home/isabel/programs/gui/shared.nix +++ b/home/isabel/programs/gui/shared.nix @@ -3,25 +3,18 @@ lib, osConfig, ... -}: -with lib; let - programs = osConfig.modules.programs; - - device = osConfig.modules.device; +}: let acceptedTypes = ["laptop" "desktop" "hybrid" "lite"]; - sys = osConfig.modules.system; in { - config = mkIf ((programs.gui.enable && sys.video.enable) && (builtins.elem device.type acceptedTypes)) { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && osConfig.modules.programs.gui.enable) { home.packages = with pkgs; [ - bitwarden - obsidian - #zoom-us # I hate this - xfce.thunar - pamixer # move - jellyfin-media-player + bitwarden # password manager + obsidian # note taking with markdown + pamixer # move evntually + # jellyfin-media-player mangal # tui manga finder + reader - insomnia # rest client - libreoffice # office apps + # insomnia # rest client + nextcloud-client # cloud storage ]; }; } diff --git a/home/isabel/programs/gui/wayland.nix b/home/isabel/programs/gui/wayland.nix index d1ec49178..6227f2f41 100644 --- a/home/isabel/programs/gui/wayland.nix +++ b/home/isabel/programs/gui/wayland.nix @@ -3,19 +3,17 @@ lib, pkgs, ... -}: -with lib; let - env = osConfig.modules.usrEnv; - programs = osConfig.modules.programs; - sys = osConfig.modules.system; +}: let + acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; in { - config = mkIf (env.isWayland && programs.gui.enable && sys.video.enable) { - home.packages = with pkgs; [ - swappy - #swaynotificationcenter - wlsunset - wl-gammactl - pavucontrol - ]; + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && (lib.isWayland osConfig) && osConfig.modules.programs.gui.enable) { + home.packages = with pkgs; + [ + swappy # used for screenshot area selection + # swaynotificationcenter + wlsunset # reduce blue light at night + wl-gammactl + ] + ++ lib.optionals osConfig.modules.system.sound.enable [pavucontrol]; }; } diff --git a/home/isabel/programs/cli/scripts/default.nix b/home/isabel/programs/scripts/default.nix similarity index 91% rename from home/isabel/programs/cli/scripts/default.nix rename to home/isabel/programs/scripts/default.nix index 1fda07abb..510be2206 100644 --- a/home/isabel/programs/cli/scripts/default.nix +++ b/home/isabel/programs/scripts/default.nix @@ -11,7 +11,7 @@ file = { ".local/bin/preview" = { - # Preview script for fzf tab + # Preview files script for fzf tab executable = true; text = import ./preview.nix {inherit lib pkgs;}; }; diff --git a/home/isabel/programs/scripts/extract.nix b/home/isabel/programs/scripts/extract.nix new file mode 100644 index 000000000..f5b066d15 --- /dev/null +++ b/home/isabel/programs/scripts/extract.nix @@ -0,0 +1,50 @@ +_: '' + SAVEIFS=$IFS + IFS="$(printf '\n\t')" + + function extract { + if [ $# -eq 0 ]; then + # display usage if no parameters given + echo "Usage: extract ." + echo " extract [path/file_name_2.ext] [path/file_name_3.ext]" + fi + for n in "$@"; do + if [ ! -f "$n" ]; then + echo "'$n' - file doesn't exist" + return 1 + fi + + case "''${n%,}" in + *.cbt|*.tar.bz2|*.tar.gz|*.tar.xz|*.tbz2|*.tgz|*.txz|*.tar) + tar zxvf "$n" ;; + *.lzma) unlzma ./"$n" ;; + *.bz2) bunzip2 ./"$n" ;; + *.cbr|*.rar) unrar x -ad ./"$n" ;; + *.gz) gunzip ./"$n" ;; + *.cbz|*.epub|*.zip) unzip ./"$n" ;; + *.z) uncompress ./"$n" ;; + *.7z|*.apk|*.arj|*.cab|*.cb7|*.chm|*.deb|*.iso|*.lzh|*.msi|*.pkg|*.rpm|*.udf|*.wim|*.xar|*.vhd) + 7z x ./"$n" ;; + *.xz) unxz ./"$n" ;; + *.exe) cabextract ./"$n" ;; + *.cpio) cpio -id < ./"$n" ;; + *.cba|*.ace) unace x ./"$n" ;; + *.zpaq) zpaq x ./"$n" ;; + *.arc) arc e ./"$n" ;; + *.cso) + ciso 0 ./"$n" ./"$n.iso" && \ + extract "$n.iso" && \rm -f "$n" ;; + *.zlib) + zlib-flate -uncompress < ./"$n" > ./"$n.tmp" && \ + mv ./"$n.tmp" ./"''${n%.*zlib}" && rm -f "$n" ;; + *.dmg) + hdiutil mount ./"$n" -mountpoint "./$n.mounted" ;; + *) + echo "extract: '$n' - unknown archive method" + return 1 + ;; + esac + done + } + IFS=$SAVEIFS +'' diff --git a/home/isabel/programs/cli/scripts/preview.nix b/home/isabel/programs/scripts/preview.nix similarity index 87% rename from home/isabel/programs/cli/scripts/preview.nix rename to home/isabel/programs/scripts/preview.nix index 291be3fad..68691393e 100644 --- a/home/isabel/programs/cli/scripts/preview.nix +++ b/home/isabel/programs/scripts/preview.nix @@ -18,7 +18,7 @@ ${lib.getExe pkgs.catimg} -w 100 -r 2 "$1" ;; *directory*) - ${lib.getExe pkgs.exa} --icons -1 --color=always "$1" + ${lib.getExe pkgs.eza} --icons -1 --color=always "$1" ;; *) echo "unknown file format" diff --git a/home/isabel/programs/shells/bash.nix b/home/isabel/programs/shells/bash.nix new file mode 100644 index 000000000..19baf756f --- /dev/null +++ b/home/isabel/programs/shells/bash.nix @@ -0,0 +1,25 @@ +{ + config, + lib, + pkgs, + ... +}: { + programs.bash = { + enable = true; + bashrcExtra = '' + eval "$(${lib.getExe pkgs.starship} init bash)" + ''; + historyFile = "${config.xdg.stateHome}/bash/history"; + historyFileSize = 1000; + historySize = 100; + shellOptions = [ + "cdspell" + "checkjobs" + "checkwinsize" + "dirspell" + "globstar" + "histappend" + "no_empty_cmd_completion" + ]; + }; +} diff --git a/home/isabel/programs/shells/default.nix b/home/isabel/programs/shells/default.nix new file mode 100644 index 000000000..968cfec6e --- /dev/null +++ b/home/isabel/programs/shells/default.nix @@ -0,0 +1,8 @@ +_: { + imports = [ + ./bash.nix + ./fish.nix + ./nushell.nix + ./shellAlias.nix + ]; +} diff --git a/home/isabel/programs/shells/fish.nix b/home/isabel/programs/shells/fish.nix new file mode 100644 index 000000000..6d174ada2 --- /dev/null +++ b/home/isabel/programs/shells/fish.nix @@ -0,0 +1,31 @@ +_: { + programs.fish = { + enable = true; + catppuccin.enable = true; + plugins = []; + functions = { + bj = "nohup $argv /dev/null &"; + "." = '' + set -l input $argv[1] + if echo $input | grep -q '^[1-9][0-9]*$' + set -l levels $input + for i in (seq $levels) + cd .. + end + else + echo "Invalid input format. Please use '' to go back a specific number of directories." + end + ''; + }; + shellAbbrs = {}; + shellInit = '' + starship init fish | source + set -x MANPAGER "sh -c 'col -bx | bat -l man -p'" + set TERM "xterm-256color" + set fish_greeting + set TERMINAL "alacritty" + export "MICRO_TRUECOLOR=1" + export GPG_TTY=$(tty) + ''; + }; +} diff --git a/home/isabel/programs/shells/nushell.nix b/home/isabel/programs/shells/nushell.nix new file mode 100644 index 000000000..9d5ab81a2 --- /dev/null +++ b/home/isabel/programs/shells/nushell.nix @@ -0,0 +1,281 @@ +{ + config, + lib, + pkgs, + inputs, + osConfig, + ... +}: let + inherit (lib) mkIf; + inherit (osConfig.modules) system; +in { + programs.nushell = { + inherit (osConfig.modules.programs.cli) enable; + package = pkgs.nushell; + + extraConfig = '' + use std + $env.config = { + show_banner: false, + } + + # nu custom commands + # Open a file. Show structured data, if possible. Else fallback to `bat` + def o [filename: path] { + if (open $filename | describe) == "raw input" { + ${lib.getExe pkgs.bat} $filename + } else { + open $filename + } + } + + # If multiple shells are open, exit current one. If this is the last one, exit completely. + def-env x [] { + if (shells | length) == 1 { exit } else { dexit } + } + + # Go to system configuration flake, and open editor. + def-env fk [] { + enter ${system.flakePath} + commandline -i ($env.EDITOR + " ./") + } + + # CTP theme + let catppuccin = { + latte: { + rosewater: "#dc8a78" + flamingo: "#dd7878" + pink: "#ea76cb" + mauve: "#8839ef" + red: "#d20f39" + maroon: "#e64553" + peach: "#fe640b" + yellow: "#df8e1d" + green: "#40a02 + teal: "#179299" + sky: "#04a5e5" + sapphire: "#209fb5" + blue: "#1e66f5" + lavender: "#7287fd" + text: "#4c4f69" + subtext1: "#5c5f77" + subtext0: "#6c6f85" + overlay2: "#7c7f93" + overlay1: "#8c8fa1" + overlay0: "#9ca0b0" + surface2: "#acb0be" + surface1: "#bcc0cc" + surface0: "#ccd0da" + crust: "#dce0e8" + mantle: "#e6e9ef" + base: "#eff1f5" + } + frappe: { + rosewater: "#f2d5cf" + flamingo: "#eebebe" + pink: "#f4b8e4" + mauve: "#ca9ee6" + red: "#e78284" + maroon: "#ea999c" + peach: "#ef9f76" + yellow: "#e5c890" + green: "#a6d189" + teal: "#81c8be" + sky: "#99d1db" + sapphire: "#85c1dc" + blue: "#8caaee" + lavender: "#babbf1" + text: "#c6d0f5" + subtext1: "#b5bfe2" + subtext0: "#a5adce" + overlay2: "#949cbb" + overlay1: "#838ba7" + overlay0: "#737994" + surface2: "#626880" + surface1: "#51576d" + surface0: "#414559" + base: "#303446" + mantle: "#292c3c" + crust: "#232634" + } + macchiato: { + rosewater: "#f4dbd6" + flamingo: "#f0c6c6" + pink: "#f5bde6" + mauve: "#c6a0f6" + red: "#ed8796" + maroon: "#ee99a0" + peach: "#f5a97f" + yellow: "#eed49f" + green: "#a6da95" + teal: "#8bd5ca" + sky: "#91d7e3" + sapphire: "#7dc4e4" + blue: "#8aadf4" + lavender: "#b7bdf8" + text: "#cad3f5" + subtext1: "#b8c0e0" + subtext0: "#a5adcb" + overlay2: "#939ab7" + overlay1: "#8087a2" + overlay0: "#6e738d" + surface2: "#5b6078" + surface1: "#494d64" + surface0: "#363a4f" + base: "#24273a" + mantle: "#1e2030" + crust: "#181926" + } + mocha: { + rosewater: "#f5e0dc" + flamingo: "#f2cdcd" + pink: "#f5c2e7" + mauve: "#cba6f7" + red: "#f38ba8" + maroon: "#eba0ac" + peach: "#fab387" + yellow: "#f9e2af" + green: "#a6e3a1" + teal: "#94e2d5" + sky: "#89dceb" + sapphire: "#74c7ec" + blue: "#89b4fa" + lavender: "#b4befe" + text: "#cdd6f4" + subtext1: "#bac2de" + subtext0: "#a6adc8" + overlay2: "#9399b2" + overlay1: "#7f849c" + overlay0: "#6c7086" + surface2: "#585b70" + surface1: "#45475a" + surface0: "#313244" + base: "#1e1e2e" + mantle: "#181825" + crust: "#11111b" + } + } + + let stheme = $catppuccin.mocha + + let theme = { + separator: $stheme.overlay0 + leading_trailing_space_bg: $stheme.overlay0 + header: $stheme.green + date: $stheme.mauve + filesize: $stheme.blue + row_index: $stheme.pink + bool: $stheme.peach + int: $stheme.peach + duration: $stheme.peach + range: $stheme.peach + float: $stheme.peach + string: $stheme.green + nothing: $stheme.peach + binary: $stheme.peach + cellpath: $stheme.peach + hints: dark_gray + + shape_garbage: { fg: $stheme.crust bg: $stheme.red attr: b } + shape_bool: $stheme.blue + shape_int: { fg: $stheme.mauve attr: b} + shape_float: { fg: $stheme.mauve attr: b} + shape_range: { fg: $stheme.yellow attr: b} + shape_internalcall: { fg: $stheme.blue attr: b} + shape_external: { fg: $stheme.blue attr: b} + shape_externalarg: $stheme.text + shape_literal: $stheme.blue + shape_operator: $stheme.yellow + shape_signature: { fg: $stheme.green attr: b} + shape_string: $stheme.green + shape_filepath: $stheme.yellow + shape_globpattern: { fg: $stheme.blue attr: b} + shape_variable: $stheme.text + shape_flag: { fg: $stheme.blue attr: b} + shape_custom: {attr: b} + } + + # nu scripts + use "~/.config/nushell/scripts/custom-completions/nix/nix-completions.nu" * + use "~/.config/nushell/scripts/custom-completions/git/git-completions.nu" * + use "~/.config/nushell/scripts/custom-completions/npm/npm-completions.nu" * + use "~/.config/nushell/scripts/custom-completions/just/just-completions.nu" * + use "~/.config/nushell/scripts/custom-completions/tealdeer/tldr-completions.nu" * + use "~/.config/nushell/scripts/custom-completions/btm/btm-completions.nu" * + use "~/.config/nushell/scripts/custom-completions/make/make-completions.nu" * + + source ~/.cache/starship/init.nu + ''; + shellAliases = builtins.removeAttrs config.home.shellAliases ["o" "x" "fk" "mkdir" "nixclean"]; # are nu functions instead + envFile.text = '' + mkdir ~/.cache/starship + starship init nu | str replace "term size -c" "term size" | save -f ~/.cache/starship/init.nu + + ''; + loginFile.text = let + drv = pkgs.runCommandLocal "expand-env.nu" {} '' + . "${config.home.sessionVariablesPackage}/etc/profile.d/hm-session-vars.sh" + ${builtins.concatStringsSep "\n" + ( + map + (key: "echo \\$env.${key} = \\(__login_hm_var_new_value \\\"${key}\\\" \\\"\$${key}\\\"\\) >> $out") + ((builtins.attrNames config.home.sessionVariables) ++ ["PATH"]) + )} + ''; + in + #nu + '' + def __login_hm_var_new_value [key: string, value: string] { + if $key in $env { + # if it already exists, see if replacement is possible + let old = ($env | get $key) + let newVal = match ($old | describe) { + "string" => { + let oldSplit = ($old | split row ":") + if ($oldSplit | length) <= 1 { + $value # override + } else { + let newSplit = ($value | split row ":") + $oldSplit | prepend $newSplit | uniq | str join ":" + } + }, + "list" => ($old | prepend ($value | split row ":") | uniq), + } + $newVal + } else { + $value + } + } + + source ${drv} + ''; + }; + + home.file = mkIf osConfig.modules.programs.cli.enable { + "${config.xdg.configHome}/nushell/history.txt" = { + source = config.lib.file.mkOutOfStoreSymlink "${config.xdg.dataHome}/history"; + }; + "${config.xdg.configHome}/nushell/env-nix.nu" = let + environmentVariables = { + EDITOR = "nvim"; + GIT_EDITOR = "nvim"; + VISUAL = "code"; + TERMINAL = "alacritty"; + }; + in { + text = '' + ${lib.concatStringsSep "\n" + (lib.mapAttrsToList (k: v: "$env.${k} = ${v}") + environmentVariables)} + ''; + }; + "${config.xdg.configHome}/nushell/scripts" = { + source = pkgs.fetchFromGitHub { + owner = "nushell"; + repo = "nu_scripts"; + rev = "85da8c2fb5967a7f575d8f63ebeb8d49d36fc139"; + hash = "sha256-tT/BTnIXEgcMoyfujzWMFlOM7EclWT9LL/dt5jj7Y2M="; + }; + }; + }; +} diff --git a/home/isabel/programs/shells/shellAlias.nix b/home/isabel/programs/shells/shellAlias.nix new file mode 100644 index 000000000..a8be3254d --- /dev/null +++ b/home/isabel/programs/shells/shellAlias.nix @@ -0,0 +1,23 @@ +{osConfig, ...}: let + inherit (osConfig.modules) system; +in { + # This configuration creates the shell aliases across: bash, zsh and fish + home.shellAliases = { + mkdir = "mkdir -pv"; # always create pearent directory + df = "df -h"; # human readblity + rs = "sudo reboot"; + sysctl = "sudo systemctl"; + jctl = "journalctl -p 3 -xb"; # get error messages from journalctl + lg = "lazygit"; + + # Remap docker to podman + docker = "podman"; + docker-compose = "podman-compose"; + + # nix stuff + rebuild = "nix-store --verify; sudo nixos-rebuild switch --flake ${system.flakePath}#${system.hostname} --use-remote-sudo"; + deploy = "nixos-rebuild switch --flake ${system.flakePath}#$1 --target-host $1 --use-remote-sudo"; + nixclean = "sudo nix-collect-garbage --delete-older-than 3d && nix-collect-garbage -d"; + nixrepair = "nix-store --verify --check-contents --repair"; + }; +} diff --git a/home/isabel/btop.nix b/home/isabel/programs/tui/confs/btop.nix similarity index 53% rename from home/isabel/btop.nix rename to home/isabel/programs/tui/confs/btop.nix index 95dde838a..7a2ccfc05 100644 --- a/home/isabel/btop.nix +++ b/home/isabel/programs/tui/confs/btop.nix @@ -2,19 +2,15 @@ osConfig, lib, ... -}: -with lib; let - programs = osConfig.modules.programs; - device = osConfig.modules.device; - +}: let acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; in { - config = mkIf ((builtins.elem device.type acceptedTypes) && (programs.cli.enable)) { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && osConfig.modules.programs.tui.enable) { programs.btop = { enable = true; catppuccin.enable = true; settings = { - # color_theme = "catppuccin_mocha"; + color_theme = "catppuccin_mocha"; vim_keys = true; rounded_corners = true; }; diff --git a/home/isabel/programs/tui/confs/default.nix b/home/isabel/programs/tui/confs/default.nix index d8524f17f..af81e156b 100644 --- a/home/isabel/programs/tui/confs/default.nix +++ b/home/isabel/programs/tui/confs/default.nix @@ -1,5 +1,6 @@ _: { imports = [ + ./btop.nix ./lazygit.nix ./ranger.nix ]; diff --git a/home/isabel/programs/tui/confs/lazygit.nix b/home/isabel/programs/tui/confs/lazygit.nix index 1959d7d3b..a71491f92 100644 --- a/home/isabel/programs/tui/confs/lazygit.nix +++ b/home/isabel/programs/tui/confs/lazygit.nix @@ -3,11 +3,8 @@ lib, osConfig, ... -}: let - inherit (lib) mkIf; - inherit (osConfig.modules) programs; -in { - config.programs.lazygit = mkIf (programs.tui.enable) { +}: { + config.programs.lazygit = lib.mkIf (osConfig.modules.programs.tui.enable) { enable = true; catppuccin.enable = true; }; diff --git a/home/isabel/programs/tui/confs/ranger.nix b/home/isabel/programs/tui/confs/ranger.nix index e7ef197f7..0c14f7571 100644 --- a/home/isabel/programs/tui/confs/ranger.nix +++ b/home/isabel/programs/tui/confs/ranger.nix @@ -4,13 +4,10 @@ osConfig, lib, ... -}: -with lib; let - inherit (osConfig.modules) programs device; - +}: let acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; in { - config = mkIf ((builtins.elem device.type acceptedTypes) && (programs.tui.enable)) { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && osConfig.modules.programs.tui.enable) { home.packages = with pkgs; [ ranger ]; @@ -18,7 +15,7 @@ in { # TODO: more file preview methods xdg.configFile."ranger/rc.conf".text = '' set preview_images true - ${(optionalString config.programs.kitty.enable "set preview_images_method kitty")} + ${(lib.optionalString config.programs.kitty.enable "set preview_images_method kitty")} ''; }; } diff --git a/home/isabel/programs/tui/default.nix b/home/isabel/programs/tui/default.nix index 0d8cae13a..8effbc4b7 100644 --- a/home/isabel/programs/tui/default.nix +++ b/home/isabel/programs/tui/default.nix @@ -1,21 +1,18 @@ { - config, pkgs, osConfig, lib, ... -}: let - inherit (lib) mkIf; - inherit (osConfig.modules) programs; -in { +}: { imports = [ ./confs ]; - config = mkIf (programs.tui.enable) { + config = lib.mkIf osConfig.modules.programs.tui.enable { home.packages = with pkgs; [ wishlist # fancy ssh glow # fancy markdown + fx # fancy jq ]; }; } diff --git a/home/isabel/programs/wm/hyprland/config.nix b/home/isabel/programs/wm/hyprland/config.nix index b74b6264d..dd8a3f684 100644 --- a/home/isabel/programs/wm/hyprland/config.nix +++ b/home/isabel/programs/wm/hyprland/config.nix @@ -10,30 +10,6 @@ pointer = config.home.pointerCursor; dev = osConfig.modules.device; inherit (osConfig.modules.device) monitors; - - mapMonitors = builtins.concatStringsSep "\n" (imap0 (i: monitor: ''monitor=${monitor},${ - if monitor == "DP-1" - then "1920x1080@144" - else "preferred" - },${toString (i * 1920)}x0,1'') monitors); - - mapMonitorsToWs = builtins.concatStringsSep "\n" ( - builtins.genList ( - x: '' - workspace = ${toString (x + 1)}, monitor:${ - if (x + 1) <= 5 - then "${builtins.elemAt monitors 0} ${ - if (x + 1) == 1 - then ", default:true" - else "" - }" - else "${builtins.elemAt monitors 1}" - } - - '' - ) - 10 - ); in { wayland.windowManager.hyprland = { settings = { @@ -59,7 +35,7 @@ in { "waybar" ] ++ optionals (defaults.bar == "ags") [ - "ags" + "ags -b hypr" ]; input = { @@ -69,8 +45,9 @@ in { touchpad = { tap-to-click = true; natural_scroll = false; # this is not natrual - disable_while_typing = false; + disable_while_typing = false; # this is annoying }; + numlock_by_default = true; # numlock enable }; gestures.workspace_swipe = dev.type == "laptop" || dev.type == "hybrid"; @@ -85,8 +62,23 @@ in { "col.active_border" = "$sapphire"; "col.inactive_border" = "$surface0"; - "col.group_border_active" = "$blue"; - "col.group_border" = "$surface0"; + }; + + group = { + insert_after_current = true; + # focus on the window that has just been moved out of the group + focus_removed_window = true; + + "col.border_active" = "$blue"; + "col.border_inactive" = "$surface0"; + + groupbar = { + gradients = false; + font_size = 12; + + render_titles = false; + scrolling = true; # change focused window with scroll + }; }; misc = { @@ -105,7 +97,6 @@ in { decoration = { rounding = 10; - multisample_edges = true; active_opacity = 1.0; inactive_opacity = 1.0; @@ -128,7 +119,7 @@ in { }; animations = { - enabled = !(dev.type == "laptop"); + enabled = dev.type != "laptop"; bezier = [ "overshot, 0.05, 0.9, 0.1, 1.1" @@ -185,7 +176,7 @@ in { "$mod, E, exec, ${defaults.fileManager}" "$mod, C, exec, ${defaults.editor}" "$mod, Return, exec, ${defaults.terminal}" - "$mod, L, exec, ${defaults.screenLock}" + "$mod, L, exec, ${defaults.screenLocker}" "$mod, O, exec, obsidian" # window managment @@ -224,16 +215,17 @@ in { ] ++ optionals (defaults.bar == "waybar") [ "$mod, D, exec, rofi -show drun" + ", XF86AudioMute, exec, pamixer -t" "$mod, escape, exec, wlogout" "$mod, period, exec, killall rofi || rofi -show emoji -emoji-format '{emoji}' -modi emoji" ] ++ optionals (defaults.bar == "ags") [ - "$mod, D, exec, ags toggle-window applauncher" - "$mod, escape, exec, ags toggle-window powermenu" - "$mod SHIFT, R, exec, ags quit ; ags" + "$mod, D, exec, ags -b hypr -t applauncher" + "$mod, escape, exec, ags -b hypr -t powermenu" + "$mod SHIFT, R, exec, ags -b hypr --quit ; ags -b hypr" + ", Xf86AudioMute, exec, ags -b hypr -r 'volume.master.toggleMute(); indicator.display()'" ] ++ optionals (defaults.bar != "eww") [ - ", XF86AudioMute, exec, pamixer -t" ", Print, exec, grim -g '$(slurp)' - | swappy -f -" "$mod, V, exec, cliphist list | rofi -dmenu -p 'Clipboard' | cliphist decode | wl-copy" ] @@ -244,24 +236,20 @@ in { ", XF86AudioPrev, exec, playerctl previous" ]; - bindle = - [] - ++ optionals (defaults.bar == "ags") [ - ", XF86MonBrightnessUp, exec, ags run-js 'ags.Service.Brightness.screen += 0.02; ags.Service.Indicator.display()'" - ", XF86MonBrightnessDown, exec, ags run-js 'ags.Service.Brightness.screen -= 0.02; ags.Service.Indicator.display()'" - ", XF86AudioRaiseVolume, exec, ags run-js 'ags.Service.Audio.speaker.volume += 0.05; ags.Service.Indicator.speaker()'" - ", XF86AudioLowerVolume, exec, ags run-js 'ags.Service.Audio.speaker.volume -= 0.05; ags.Service.Indicator.speaker()'" - ]; + bindle = optionals (defaults.bar == "ags") [ + ", XF86MonBrightnessUp, exec, ags -b hypr -r 'brightness.screen += 0.05; indicator.display()'" + ", XF86MonBrightnessDown, exec, ags -b hypr -r 'brightness.screen -= 0.05; indicator.display()'" + ", XF86AudioRaiseVolume, exec, ags -b hypr -r 'audio.speaker.volume += 0.05; indicator.speaker()'" + ", XF86AudioLowerVolume, exec, ags -b hypr -r 'audio.speaker.volume -= 0.05; indicator.speaker()'" + ]; - bindl = - [] - ++ optionals (defaults.bar == "ags") [ - ", XF86AudioPlay, exec, ags run-js `ags.Service.Mpris.getPlayer()?.playPause()`" - ", XF86AudioStop, exec, ags run-js `ags.Service.Mpris.getPlayer()?.stop()`" - ", XF86AudioPause, exec, ags run-js `ags.Service.Mpris.getPlayer()?.pause()`" - ", XF86AudioPrev, exec, ags run-js `ags.Service.Mpris.getPlayer()?.previous()`" - ", XF86AudioNext, exec, ags run-js `ags.Service.Mpris.getPlayer()?.next()`" - ]; + bindl = optionals (defaults.bar == "ags") [ + ", XF86AudioPlay, exec, ags -b hypr -r 'mpris.players.pop()?.playPause()'" + ", XF86AudioStop, exec, ags -b hypr -r 'mpris.players.pop()?.stop()'" + ", XF86AudioPause, exec, ags -b hypr -r 'mpris.players.pop()?.pause()'" + ", XF86AudioPrev, exec, ags -b hypr -r 'mpris.players.pop()?.previous()'" + ", XF86AudioNext, exec, ags -b hypr -r 'mpris.players.pop()?.next()'" + ]; # mouse binds bindm = [ @@ -271,8 +259,7 @@ in { # hold to repeat action buttons binde = - [] - ++ optionals (defaults.bar == "eww") [ + optionals (defaults.bar == "eww") [ ", XF86AudioRaiseVolume, exec, ~/.config/eww/scripts/volume up" ", XF86AudioLowerVolume, exec, ~/.config/eww/scripts/volume down" ", XF86MonBrightnessUp, exec, ~/.config/eww/scripts/brightness up" @@ -286,7 +273,30 @@ in { ]; }; - extraConfig = '' + extraConfig = let + mapMonitors = builtins.concatStringsSep "\n" (imap0 (i: monitor: ''monitor=${monitor},${ + if monitor == "DP-1" + then "1920x1080@144" + else "preferred" + },${toString (i * 1920)}x0,1'') monitors); + + mapMonitorsToWs = builtins.concatStringsSep "\n" ( + builtins.genList ( + x: '' + workspace = ${toString (x + 1)}, monitor:${ + if (x + 1) <= 5 + then "${builtins.elemAt monitors 0} ${ + if (x + 1) == 1 + then ", default:true" + else "" + }" + else "${builtins.elemAt monitors 1}" + } + '' + ) + 10 + ); + in '' ${mapMonitors} ${optionalString (builtins.length monitors != 1) "${mapMonitorsToWs}"} diff --git a/home/isabel/programs/wm/hyprland/default.nix b/home/isabel/programs/wm/hyprland/default.nix index 535fa66b7..8bdfddbfc 100644 --- a/home/isabel/programs/wm/hyprland/default.nix +++ b/home/isabel/programs/wm/hyprland/default.nix @@ -4,32 +4,27 @@ osConfig, inputs', ... -}: -with lib; let - hyprpicker = inputs'.hyprpicker.packages.default; - hyprland-share-picker = inputs'.xdg-portal-hyprland.packages.xdg-desktop-portal-hyprland; +}: let + inherit (osConfig.modules) device usrEnv; - env = osConfig.modules.usrEnv; - device = osConfig.modules.device; - sys = osConfig.modules.system; - programs = osConfig.modules.programs; + acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; in { imports = [./config.nix]; - config = mkIf ((sys.video.enable) && (env.isWayland && (env.desktop == "Hyprland"))) { - home.packages = with pkgs; - [ - grim - hyprpicker - hyprland-share-picker - ] - ++ optionals (programs.nur.enable && programs.nur.bella) [ - nur.repos.bella.catppuccin-hyprland - ]; + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && lib.isWayland osConfig && usrEnv.desktop == "Hyprland") { + home.packages = with pkgs; [ + grim + inputs'.hyprpicker.packages.default + ]; + wayland.windowManager.hyprland = { enable = true; - systemdIntegration = true; - package = inputs'.hyprland.packages.default.override { - enableNvidiaPatches = (device.gpu == "nvidia") || (device.gpu == "hybrid-nv"); + package = inputs'.hyprland.packages.default; + enableNvidiaPatches = (device.gpu == "nvidia") || (device.gpu == "hybrid-nv"); + xwayland.enable = true; + + systemd = { + enable = true; + variables = ["--all"]; }; }; }; diff --git a/home/isabel/programs/wm/sway/config.nix b/home/isabel/programs/wm/sway/config.nix index d42564264..f5dd3cc13 100644 --- a/home/isabel/programs/wm/sway/config.nix +++ b/home/isabel/programs/wm/sway/config.nix @@ -1,84 +1,79 @@ { - lib, config, defaults, ... -}: let - inherit (lib) mkIf; -in { - config = mkIf (config.wayland.windowManager.sway.enable) { - wayland.windowManager.sway = { - config = { - modifier = "Mod4"; - workspaceAutoBackAndForth = true; - terminal = defaults.terminal; - menu = defaults.launcher; - defaultWorkspace = "workspace number 1"; +}: { + wayland.windowManager.sway = { + config = { + modifier = "Mod4"; + workspaceAutoBackAndForth = true; + terminal = defaults.terminal; + menu = defaults.launcher; + defaultWorkspace = "workspace number 1"; - keybindings = let - mod = config.wayland.windowManager.sway.config.modifier; - in { - # launchers - "${mod}+Return" = "exec ${defaults.terminal}"; - "${mod}+d" = "exec ${defaults.launcher}"; - "${mod}+b" = "exec ${defaults.browser}"; - "${mod}+e" = "exec ${defaults.fileManager}"; - "${mod}+o" = "exec obsidian"; + keybindings = let + mod = config.wayland.windowManager.sway.config.modifier; + in { + # launchers + "${mod}+Return" = "exec ${defaults.terminal}"; + "${mod}+d" = "exec ${defaults.launcher}"; + "${mod}+b" = "exec ${defaults.browser}"; + "${mod}+e" = "exec ${defaults.fileManager}"; + "${mod}+o" = "exec obsidian"; - "${mod}+l" = "exec swaylock"; - "${mod}+t" = "floating toggle"; - "Print" = "grim -g \"$(slurp)\""; - "${mod}+q" = "kill"; - }; + "${mod}+l" = "exec swaylock"; + "${mod}+t" = "floating toggle"; + "Print" = "grim -g \"$(slurp)\""; + "${mod}+q" = "kill"; + }; - window = { - titlebar = false; - hideEdgeBorders = "none"; - border = 2; - }; + window = { + titlebar = false; + hideEdgeBorders = "none"; + border = 2; + }; - gaps = { - smartBorders = "on"; - outer = 5; - inner = 5; - }; + gaps = { + smartBorders = "on"; + outer = 5; + inner = 5; + }; - startup = [{command = "dbus-update-activation-environment --systemd WAYLAND_DISPLAY DISPLAY";}]; + startup = [{command = "dbus-update-activation-environment --systemd WAYLAND_DISPLAY DISPLAY";}]; - input = { - "type:pointer" = { - accel_profile = "flat"; - pointer_accel = "0"; - }; - "type:touchpad" = { - middle_emulation = "enabled"; - natural_scroll = "enabled"; - tap = "enabled"; - }; + input = { + "type:pointer" = { + accel_profile = "flat"; + pointer_accel = "0"; + }; + "type:touchpad" = { + middle_emulation = "enabled"; + natural_scroll = "enabled"; + tap = "enabled"; }; - extraConfig = '' - set $ws1 1:一 - set $ws2 2:二 - set $ws3 3:三 - set $ws4 4:四 - set $ws5 5:五 - set $ws6 6:六 - set $ws7 7:七 - set $ws8 8:八 - set $ws9 9:九 - set $ws10 10:十 + }; + extraConfig = '' + set $ws1 1:一 + set $ws2 2:二 + set $ws3 3:三 + set $ws4 4:四 + set $ws5 5:五 + set $ws6 6:六 + set $ws7 7:七 + set $ws8 8:八 + set $ws9 9:九 + set $ws10 10:十 - for_window [window_role="PictureInPicture"] floating enable sticky enable - for_window [class="Pavucontrol"] floating enable + for_window [window_role="PictureInPicture"] floating enable sticky enable + for_window [class="Pavucontrol"] floating enable - corner_radius 5 - smart_corner_radius enable + corner_radius 5 + smart_corner_radius enable - blur enable - blur_passes 2 - blur_radius 4 - ''; - }; + blur enable + blur_passes 2 + blur_radius 4 + ''; }; }; } diff --git a/home/isabel/programs/wm/sway/default.nix b/home/isabel/programs/wm/sway/default.nix index e15fad9a6..3e3997ef4 100644 --- a/home/isabel/programs/wm/sway/default.nix +++ b/home/isabel/programs/wm/sway/default.nix @@ -1,10 +1,14 @@ -{lib, ...}: -with lib; let - env = osConfig.modules.usrEnv; - sys = osConfig.modules.system; +{ + lib, + osConfig, + ... +}: let + inherit (osConfig.modules) usrEnv; + + acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; in { imports = [./config.nix]; - config = mkIf ((sys.video.enable) && (env.isWayland && (env.desktop == "Sway"))) { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && lib.isWayland osConfig && usrEnv.desktop == "Sway") { wayland.windowManager.sway = { enable = true; package = null; diff --git a/home/isabel/services/default.nix b/home/isabel/services/default.nix index ac6ebb398..859966c66 100644 --- a/home/isabel/services/default.nix +++ b/home/isabel/services/default.nix @@ -1,7 +1,9 @@ _: { imports = [ - ./wayland # services that are wayland-only - ./x11 # services that are x11-only - ./shared # services that should be enabled regardless + ./shared # Always on services + ./wayland # wayland-only services + #./x11 # x11-only services + + ./nix-index.nix ]; } diff --git a/home/isabel/services/nix-index.nix b/home/isabel/services/nix-index.nix new file mode 100644 index 000000000..28f664db3 --- /dev/null +++ b/home/isabel/services/nix-index.nix @@ -0,0 +1,13 @@ +{inputs, ...}: { + imports = [inputs.nix-index-db.hmModules.nix-index]; + + config.programs = { + nix-index = { + enable = true; + + # link nix-index database to ~/.cache/nix-index + symlinkToCacheHome = true; + }; + nix-index-database.comma.enable = true; + }; +} diff --git a/home/isabel/services/shared/cloud/default.nix b/home/isabel/services/shared/cloud/default.nix new file mode 100644 index 000000000..026d35ba3 --- /dev/null +++ b/home/isabel/services/shared/cloud/default.nix @@ -0,0 +1,28 @@ +{ + lib, + osConfig, + pkgs, + ... +}: let + acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; +in { + config = lib.mkIf ((lib.isAcceptedDevice osConfig acceptedTypes) && (lib.isWayland osConfig)) { + /* + services = { + nextcloud-client.enable = true; + nextcloud-client.startInBackground = true; + }; + */ + + home.packages = [pkgs.nextcloud-client]; + + systemd.user.services.nextcloud = lib.mkGraphicalService { + Unit.Description = "Nextcloud client service"; + Service = { + ExecStart = "${pkgs.nextcloud-client}/bin/nextcloud --background"; + Restart = "always"; + Slice = "background.slice"; + }; + }; + }; +} diff --git a/home/isabel/services/shared/default.nix b/home/isabel/services/shared/default.nix index 31d3e81a2..eb3a0c339 100644 --- a/home/isabel/services/shared/default.nix +++ b/home/isabel/services/shared/default.nix @@ -1,5 +1,6 @@ _: { imports = [ + ./cloud ./polkit ./kdeconnect.nix diff --git a/home/isabel/services/shared/kdeconnect.nix b/home/isabel/services/shared/kdeconnect.nix index 0949295b5..9210fc233 100644 --- a/home/isabel/services/shared/kdeconnect.nix +++ b/home/isabel/services/shared/kdeconnect.nix @@ -2,14 +2,14 @@ lib, osConfig, ... -}: -with lib; let - device = osConfig.modules.device; +}: let + inherit (osConfig.modules.system) video; + inherit (lib) mkIf isAcceptedDevice; + acceptedTypes = ["desktop" "laptop" "hybrid"]; - sys = osConfig.modules.system; in { - config = mkIf (builtins.elem device.type acceptedTypes && sys.video.enable) { - # connect my phone + config = mkIf ((isAcceptedDevice osConfig acceptedTypes) && video.enable) { + # connect my phone, please its so inconsistant services.kdeconnect = { enable = true; indicator = true; diff --git a/home/isabel/services/shared/polkit/default.nix b/home/isabel/services/shared/polkit/default.nix index cef89efd3..4f6e23078 100644 --- a/home/isabel/services/shared/polkit/default.nix +++ b/home/isabel/services/shared/polkit/default.nix @@ -3,18 +3,19 @@ osConfig, pkgs, ... -}: -with lib; let - device = osConfig.modules.device; - video = osConfig.modules.system.video; - env = osConfig.modules.usrEnv; - +}: let + inherit (lib) mkIf isAcceptedDevice mkGraphicalService; + inherit (osConfig.modules.system) video; acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; in { - config = mkIf ((builtins.elem device.type acceptedTypes) && (video.enable && env.isWayland)) { + config = mkIf ((isAcceptedDevice osConfig acceptedTypes) && video.enable) { # gnome polkit agent - systemd.user.services.polkit-gnome-authentication-agent-1 = lib.mkGraphicalService { - Service.ExecStart = "${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1"; + # systemd.user.services.polkit-gnome-authentication-agent-1 = mkGraphicalService { + # Service.ExecStart = "${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1"; + + # pantheon alternate, probaly runs lighter + systemd.user.services.polkit-pantheon-authentication-agent-1 = mkGraphicalService { + Service.ExecStart = "${pkgs.pantheon.pantheon-agent-polkit}/libexec/policykit-1-pantheon/io.elementary.desktop.agent-polkit"; }; }; } diff --git a/home/isabel/services/shared/rnnoise.nix b/home/isabel/services/shared/rnnoise.nix index 000795e44..70a76c366 100644 --- a/home/isabel/services/shared/rnnoise.nix +++ b/home/isabel/services/shared/rnnoise.nix @@ -4,14 +4,13 @@ pkgs, ... }: let - inherit (lib) mkIf; - inherit (osConfig.modules) device; + inherit (lib) mkIf isAcceptedDevice; json = pkgs.formats.json {}; acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; in { - config = mkIf (builtins.elem device.type acceptedTypes) { + config = mkIf (isAcceptedDevice osConfig acceptedTypes) { xdg.configFile."pipewire/pipewire.conf.d/99-input-denoising.conf" = { source = json.generate "99-input-denoising.conf" { "context.modules" = [ diff --git a/home/isabel/services/shared/tray.nix b/home/isabel/services/shared/tray.nix index 528d8385a..8dd3eebb7 100644 --- a/home/isabel/services/shared/tray.nix +++ b/home/isabel/services/shared/tray.nix @@ -3,10 +3,10 @@ lib, ... }: let - env = osConfig.modules.usrEnv; + inherit (lib) mkIf isAcceptedDevice; + acceptedTypes = ["lite" "hybrid" "laptop" "desktop"]; in { - config = (lib.mkIf env.useHomeManager) { - # fake a tray to let apps start + config = mkIf (isAcceptedDevice osConfig acceptedTypes) { # https://github.com/nix-community/home-manager/issues/2064 systemd.user.targets.tray = { Unit = { diff --git a/home/isabel/services/wayland/clipboard.nix b/home/isabel/services/wayland/clipboard.nix index 194c9952b..ea1cdd3fd 100644 --- a/home/isabel/services/wayland/clipboard.nix +++ b/home/isabel/services/wayland/clipboard.nix @@ -3,20 +3,16 @@ pkgs, osConfig, ... -}: -with lib; let - device = osConfig.modules.device; - video = osConfig.modules.system.video; - env = osConfig.modules.usrEnv; - +}: let + inherit (lib) mkIf isAcceptedDevice isWayland mkGraphicalService getExe; acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; in { - config = mkIf ((builtins.elem device.type acceptedTypes) && (video.enable && env.isWayland)) { + config = mkIf ((isAcceptedDevice osConfig acceptedTypes) && (isWayland osConfig)) { systemd.user.services = { - cliphist = lib.mkGraphicalService { + cliphist = mkGraphicalService { Unit.Description = "Clipboard history service"; Service = { - ExecStart = "${pkgs.wl-clipboard}/bin/wl-paste --watch ${lib.getExe pkgs.cliphist} store"; + ExecStart = "${pkgs.wl-clipboard}/bin/wl-paste --watch ${getExe pkgs.cliphist} store"; Restart = "always"; }; }; diff --git a/home/isabel/services/wayland/default.nix b/home/isabel/services/wayland/default.nix index c884bc22d..dd1e033f2 100644 --- a/home/isabel/services/wayland/default.nix +++ b/home/isabel/services/wayland/default.nix @@ -1,6 +1,5 @@ _: { imports = [ ./screenlock - #./clipboard.nix ]; } diff --git a/home/isabel/services/wayland/screenlock/gtklock.nix b/home/isabel/services/wayland/screenlock/gtklock.nix index 57844e9e9..70ac5104a 100644 --- a/home/isabel/services/wayland/screenlock/gtklock.nix +++ b/home/isabel/services/wayland/screenlock/gtklock.nix @@ -6,14 +6,10 @@ defaults, ... }: let - inherit (lib) mkIf; - dev = osConfig.modules.device; - vid = osConfig.modules.system.video; - env = osConfig.modules.usrEnv; - + inherit (lib) mkIf isAcceptedDevice isWayland; acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; in { - config = mkIf ((builtins.elem dev.type acceptedTypes && defaults.screenLock == "gtklock") && (vid.enable && env.isWayland)) { + config = mkIf ((isAcceptedDevice osConfig acceptedTypes) && (isWayland osConfig) && defaults.screenLocker == "gtklock") { programs.gtklock = { enable = true; package = pkgs.gtklock; diff --git a/home/isabel/services/wayland/screenlock/swaylock.nix b/home/isabel/services/wayland/screenlock/swaylock.nix index fb9d69cc0..05902e341 100644 --- a/home/isabel/services/wayland/screenlock/swaylock.nix +++ b/home/isabel/services/wayland/screenlock/swaylock.nix @@ -6,15 +6,10 @@ defaults, ... }: let - inherit (lib) mkIf; - - dev = osConfig.modules.device; - vid = osConfig.modules.system.video; - env = osConfig.modules.usrEnv; - + inherit (lib) mkIf isWayland isAcceptedDevice; acceptedTypes = ["desktop" "laptop" "lite" "hybrid"]; in { - config = mkIf ((builtins.elem dev.type acceptedTypes && defaults.screenLock == "swaylock") && (vid.enable && env.isWayland)) { + config = mkIf ((isAcceptedDevice osConfig acceptedTypes) && (isWayland osConfig) && defaults.screenLocker == "swaylock") { home.packages = with pkgs; [swaylock-effects]; programs.swaylock = { diff --git a/home/isabel/shells/default.nix b/home/isabel/shells/default.nix deleted file mode 100644 index b901e1c6f..000000000 --- a/home/isabel/shells/default.nix +++ /dev/null @@ -1,3 +0,0 @@ -{...}: { - home.file."shells/" = {source = ../shells;}; -} diff --git a/home/isabel/shells/docker.nix b/home/isabel/shells/docker.nix deleted file mode 100644 index d394e9223..000000000 --- a/home/isabel/shells/docker.nix +++ /dev/null @@ -1,11 +0,0 @@ -{ - pkgs ? import {}, - extras ? "", -}: -pkgs.mkShell { - nativeBuildInputs = with pkgs; [ - docker - docker-compose - extras - ]; -} diff --git a/home/isabel/shells/node.nix b/home/isabel/shells/node.nix deleted file mode 100644 index 593c31781..000000000 --- a/home/isabel/shells/node.nix +++ /dev/null @@ -1,11 +0,0 @@ -{ - pkgs ? import {}, - extras ? "", -}: -pkgs.mkShell { - nativeBuildInputs = with pkgs; [ - nodejs - nodePackages.typescript - extras - ]; -} diff --git a/home/isabel/shells/py.nix b/home/isabel/shells/py.nix deleted file mode 100644 index 105247bf7..000000000 --- a/home/isabel/shells/py.nix +++ /dev/null @@ -1,11 +0,0 @@ -{ - pkgs ? import {}, - extras ? "", -}: -pkgs.mkShell { - nativeBuildInputs = with pkgs; [ - python - python3 - extras - ]; -} diff --git a/home/isabel/shells/rust.nix b/home/isabel/shells/rust.nix deleted file mode 100644 index 3d72bcc0a..000000000 --- a/home/isabel/shells/rust.nix +++ /dev/null @@ -1,20 +0,0 @@ -{ - pkgs ? import {}, - extras ? "", -}: -pkgs.mkShell { - buildInputs = with pkgs; [ - rustc - rustfmt - sccache - rust-analyzer - cargo - openssl - extras - ]; - - shellHook = '' - export OPENSSL_DIR="${pkgs.openssl.dev}" - export OPENSSL_LIB_DIR="${pkgs.openssl.out}/lib" - ''; -} diff --git a/home/isabel/shells/spawnshell.sh b/home/isabel/shells/spawnshell.sh deleted file mode 100755 index 289238eeb..000000000 --- a/home/isabel/shells/spawnshell.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -if [[ $# -gt 1 ]]; then - extras="${*:2}" - nix-shell ~/shells/"$1".nix --arg extras "with import {}; [ $extras ]" -else - nix-shell ~/shells/"$1".nix -fi diff --git a/home/isabel/system/default.nix b/home/isabel/system/default.nix index 77695f7a1..083ed5459 100644 --- a/home/isabel/system/default.nix +++ b/home/isabel/system/default.nix @@ -1,5 +1,6 @@ _: { imports = [ + ./env.nix ./gpg.nix ./ssh.nix ./xdg.nix diff --git a/home/isabel/system/env.nix b/home/isabel/system/env.nix new file mode 100644 index 000000000..83e1f6a65 --- /dev/null +++ b/home/isabel/system/env.nix @@ -0,0 +1,15 @@ +{ + osConfig, + defaults, + ... +}: { + home.sessionVariables = { + EDITOR = defaults.editor; + GIT_EDITOR = defaults.editor; + VISUAL = defaults.editor; + TERMINAL = defaults.terminal; + SYSTEMD_PAGERSECURE = "true"; + PAGER = "less -FR"; + FLAKE = "${osConfig.modules.system.flakePath}"; + }; +} diff --git a/home/isabel/system/gpg.nix b/home/isabel/system/gpg.nix index 72bc1d7c4..0c0c8d2d7 100644 --- a/home/isabel/system/gpg.nix +++ b/home/isabel/system/gpg.nix @@ -5,7 +5,7 @@ inputs, ... }: let - sys = osConfig.modules.system; + inherit (osConfig.modules.system) video; in { imports = [inputs.sops.homeManagerModules.sops]; @@ -13,7 +13,7 @@ in { gpg-agent = { enable = true; pinentryFlavor = - if (sys.video.enable) + if (video.enable) then "gnome3" else "curses"; enableSshSupport = true; @@ -25,7 +25,7 @@ in { }; }; - # Allow manually restarting gpg-agent in case of failure + # Allow manually restarting gpg-agent if it fails systemd.user.services.gpg-agent.Unit.RefuseManualStart = lib.mkForce false; sops.gnupg.home = config.programs.gpg.homedir; diff --git a/home/isabel/system/ssh.nix b/home/isabel/system/ssh.nix index f7f46e20b..5d3385cfa 100644 --- a/home/isabel/system/ssh.nix +++ b/home/isabel/system/ssh.nix @@ -1,15 +1,21 @@ -{pkgs, ...}: { - home.packages = with pkgs; [cloudflared]; +_: { + # {pkgs, ...}: { + # home.packages = with pkgs; [cloudflared]; programs = { ssh = { enable = true; hashKnownHosts = true; compression = true; - extraConfig = '' - Host * - Port 22 - ''; - matchBlocks = { + matchBlocks = let + base = { + user = "isabel"; + }; + template = + base + // { + identityFile = "~/.ssh/nixos"; + }; + in { # git clients "aur.archlinux.org" = { user = "aur"; @@ -30,31 +36,34 @@ identityFile = "~/.ssh/openvpn"; }; - #"edalyn" = { - # hostname = "141.147.113.225"; - # user = "ubuntu"; - # identityFile = "~/.ssh/edalyn"; - #}; - - #"luz" = { - # hostname = "144.21.55.221"; - # user = "ubuntu"; - # identityFile = "~/.ssh/luz"; - #}; - "king" = { hostname = "150.230.117.215"; user = "ubuntu"; identityFile = "~/.ssh/king"; }; - "bernie" = { - hostname = "143.47.240.116"; - user = "isabel"; - identityFile = "~/.ssh/bernie"; - }; + "amity" = + base + // { + hostname = "143.47.240.116"; + identityFile = "~/.ssh/amity"; + }; + + # hetzner cloud vps + "bernie" = + template + // { + hostname = "91.107.198.173"; + }; # my local servers / clients + "hydra" = + template + // { + hostname = "192.168.86.3"; + }; + + /* "alpha" = { hostname = "192.168.86.4"; user = "isabel"; @@ -67,12 +76,7 @@ identityFile = "~/.ssh/alpha"; proxyCommand = "cloudflared access ssh --hostname %h"; }; - - "hydra" = { - hostname = "192.168.86.3"; - user = "isabel"; - identityFile = "~/.ssh/hydra"; - }; + */ }; }; }; diff --git a/home/isabel/system/xdg.nix b/home/isabel/system/xdg.nix index b76385526..5e28dfa05 100644 --- a/home/isabel/system/xdg.nix +++ b/home/isabel/system/xdg.nix @@ -3,7 +3,8 @@ pkgs, ... }: let - browser = ["chromium.desktop"]; + # browser = ["chromium.desktop"]; + browser = ["Schizofox.desktop"]; zathura = ["org.pwmt.zathura.desktop"]; filemanager = ["thunar.desktop"]; diff --git a/home/isabel/themes/global.nix b/home/isabel/themes/global.nix index 6a73a8329..8e974afa0 100644 --- a/home/isabel/themes/global.nix +++ b/home/isabel/themes/global.nix @@ -1,14 +1,12 @@ {osConfig, ...}: let cfg = osConfig.modules.style; in { - # cursor theme - home = { - pointerCursor = { - package = cfg.pointerCursor.package; - name = "${cfg.pointerCursor.name}"; - size = cfg.pointerCursor.size; - gtk.enable = true; - x11.enable = true; - }; + # pointer / cursor theming + home.pointerCursor = { + package = cfg.pointerCursor.package; + name = "${cfg.pointerCursor.name}"; + size = cfg.pointerCursor.size; + gtk.enable = true; + x11.enable = true; }; } diff --git a/home/isabel/themes/gtk.nix b/home/isabel/themes/gtk.nix index 85d69bd9d..d7e995a20 100644 --- a/home/isabel/themes/gtk.nix +++ b/home/isabel/themes/gtk.nix @@ -12,7 +12,7 @@ acceptedTypes = ["laptop" "desktop" "hybrid" "lite"]; in { - config = mkIf (builtins.elem device.type acceptedTypes && (sys.video.enable)) { + config = mkIf (builtins.elem device.type acceptedTypes && sys.video.enable) { xdg.systemDirs.data = let schema = pkgs.gsettings-desktop-schemas; in ["${schema}/share/gsettings-schemas/${schema.name}"]; @@ -28,7 +28,7 @@ in { # set GTK theme to the name specified by the gtk package GTK_THEME = "${cfg.gtk.theme.name}"; - # gtk applications should use filepickers specified by xdg + # gtk applications should use xdg specified settings GTK_USE_PORTAL = "${with lib; toString (boolToNum cfg.gtk.usePortal)}"; }; }; diff --git a/home/isabel/themes/qt.nix b/home/isabel/themes/qt.nix index 19d52b403..7a57e12db 100644 --- a/home/isabel/themes/qt.nix +++ b/home/isabel/themes/qt.nix @@ -4,7 +4,7 @@ osConfig, ... }: let - inherit (lib) mkIf optionalAttrs; + inherit (lib) mkIf optionals; inherit (osConfig.modules) device; sys = osConfig.modules.system; cfg = osConfig.modules.style; @@ -12,64 +12,63 @@ acceptedTypes = ["laptop" "desktop" "hybrid" "lite"]; in { config = mkIf (builtins.elem device.type acceptedTypes && sys.video.enable) { - xdg.configFile."kdeglobals".source = cfg.qt.kdeglobals.source; + xdg.configFile = { + "kdeglobals".source = cfg.qt.kdeglobals.source; + + "Kvantum/kvantum.kvconfig".source = (pkgs.formats.ini {}).generate "kvantum.kvconfig" { + General.theme = "catppuccin"; + Applications.catppuccin = '' + qt5ct, org.kde.dolphin, org.kde.kalendar, org.qbittorrent.qBittorrent, hyprland-share-picker, dolphin-emu, Nextcloud, nextcloud, cantata, org.kde.kid3-qt + ''; + }; + "Kvantum/catppuccin/catppuccin.kvconfig".source = builtins.fetchurl { + url = "https://raw.githubusercontent.com/catppuccin/Kvantum/main/src/Catppuccin-Mocha-Sapphire/Catppuccin-Mocha-Sapphire.kvconfig"; + sha256 = "0n9f5hysr4k1sf9fd3sgd9fvqwrxrpcvj6vajqmb5c5ji8nv2w3c"; + }; + + "Kvantum/catppuccin/catppuccin.svg".source = builtins.fetchurl { + url = "https://raw.githubusercontent.com/catppuccin/Kvantum/main/src/Catppuccin-Mocha-Sapphire/Catppuccin-Mocha-Sapphire.svg"; + sha256 = "1hq9h34178h0d288hgwb0ngqnixz24m9lk0ahc4dahwqn77fndwf"; + }; + }; qt = { enable = true; - platformTheme = mkIf cfg.forceGtk "gtk"; # just an override for QT_QPA_PLATFORMTHEME, takes "gtk" or "gnome" - style = { + platformTheme = mkIf cfg.forceGtk "gtk"; # just an override for QT_QPA_PLATFORMTHEME, takes “gtk”, “gnome”, “qtct” or “kde” + style = mkIf (!cfg.forceGtk) { name = "${cfg.qt.theme.name}"; - package = cfg.qt.theme.package; + inherit (cfg.qt.theme) package; }; }; - # credits: yavko - # catppuccin theme for qt-apps - home.packages = with pkgs; [ - qt5.qttools - qt6Packages.qtstyleplugin-kvantum - libsForQt5.qtstyleplugin-kvantum - libsForQt5.qt5ct - breeze-icons - - # add theme package to path just in case - cfg.qt.theme.package - ]; + home.packages = with pkgs; + [ + libsForQt5.qt5ct + breeze-icons - home.sessionVariables = - { - #QT_QPA_PLATFORMTHEME = "kvantum"; # can't be used alongside kvantum, nix above knows why - #QT_STYLE_OVERRIDE = "kvantum"; - QT_AUTO_SCREEN_SCALE_FACTOR = "1"; - QT_QPA_PLATFORM = "wayland;xcb"; - QT_WAYLAND_DISABLE_WINDOWDECORATION = "1"; - DISABLE_QT5_COMPAT = "0"; + # add theme package to path just in case + cfg.qt.theme.package + ] + ++ optionals cfg.useKvantum [ + qt6Packages.qtstyleplugin-kvantum + libsForQt5.qtstyleplugin-kvantum + ]; - # tell calibre to use the dark theme, because the light one hurts my eyes - CALIBRE_USE_DARK_PALETTE = "1"; - } - // optionalAttrs cfg.useKvantum { - xdg.configFile."Kvantum/catppuccin/catppuccin.kvconfig".source = builtins.fetchurl { - url = "https://raw.githubusercontent.com/catppuccin/Kvantum/main/src/Catppuccin-Mocha-Blue/Catppuccin-Mocha-Blue.kvconfig"; - sha256 = ""; - }; + home.sessionVariables = { + # scaling - 1 means no scaling + QT_AUTO_SCREEN_SCALE_FACTOR = "1"; - xdg.configFile."Kvantum/catppuccin/catppuccin.svg".source = builtins.fetchurl { - url = "https://raw.githubusercontent.com/catppuccin/Kvantum/main/src/Catppuccin-Mocha-Blue/Catppuccin-Mocha-Blue.svg"; - sha256 = ""; - }; + # use wayland as the default backend, fallback to xcb if wayland is not available + QT_QPA_PLATFORM = "wayland;xcb"; - xdg.configFile."Kvantum/kvantum.kvconfig".source = (pkgs.formats.ini {}).generate "kvantum.kvconfig" { - General.Theme = "Catppuccin-Mocha-Mauve"; - }; + # disable window decorations everywhere + QT_WAYLAND_DISABLE_WINDOWDECORATION = "1"; - xdg.configFile."Kvantum/kvantum.kvconfig".text = '' - [General] - theme=catppuccin + # remain backwards compatible with qt5 + DISABLE_QT5_COMPAT = "0"; - [Applications] - catppuccin=qt5ct, org.kde.dolphin, org.kde.kalendar, org.qbittorrent.qBittorrent, hyprland-share-picker, dolphin-emu, Nextcloud, nextcloud - ''; - }; + # tell calibre to use the dark theme + CALIBRE_USE_DARK_PALETTE = "1"; + }; }; } diff --git a/hosts/amatarasu/default.nix b/hosts/amatarasu/default.nix index c7c65e705..43826e00a 100644 --- a/hosts/amatarasu/default.nix +++ b/hosts/amatarasu/default.nix @@ -21,11 +21,11 @@ in { }; system = { mainUser = "isabel"; - hostname = "amatarasu"; boot = { loader = "systemd-boot"; + secureBoot = false; plymouth = { enable = true; withThemes = true; @@ -35,11 +35,16 @@ in { loadRecommendedModules = true; }; + fs = ["ext4" "vfat"]; video.enable = true; sound.enable = true; bluetooth.enable = false; printing.enable = false; + security = { + auditd.enable = true; + }; + networking = { optimizeTcp = true; }; @@ -57,32 +62,33 @@ in { desktop = "Hyprland"; useHomeManager = true; }; - services = { - smb = { - enable = true; - recive = { - media = true; - general = true; - }; - }; - photoprism.enable = true; - vscode-server.enable = true; - }; + programs = { git.signingKey = "7F2F6BD6997FCDF7"; - cli.enable = true; + cli = { + enable = true; + modernShell.enable = true; + }; + tui.enable = true; gui.enable = true; - default = { + zathura.enable = true; + + defaults = { bar = "ags"; }; + }; - nur = { - enable = true; - bella = true; - nekowinston = true; + services = { + smb = { + enable = false; + recive = { + media = false; + general = false; + }; }; + vscode-server.enable = true; }; }; diff --git a/hosts/amatarasu/hardware-configuration.nix b/hosts/amatarasu/hardware-configuration.nix index 4e8613ff6..8a56d3107 100644 --- a/hosts/amatarasu/hardware-configuration.nix +++ b/hosts/amatarasu/hardware-configuration.nix @@ -1,6 +1,3 @@ -# Do not modify this file! It was generated by ‘nixos-generate-config’ -# and may be overwritten by future invocations. Please make changes -# to /etc/nixos/configuration.nix instead. { config, lib, diff --git a/hosts/bernie/default.nix b/hosts/bernie/default.nix index dbd0539ed..39a5c56c0 100644 --- a/hosts/bernie/default.nix +++ b/hosts/bernie/default.nix @@ -1,93 +1,63 @@ -{ - lib, - config, - ... -}: { - imports = [./hardware-configuration.nix]; - config = { - modules = { - device = { - type = "server"; - cpu = null; - gpu = null; - hasTPM = false; - hasBluetooth = false; - hasSound = false; +_: { + imports = [ + ./hardware-configuration.nix + ./mount.nix + ./overrides.nix + ./services.nix + ]; + + config.modules = { + device = { + type = "server"; + cpu = "amd"; + gpu = null; + hasTPM = false; + hasBluetooth = false; + hasSound = false; + }; + system = { + mainUser = "isabel"; + hostname = "bernie"; + + boot = { + loader = "grub"; + enableKernelTweaks = true; + enableInitrdTweaks = true; + loadRecommendedModules = true; }; - system = { - mainUser = "isabel"; - - hostname = "bernie"; - - boot = { - loader = "grub"; - device = lib.mkForce "/dev/sda15"; - enableKernelTweaks = true; - enableInitrdTweaks = true; - loadRecommendedModules = true; - }; - video.enable = false; - sound.enable = false; - bluetooth.enable = false; - printing.enable = false; + fs = ["vfat" "exfat" "ext4"]; + video.enable = false; + sound.enable = false; + bluetooth.enable = false; + printing.enable = false; - networking = { - optimizeTcp = false; - }; - - virtualization = { - enable = true; - docker.enable = true; - qemu.enable = false; - podman.enable = false; - distrobox.enable = false; - }; - }; - usrEnv = { - isWayland = false; - useHomeManager = true; + networking = { + optimizeTcp = false; }; - services = { - smb = { - enable = true; - }; - vscode-server.enable = true; - mailserver.enable = true; - gitea.enable = true; - vaultwarden.enable = true; - }; - programs = { - git.signingKey = ""; - - cli.enable = true; - gui.enable = false; - nur = { - enable = true; - bella = true; - nekowinston = true; - }; + virtualization = { + enable = true; + docker.enable = false; + qemu.enable = false; + podman.enable = false; + distrobox.enable = false; }; }; + usrEnv = { + isWayland = false; + useHomeManager = true; + }; - zramSwap.enable = true; - services.openssh.enable = true; - users.users.root.openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQhSDXRDS5ABDyCPOZ2B3bl455Mlzb32vmofdkXJCNXW98jUeCyaZk8XHRta06KeADFMvpwDEzjGz6Zb+NJIfMkh20mVdOpTHrA80cER1F2SlNf9fmZIgOyCzSUOSGqXHsWppikHmKzv1hPifQYoqWdRXN7bD9Jk5JjgxGcaXkICcV93s/tRy5Yl5l5LhM00fUDXUF85xnmqU3Ujepx0gknE0qaqgT+kFRe0hy7HIkjrEjMqy5nfHFlJG/XAxrHKK9p/BvvCgO/xiRimK2UgfH/5jml20EytVeZ6fIAeyVLvWA/FtLyaafoLqmETV6BhUnk8PtdAxjGQTQXZmUOv2D0Lvmxo1GqjYVPOfhINBprUaRwxIFM57SpwmXmGVWOlyTgTtBoPewUQ/QwT5cVV+a8ASeEhrFB4TzHxK4RM8++zL0eVtESW+L+/rsmfUHIIEXnLvVmnb8t0AWpWxQWaEe7YaNS9VNtm6gK0wl12PZXqN5K4eCXIyrsCbUdaldnts= root" - ]; + programs = { + git.signingKey = "B4D9D513B1560D99"; - boot = { - growPartition = !config.boot.initrd.systemd.enable; - kernelParams = ["net.ifnames=0"]; - kernel = { - sysctl = { - "net.ipv4.ip_forward" = true; - "net.ipv6.conf.all.forwarding" = true; - }; + cli = { + enable = true; + modernShell.enable = true; }; + tui.enable = true; + gui.enable = false; }; - - nix.settings.system-features = ["nixos-test" "benchmark" "big-parallel" "kvm" "gccarch-armv8-a"]; }; } diff --git a/hosts/bernie/hardware-configuration.nix b/hosts/bernie/hardware-configuration.nix index 005bed96a..3dc12bddc 100644 --- a/hosts/bernie/hardware-configuration.nix +++ b/hosts/bernie/hardware-configuration.nix @@ -1,34 +1,25 @@ { lib, + config, modulesPath, ... }: { imports = [(modulesPath + "/profiles/qemu-guest.nix")]; - - boot.initrd.availableKernelModules = ["xhci_pci" "virtio_pci" "virtio_scsi" "usbhid"]; - boot.initrd.kernelModules = []; - boot.kernelModules = []; - boot.extraModulePackages = []; - + boot.initrd.availableKernelModules = ["ata_piix" "uhci_hcd" "xen_blkfront" "vmw_pvscsi"]; + boot.initrd.kernelModules = ["nvme"]; + boot.kernelModules = ["kvm-amd"]; fileSystems."/" = { - device = "/dev/disk/by-uuid/de867c31-4437-4638-89f2-a345197bcb18"; + device = "/dev/sda1"; fsType = "ext4"; }; - fileSystems."/boot" = { - device = "/dev/disk/by-uuid/AF75-5E6E"; - fsType = "vfat"; - }; - - swapDevices = []; - # Enables DHCP on each ethernet and wireless interface. In case of scripted networking # (the default) this is the recommended approach. When using systemd-networkd it's # still possible to use this option, but it's recommended to use it in conjunction # with explicit per-interface declarations with `networking.interfaces..useDHCP`. networking.useDHCP = lib.mkDefault true; - # networking.interfaces.enp0s6.useDHCP = lib.mkDefault true; + # networking.interfaces.ens3.useDHCP = lib.mkDefault true; - nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux"; - powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand"; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; } diff --git a/hosts/bernie/mount.nix b/hosts/bernie/mount.nix new file mode 100644 index 000000000..7d0139e55 --- /dev/null +++ b/hosts/bernie/mount.nix @@ -0,0 +1,6 @@ +_: { + fileSystems."/srv/storage" = { + device = "/dev/disk/by-id/scsi-0HC_Volume_37980392"; + fsType = "ext4"; + }; +} diff --git a/hosts/bernie/overrides.nix b/hosts/bernie/overrides.nix new file mode 100644 index 000000000..1bd2f64dd --- /dev/null +++ b/hosts/bernie/overrides.nix @@ -0,0 +1,31 @@ +{ + lib, + config, + ... +}: { + config = { + services.smartd.enable = lib.mkForce false; # Unavailable - device lacks SMART capability. + + boot = { + growPartition = !config.boot.initrd.systemd.enable; + kernelParams = ["net.ifnames=0"]; + kernel = { + sysctl = { + "net.ipv4.ip_forward" = true; + "net.ipv6.conf.all.forwarding" = true; + }; + }; + + loader.grub = { + enable = true; + useOSProber = lib.mkForce false; + efiSupport = lib.mkForce false; + enableCryptodisk = false; + theme = null; + backgroundColor = null; + splashImage = null; + device = lib.mkForce "/dev/sda"; + }; + }; + }; +} diff --git a/hosts/bernie/services.nix b/hosts/bernie/services.nix new file mode 100644 index 000000000..a868a6c97 --- /dev/null +++ b/hosts/bernie/services.nix @@ -0,0 +1,30 @@ +_: { + modules.services = { + nextcloud.enable = true; + vscode-server.enable = false; + miniflux.enable = false; + matrix.enable = true; + forgejo.enable = true; + vaultwarden.enable = true; + isabelroses-web.enable = true; + nginx.enable = true; + cloudflared.enable = false; + + mailserver = { + enable = true; + rspamd-web.enable = false; + }; + + monitoring = { + grafana.enable = true; + prometheus.enable = true; + }; + + database = { + mysql.enable = false; + mongodb.enable = false; + postgresql.enable = true; + redis.enable = true; + }; + }; +} diff --git a/hosts/beta/default.nix b/hosts/beta/default.nix index e95cc4918..72778b2ee 100644 --- a/hosts/beta/default.nix +++ b/hosts/beta/default.nix @@ -1,8 +1,4 @@ -{ - lib, - config, - ... -}: { +{config, ...}: { imports = [./hardware-configuration.nix]; config = { modules = { @@ -16,7 +12,6 @@ }; system = { mainUser = "isabel"; - hostname = "beta"; boot = { @@ -47,24 +42,20 @@ isWayland = false; useHomeManager = true; }; - services = { - smb = { - enable = true; - }; - vscode-server.enable = true; - mailserver.enable = true; - }; + programs = { git.signingKey = ""; cli.enable = true; gui.enable = false; + }; - nur = { + services = { + smb = { enable = true; - bella = true; - nekowinston = true; }; + vscode-server.enable = true; + mailserver.enable = true; }; }; diff --git a/hosts/default.nix b/hosts/default.nix index 8cdaed8fa..f39893929 100644 --- a/hosts/default.nix +++ b/hosts/default.nix @@ -7,73 +7,82 @@ inherit (self) inputs; inherit (lib) concatLists mkNixosSystem mkNixosIso; - modulePath = ../modules; + # home manager modules from inputs + hm = inputs.home-manager.nixosModules.home-manager; + cat = inputs.catppuccin.nixosModules.catppuccin; - # common modules, to be shared across all systems - commonModules = modulePath + /common; # the path where common modules reside - core = commonModules + /core; # the self-proclaimed sane defaults for all my systems - options = commonModules + /options; # the module that provides the options for my system configuration - secrets = commonModules + /secrets; + # modules + modulePath = ../modules; # the base module path + options = modulePath + /options; # the module options for quick configuration - # system types, split up per system - deviceType = commonModules + /types; # the path where device type modules reside - server = deviceType + /server; # for devices that are of the server type - provides online services - laptop = deviceType + /laptop; # for devices that are of the laptop type - provides power optimizations - workstation = deviceType + /workstation; # for devices that are of workstation type - any device that is for daily use - hybrid = [server laptop]; + # common modules, these are shared across all systems + commonModules = modulePath + /common; # the base directory for the common module + core = commonModules + /core; # defaults for all systems + secrets = commonModules + /secrets; # shhh - # extra modules, likely optional but possibly critical - extraModules = modulePath + /extra; # the path where extra modules reside - sharedModules = extraModules + /shared; # shared modules + # hardware types, providing improved defaults and system preformance improvements + deviceType = commonModules + /types; # the base directory for the types module + server = deviceType + /server; # for server type configurations + laptop = deviceType + /laptop; # for laptop type configurations + desktop = deviceType + /desktop; # for desktop type configurations + workstation = deviceType + /workstation; # for server type configurations + #hybrid = [server laptop]; # combine the server and laptop configurations for the best of both worlds - ## home-manager ## - home = ../home; # home-manager configurations for hosts that need home-manager - homes = [hm home]; # combine hm flake input and the home module to be imported together + # extra modules + extraModules = modulePath + /extra; # the base directory for the extra module + sharedModules = extraModules + /shared; # the base directory for the shared module - ## flake inputs ## - hm = inputs.home-manager.nixosModules.home-manager; # home-manager nixos module - cat = inputs.catppuccin.nixosModules.catppuccin; + ## home-manager + home = ../home; # home-manager configurations, used if hm is enabled + homes = [hm home]; # combine hm input module and the home module, confiuration modules - # a list of shared modules that ALL systems need + # a list of shared modules shared = [ - core # the "sane" default shared across systems - options - sharedModules - cat # for the quick themeing - secrets + core # default shared across all system configuratons + options # amazing quick settings module + sharedModules # sharing is careing, this mainly contains: hm and nixos (if any) modules + cat # catppucin for the quick themeing + secrets # shh ]; - # extraSpecialArgs that all hosts need + # extraSpecialArgs that are on all machines sharedArgs = {inherit inputs self lib;}; in { - # fuck nvidia - Linus "the linux" Torvalds - amatarasu = mkNixosSystem { + hydra = mkNixosSystem { inherit withSystem; system = "x86_64-linux"; modules = [ - ./amatarasu + ./hydra workstation + laptop ] - ++ concatLists [shared homes]; + ++ concatLists [ + shared + homes + /* + hybrid + */ + ]; specialArgs = sharedArgs; }; - hydra = mkNixosSystem { + amatarasu = mkNixosSystem { inherit withSystem; system = "x86_64-linux"; modules = [ - ./hydra + ./amatarasu + desktop workstation ] - ++ concatLists [shared homes hybrid]; + ++ concatLists [shared homes]; specialArgs = sharedArgs; }; bernie = mkNixosSystem { inherit withSystem; - system = "aarch64-linux"; + system = "x86_64-linux"; modules = [ ./bernie @@ -83,6 +92,19 @@ in { specialArgs = sharedArgs; }; + /* + beta = mkNixosSystem { + inherit withSystem; + system = "x86_64-linux"; + modules = [ + ./beta + server + ] + ++ concatLists [shared homes]; + specialArgs = sharedArgs; + }; + */ + lilith = mkNixosIso { system = "x86_64-linux"; modules = [ diff --git a/hosts/hydra/default.nix b/hosts/hydra/default.nix index 8c96ef903..563b5a106 100644 --- a/hosts/hydra/default.nix +++ b/hosts/hydra/default.nix @@ -1,33 +1,39 @@ -{config, ...}: { +_: { imports = [./hardware-configuration.nix]; config = { modules = { device = { - type = "hybrid"; + type = "laptop"; cpu = "intel"; gpu = null; - hasTPM = true; monitors = ["eDP-1"]; + hasTPM = true; hasBluetooth = true; hasSound = true; }; system = { mainUser = "isabel"; - hostname = "hydra"; boot = { loader = "systemd-boot"; + secureBoot = false; enableKernelTweaks = true; enableInitrdTweaks = true; loadRecommendedModules = true; }; + fs = ["ext4" "vfat"]; video.enable = true; sound.enable = true; bluetooth.enable = true; printing.enable = false; + security = { + fixWebcam = false; + auditd.enable = true; + }; + networking = { optimizeTcp = true; }; @@ -45,40 +51,35 @@ desktop = "Hyprland"; useHomeManager = true; }; - services = { - smb = { - enable = true; - recive = { - media = true; - general = true; - }; - }; - vscode-server.enable = true; - cloudflare = { - enable = true; - id = "32f941a8-e557-4d8a-bafd-52a7d65a5daf"; - }; - jellyfin = { - enable = true; - asDockerContainer = false; - }; - }; + programs = { git.signingKey = "CFF897835DD77813"; - cli.enable = true; + cli = { + enable = true; + modernShell.enable = true; + }; tui.enable = true; gui.enable = true; - default = { + zathura.enable = true; + + defaults = { bar = "ags"; }; + }; - nur = { - enable = true; - bella = true; - nekowinston = true; + services = { + smb = { + enable = false; + recive = { + media = false; + general = false; + }; }; + vscode-server.enable = true; + cloudflared.enable = false; + jellyfin.enable = false; }; }; diff --git a/hosts/lilith/boot.nix b/hosts/lilith/boot.nix new file mode 100644 index 000000000..bd8c57573 --- /dev/null +++ b/hosts/lilith/boot.nix @@ -0,0 +1,25 @@ +{ + pkgs, + lib, + ... +}: { + boot = { + kernelParams = lib.mkAfter ["noquiet"]; + # we have no need for systemd in initrd installation media + initrd.systemd = { + enable = lib.mkImageMediaOverride false; + emergencyAccess = lib.mkImageMediaOverride true; + }; + kernelPackages = pkgs.linuxPackages_latest; + + # https://github.com/NixOS/nixpkgs/issues/58959 + supportedFilesystems = lib.mkForce [ + "btrfs" + "vfat" + "f2fs" + "xfs" + "ntfs" + "cifs" + ]; + }; +} diff --git a/hosts/lilith/default.nix b/hosts/lilith/default.nix index a2aa27710..e70a74785 100644 --- a/hosts/lilith/default.nix +++ b/hosts/lilith/default.nix @@ -2,32 +2,89 @@ config, lib, pkgs, + modulesPath, ... -}: { - # Secure defaults - nixpkgs.config = {allowBroken = true;}; # false breaks zfs kernel - # Always copytoram so that, if the image is booted from, e.g., a - # USB stick, nothing is mistakenly written to persistent storage. - boot.kernelParams = ["copytoram"]; - boot.tmp.cleanOnBoot = true; - boot.kernel.sysctl = {"kernel.unprivileged_bpf_disabled" = 1;}; - - # make sure we are air-gapped - networking.wireless.enable = true; - networking.dhcpcd.enable = true; - - services.getty.helpLine = "The 'root' account has an empty password."; - - services.openssh.enable = true; - users.users.root.openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDZmzCZrKIdTSUf1GFWB9bF2nDRfjdWI4+jfcZbsscsSdNHBBaYnDjQftj8lVUMmSzjKasIeU3yKmuai6t2GBnIfxZq+5L/uvIZhYfgJwcjhLkXZL2CCG1UtxFV6Gwe2RJWA7VrGzhfU+Kjx6O7oCKlwy0M6cknUU+G17rqoGlOwDtMiDR+as6UoxeEf//xIdvBdEb3A+JGo4WVx1+/8XedKM5ngyY0zH6vKb12kudVMjJsqQ4cES8JozuL4LMEExsPRALPVGYQ69ulMLl4zkbbP2Ne5UO9Uf/BsBF2DJU3uWVIG6nAUIeNr4NXaa7h4/cnlpP+f4H/7MvOeif85TYU2WK+yiy11z7N6wxbB1/Mtq2sMldMq3Csb7A0GkeF1qXazG0yp4Oa0sene0JfPI3AsYSFOHuByVRkb6kI3f+d/xogwoLJ645olZLcobsqWoS4TQZHj44CTRseXzCQiUGBKV9Bb/7hqY7TbcwRd7cEW91lbXIzO6PUDhi1E59VqYE= isabel" +}: +with lib; { + imports = [ + "${modulesPath}/profiles/minimal.nix" + "${modulesPath}/installer/cd-dvd/installation-cd-base.nix" + + ./boot.nix + ./iso.nix + ./networking.nix + ./nix.nix + ]; + + # FIXME: for some reason, we cannot boot off ventoy + # and have to burn the iso to an entire USB with dd + # dd if=result/iso/*.iso of=/dev/sdX status=progress + + users.extraUsers.root.password = ""; + + console = let + variant = "u24n"; + in { + # hidpi terminal font + font = "${pkgs.terminus_font}/share/consolefonts/ter-${variant}.psf.gz"; + keyMap = "en"; + }; + + # fix: "too many open files" + security.pam.loginLimits = [ + { + domain = "*"; + item = "nofile"; + type = "-"; + value = "65536"; + } ]; - isoImage.isoBaseName = lib.mkForce config.networking.hostName; - boot.kernelPackages = pkgs.linuxPackages_latest; + services.getty.helpLine = + '' + The "nixos" and "root" accounts have empty passwords. + An ssh daemon is running. You then must set a password + for either "root" or "nixos" with `passwd` or add an ssh key + to /home/nixos/.ssh/authorized_keys be able to login. + If you need a wireless connection, you may use networkmanager + by invoking `nmcli` or `nmtui`, the ncurses interface. + '' + + optionalString config.services.xserver.enable '' + Type `sudo systemctl start display-manager' to + start the graphical user interface. + ''; + + # Use environment options, minimal profile, to save space + environment = { + noXlibs = mkDefault true; + + # no packages other, other then the ones i provide + defaultPackages = []; + + # needed packages for the installer + systemPackages = with pkgs; [ + nixos-install-tools + gitMinimal + neovim + netcat + ]; + + # fix annoying warning + etc."mdadm.conf".text = '' + MAILADDR root + ''; + }; + + # disable documentation to save space + documentation = { + enable = mkDefault false; + doc.enable = mkDefault false; + info.enable = mkDefault false; + }; - services.gvfs.enable = true; + # disable fontConfig to save space, not like we have a GUI anyways + fonts.fontconfig.enable = lib.mkForce false; - services.autorandr.enable = true; - programs.nm-applet.enable = true; + # disable sound related programs, saving more space + sound.enable = false; } diff --git a/hosts/lilith/iso.nix b/hosts/lilith/iso.nix new file mode 100644 index 000000000..15295364a --- /dev/null +++ b/hosts/lilith/iso.nix @@ -0,0 +1,21 @@ +{ + self, + config, + lib, + pkgs, + ... +}: { + networking.hostName = lib.mkImageMediaOverride "lilith"; + + isoImage = let + rev = self.shortRev or "dirty"; + in { + # lilith-$rev-$arch.iso + isoName = lib.mkImageMediaOverride "lilith-${config.system.nixos.release}-${rev}-${pkgs.stdenv.hostPlatform.uname.processor}.iso"; + # lilith-$release-$rev-$arch + volumeID = "lilith-${config.system.nixos.release}-${rev}-${pkgs.stdenv.hostPlatform.uname.processor}"; + + # faster compression in exchange for larger iso size + squashfsCompression = "gzip -Xcompression-level 1"; + }; +} diff --git a/hosts/lilith/networking.nix b/hosts/lilith/networking.nix new file mode 100644 index 000000000..772a52e0a --- /dev/null +++ b/hosts/lilith/networking.nix @@ -0,0 +1,14 @@ +{ + pkgs, + lib, + ... +}: { + # use networkmanager in the live environment + networking.networkmanager.enable = lib.mkForce true; + networking.wireless.enable = lib.mkForce false; + + systemd.services.sshd.wantedBy = pkgs.lib.mkForce ["multi-user.target"]; + users.users.root.openssh.authorizedKeys.keys = [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDZmzCZrKIdTSUf1GFWB9bF2nDRfjdWI4+jfcZbsscsSdNHBBaYnDjQftj8lVUMmSzjKasIeU3yKmuai6t2GBnIfxZq+5L/uvIZhYfgJwcjhLkXZL2CCG1UtxFV6Gwe2RJWA7VrGzhfU+Kjx6O7oCKlwy0M6cknUU+G17rqoGlOwDtMiDR+as6UoxeEf//xIdvBdEb3A+JGo4WVx1+/8XedKM5ngyY0zH6vKb12kudVMjJsqQ4cES8JozuL4LMEExsPRALPVGYQ69ulMLl4zkbbP2Ne5UO9Uf/BsBF2DJU3uWVIG6nAUIeNr4NXaa7h4/cnlpP+f4H/7MvOeif85TYU2WK+yiy11z7N6wxbB1/Mtq2sMldMq3Csb7A0GkeF1qXazG0yp4Oa0sene0JfPI3AsYSFOHuByVRkb6kI3f+d/xogwoLJ645olZLcobsqWoS4TQZHj44CTRseXzCQiUGBKV9Bb/7hqY7TbcwRd7cEW91lbXIzO6PUDhi1E59VqYE= isabel" + ]; +} diff --git a/hosts/lilith/nix.nix b/hosts/lilith/nix.nix new file mode 100644 index 000000000..bd1ebb2f0 --- /dev/null +++ b/hosts/lilith/nix.nix @@ -0,0 +1,13 @@ +_: { + nix = { + settings = { + experimental-features = ["nix-command" "flakes" "repl-flake"]; + log-lines = 30; + extra-experimental-features = ["ca-derivations"]; + warn-dirty = false; + http-connections = 50; + accept-flake-config = true; + auto-optimise-store = true; + }; + }; +} diff --git a/lib/builders.nix b/lib/builders.nix index 72e324fac..22cbc7ec8 100644 --- a/lib/builders.nix +++ b/lib/builders.nix @@ -3,16 +3,14 @@ inputs, ... }: let - # inherit self from inputs inherit (inputs) self; - # just an alias to nixpkgs.lib.nixosSystem, lets me avoid adding - # nixpkgs to the scope in the file it is used in + # just an alias to nixpkgs.lib.nixosSystem mkSystem = lib.nixosSystem; - # mkNixosSystem wraps mkSystem (a.k.a lib.nixosSystem) with flake-parts' withSystem to provide inputs' and self' from flake-parts - # it also acts as a template for my nixos hosts with system type and modules being imported beforehand - # specialArgs is also defined here to avoid defining them for each host and lazily merged if the host defines any other args + # mkNixosSystem wraps mkSystem (or lib.nixosSystem) with flake-parts' withSystem to give us inputs' and self' from flake-parts + # which can also be used as a template for nixos hosts with system type and modules to be imported with ease + # specialArgs is also defined here to avoid defining them for each host mkNixosSystem = { modules, system, @@ -29,9 +27,8 @@ specialArgs = {inherit lib inputs self inputs' self';} // args.specialArgs or {}; }); - # mkIso is should be a set that extends mkSystem with necessary modules - # to create an Iso image - # we do not use mkNixosSystem because it overcomplicates things, an ISO does not require what we get in return for those complications + # mkIso is should be a set that extends mkSystem (again) with necessary modules to create an Iso image + # don't use mkNixosSystem as it is complelty overkill for an iso and will have too much data, we need a light weight image mkNixosIso = { modules, system, diff --git a/lib/hardware.nix b/lib/hardware.nix new file mode 100644 index 000000000..315d1a3df --- /dev/null +++ b/lib/hardware.nix @@ -0,0 +1,12 @@ +_: let + # check if the host platform is linux and x86 + # (isx86Linux pkgs) -> true + isx86Linux = pkgs: with pkgs.stdenv; hostPlatform.isLinux && hostPlatform.isx86; + + # assume the first monitor in the list of monitors is primary + # get its name from the list of monitors + # `primaryMonitor osConfig` -> "DP-1" + primaryMonitor = config: builtins.elemAt config.modules.device.monitors 0; +in { + inherit isx86Linux primaryMonitor; +} diff --git a/lib/helpers.nix b/lib/helpers.nix index f6ac0360a..db69c0db2 100644 --- a/lib/helpers.nix +++ b/lib/helpers.nix @@ -1,9 +1,7 @@ {lib, ...}: let inherit (lib) lists mapAttrsToList filterAttrs hasSuffix; - primaryMonitor = config: builtins.elemAt config.modules.device.monitors 0; - - # filter files that have the .nix suffix + # filter files for the .nix suffix filterNixFiles = k: v: v == "regular" && hasSuffix ".nix" k; # import files that are selected by filterNixFiles @@ -12,7 +10,7 @@ (filterAttrs filterNixFiles (builtins.readDir path)))) import; - # return an int (1/0) based on boolean value + # return an int based on boolean value boolToNum = bool: if bool then 1 @@ -21,15 +19,26 @@ # a basic function to fetch a specified user's public keys from github .keys url fetchKeys = username: (builtins.fetchurl "https://github.com/${username}.keys"); - # a helper function that checks if a list contains a list of given strings + indexOf = list: elem: let + f = f: i: + if i == (builtins.length list) + then null + else if (builtins.elemAt list i) == elem + then i + else f f (i + 1); + in + f f 0; + + # a function to go from normal text to lower snake case + # "A Normal String" -> "a-normal-string" + serializeTheme = inputString: lib.strings.toLower (builtins.replaceStrings [" "] ["-"] inputString); + + # a function that checks if a list contains a list of given strings containsStrings = { list, targetStrings, }: builtins.all (s: builtins.any (x: x == s) list) targetStrings; - - # replace whitespaces with hyphens - serializeTheme = inputString: lib.strings.toLower (builtins.replaceStrings [" "] ["-"] inputString); in { - inherit primaryMonitor filterNixFiles importNixFiles boolToNum fetchKeys containsStrings serializeTheme; + inherit filterNixFiles importNixFiles boolToNum fetchKeys containsStrings serializeTheme indexOf; } diff --git a/lib/validators.nix b/lib/validators.nix index 75ff379fe..5b3570cd3 100644 --- a/lib/validators.nix +++ b/lib/validators.nix @@ -4,6 +4,23 @@ # a function that returns a boolean based on whether or not the groups exist ifGroupsExist = config: groups: lib.any (group: builtins.hasAttr group config.users.groups) groups; + + # convenience function check if the declared device type is of an accepted type + # takes config and a list of accepted device types + # `isAcceptedDevice osConfig ["foo" "bar"];` + isAcceptedDevice = conf: list: builtins.elem conf.modules.device.type list; + + # assert if the device is wayland-ready by checking sys.video and env.isWayland options + # `(lib.isWayland config)` where config is in scope + # `isWayland osConfig` -> true + isWayland = conf: conf.modules.system.video.enable && conf.modules.usrEnv.isWayland; + + # ifOneEnabled takes a parent option and 3 child options and checks if at least one of them is enabled + # `ifOneEnabled config.modules.services "service1" "service2" "service3"` + ifOneEnabled = cfg: a: b: c: (cfg.a || cfg.b || cfg.c); + + # check if modernshell and cli are both enabled + isModernShell = conf: conf.modules.programs.cli.enable && conf.modules.programs.cli.modernShell.enable; in { - inherit ifTheyExist ifGroupsExist; + inherit ifTheyExist ifGroupsExist isAcceptedDevice isWayland ifOneEnabled isModernShell; } diff --git a/modules/common/core/default.nix b/modules/common/core/default.nix index 3aad5f876..7a792d219 100644 --- a/modules/common/core/default.nix +++ b/modules/common/core/default.nix @@ -1,6 +1,6 @@ _: { imports = [ - ./nix # configuration for the nix package manager and build tool - ./system # system configurations, from bootloader to desktop environment + ./gaming # super cool procrastinations related things + ./system # system configurations ]; } diff --git a/modules/common/core/gaming/default.nix b/modules/common/core/gaming/default.nix new file mode 100644 index 000000000..a91902b91 --- /dev/null +++ b/modules/common/core/gaming/default.nix @@ -0,0 +1,6 @@ +_: { + imports = [ + ./gamemode.nix # cool scripts, and programs to imporve gaming preformance + ./steam.nix # steam, the gaming platform + ]; +} diff --git a/modules/common/core/gaming/gamemode.nix b/modules/common/core/gaming/gamemode.nix new file mode 100644 index 000000000..db380a5a6 --- /dev/null +++ b/modules/common/core/gaming/gamemode.nix @@ -0,0 +1,62 @@ +{ + config, + lib, + pkgs, + inputs, + ... +}: let + inherit (lib) makeBinPath mkIf optionalString; + + env = config.modules.usrEnv; + + programs = makeBinPath (with pkgs; [ + inputs.hyprland.packages.${stdenv.system}.default + coreutils + power-profiles-daemon + systemd + ]); + + startscript = pkgs.writeShellScript "gamemode-start" '' + ${optionalString (env.desktop == "Hyprland") '' + export PATH=$PATH:${programs} + export HYPRLAND_INSTANCE_SIGNATURE=$(ls -w1 /tmp/hypr | tail -1) + hyprctl --batch 'keyword decoration:blur 0 ; keyword animations:enabled 0 ; keyword misc:vfr 0' + ''} + + powerprofilesctl set performance + ${pkgs.libnotify}/bin/notify-send -a 'Gamemode' 'Optimizations activated' + ''; + + endscript = pkgs.writeShellScript "gamemode-end" '' + ${optionalString (env.desktop == "Hyprland") '' + export PATH=$PATH:${programs} + export HYPRLAND_INSTANCE_SIGNATURE=$(ls -w1 /tmp/hypr | tail -1) + hyprctl --batch 'keyword decoration:blur 1 ; keyword animations:enabled 1 ; keyword misc:vfr 1' + ''} + + powerprofilesctl set power-saver + ${pkgs.libnotify}/bin/notify-send -a 'Gamemode' 'Optimizations deactivated' + ''; + + cfg = config.modules.programs.gaming; +in { + imports = [./steam.nix]; + config = mkIf cfg.enable { + programs = { + gamemode = { + enable = true; + enableRenice = true; + settings = { + general = { + softrealtime = "auto"; + renice = 15; + }; + custom = { + start = startscript.outPath; + end = endscript.outPath; + }; + }; + }; + }; + }; +} diff --git a/modules/common/core/gaming/steam.nix b/modules/common/core/gaming/steam.nix new file mode 100644 index 000000000..b40eb6541 --- /dev/null +++ b/modules/common/core/gaming/steam.nix @@ -0,0 +1,24 @@ +{ + pkgs, + lib, + config, + inputs, + ... +}: let + cfg = config.modules.programs.gaming; +in { + imports = [inputs.nix-gaming.nixosModules.steamCompat]; + # enable steam + programs.steam = lib.mkIf cfg.enable { + enable = true; + # Open ports in the firewall for Steam Remote Play + remotePlay.openFirewall = true; + # Open ports in the firewall for Source Dedicated Server + dedicatedServer.openFirewall = true; + # Compatibility tools to install + # this option used to be provided by modules/shared/nixos/steam + extraCompatPackages = [ + inputs.nix-gaming.packages.${pkgs.system}.proton-ge + ]; + }; +} diff --git a/modules/common/core/system/activation/default.nix b/modules/common/core/system/activation/default.nix index 610b312b9..1fd45f26e 100644 --- a/modules/common/core/system/activation/default.nix +++ b/modules/common/core/system/activation/default.nix @@ -2,10 +2,8 @@ config, lib, ... -}: let - inherit (lib) mkIf; -in { - system.activationScripts.diff = mkIf config.modules.system.activation.diffGenerations { +}: { + system.activationScripts.diff = lib.mkIf config.modules.system.activation.diffGenerations { supportsDryActivation = true; text = '' if [[ -e /run/current-system ]]; then diff --git a/modules/common/core/system/boot/generic/default.nix b/modules/common/core/system/boot/generic/default.nix deleted file mode 100644 index 8194462e0..000000000 --- a/modules/common/core/system/boot/generic/default.nix +++ /dev/null @@ -1,161 +0,0 @@ -{ - lib, - config, - ... -}: -with lib; let - sys = config.modules.system; -in { - config = { - boot = { - consoleLogLevel = 0; - - # always use the latest kernel instead of the old-ass lts one - kernelPackages = lib.mkOverride 500 sys.boot.kernel; - - extraModulePackages = with config.boot.kernelPackages; [acpi_call]; - extraModprobeConfig = "options hid_apple fnmode=1"; - - # settings shared between bootloaders - # they are set unless system.boot.loader != none - loader = { - # if set to 0, space needs to be held to get the boot menu to appear - timeout = mkForce 2; - generationsDir.copyKernels = true; - - # allow installation to modify EFI variables - efi.canTouchEfiVariables = true; - }; - - # instructions on how /tmp should be handled - # if your system is low on ram, you should avoid tmpfs to prevent hangups while compiling - tmp = { - # /tmp on tmpfs, lets it live on your ram - useTmpfs = mkDefault true; - - # If not using tmpfs, which is naturally purged on reboot, we must clean - # /tmp ourselves. /tmp should be volatile storage! - cleanOnBoot = mkDefault (!config.boot.tmp.useTmpfs); - }; - - # initrd and kernel tweaks - # if you intend to copy paste this section, read what each parameter or module does before doing so - # I am not responsible for your broken system - initrd = mkMerge [ - (mkIf sys.boot.enableInitrdTweaks { - # Verbosity of the initrd - # disabling verbosity removes only the mandatory messages generated by the NixOS - verbose = false; - - # strip copied binaries and libraries from inframs - # saves 30~ mb space according to the nix derivation - systemd.strip = true; - - # extremely experimental, just the way I like it on a production machine - systemd.enable = true; - }) - - (mkIf sys.boot.enableKernelTweaks { - # List of modules that are always loaded by the initrd - kernelModules = [ - "xhci_pci" - "ahci" - "btrfs" - "cifs" - "sd_mod" - "dm_mod" - "usb_storage" - "rtsx_pci_sdmmc" - ]; - - # the set of kernel modules in the initial ramdisk used during the boot process - availableKernelModules = [ - "nvme" - "usbhid" - "sd_mod" - "dm_mod" - ]; - }) - ]; - - # https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html - kernelParams = - [ - # https://en.wikipedia.org/wiki/Kernel_page-table_isolation - # auto means kernel will automatically decide the pti state - "pti=auto" # on | off - - # make stack-based attacks on the kernel harder - "randomize_kstack_offset=on" - - # this has been defaulted to none back in 2016 - break really old binaries for security - "vsyscall=none" - - # https://tails.boum.org/contribute/design/kernel_hardening/ - "slab_nomerge" - - # only allow signed modules - "module.sig_enforce=1" - - # blocks access to all kernel memory, even preventing administrators from being able to inspect and probe the kernel - "lockdown=confidentiality" - - # enable buddy allocator free poisoning - "page_poison=1" - - # performance improvement for direct-mapped memory-side-cache utilization, reduces the predictability of page allocations - "page_alloc.shuffle=1" - - # for debugging kernel-level slab issues - "slub_debug=FZP" - - # always-enable sysrq keys. Useful for debugging - "sysrq_always_enabled=0" - - # save power on idle by limiting c-states - # https://gist.github.com/wmealing/2dd2b543c4d3cff6cab7 - "processor.max_cstate=5" - - # disable the intel_idle driver and use acpi_idle instead - "idle=nomwait" - - # ignore access time (atime) updates on files, except when they coincide with updates to the ctime or mtime - "rootflags=noatime" - - # enable IOMMU for devices used in passthrough and provide better host performance - "iommu=pt" - - # disable usb autosuspend - "usbcore.autosuspend=-1" - # linux security modules - "lsm=landlock,lockdown,yama,apparmor,bpf" - - # isables resume and restores original swap space - "noresume" - - # allows systemd to set and save the backlight state - "acpi_backlight=native" # none | vendor | video | native - - # prevent the kernel from blanking plymouth out of the fb - "fbcon=nodefer" - - # disable boot logo if any - "logo.nologo" - - # tell the kernel to not be verbose - # "quiet" - - # disable systemd status messages - # rd prefix means systemd-udev will be used instead of initrd - "rd.systemd.show_status=auto" - - # lower the udev log level to show only errors or worse - "rd.udev.log_level=3" - - # disable the cursor in vt to get a black screen during intermissions - "vt.global_cursor_default=0" - ] - ++ optionals (sys.boot.extraKernelParams != []) sys.boot.extraKernelParams; - }; - }; -} diff --git a/modules/common/core/system/default.nix b/modules/common/core/system/default.nix index ef19199a2..0b8368bb8 100644 --- a/modules/common/core/system/default.nix +++ b/modules/common/core/system/default.nix @@ -1,11 +1,14 @@ _: { imports = [ - ./hardware # hardware - i.e bluetooth, sound, tpm etc. - ./media # enable multimedia - ./boot # boot and bootloader configurations - ./os # system configurations - ./smb # host and recive smb shares ./activation # activation system for nixos-rebuild - ./virtualization # hypervisor and virtualisation related options - docker, QEMU, waydroid etc. + ./emulation # emulation setup + ./encryption # keeping my stuff hidden from you strange people + ./hardware # hardware - bluetooth etc. + ./media # sound and video + ./nix # nix the package manger options + ./os # system configurations + ./security # keeping the system safe + ./smb # host and recive smb shares TODO move + ./virtualization # docker, QEMU, waydroid etc. ]; } diff --git a/modules/common/core/system/emulation/default.nix b/modules/common/core/system/emulation/default.nix new file mode 100644 index 000000000..b4032a439 --- /dev/null +++ b/modules/common/core/system/emulation/default.nix @@ -0,0 +1,28 @@ +{ + config, + pkgs, + lib, + ... +}: let + inherit (lib) mkIf; + sys = config.modules.system; +in { + config = mkIf sys.emulation.enable { + nix.settings.extra-sandbox-paths = ["/run/binfmt" "${pkgs.qemu}"]; + + boot.binfmt = { + emulatedSystems = sys.emulation.systems; + registrations = { + # aarch64 interpreter + aarch64-linux = { + interpreter = "${pkgs.qemu}/bin/qemu-aarch64"; + }; + + # i686 interpreter + i686-linux = { + interpreter = "${pkgs.qemu}/bin/qemu-i686"; + }; + }; + }; + }; +} diff --git a/modules/common/core/system/encryption/default.nix b/modules/common/core/system/encryption/default.nix new file mode 100644 index 000000000..f770726f6 --- /dev/null +++ b/modules/common/core/system/encryption/default.nix @@ -0,0 +1,34 @@ +{ + config, + lib, + ... +}: let + inherit (lib) mkIf; + + cfg = config.modules.system.encryption; +in { + config = mkIf cfg.enable { + # mildly improves performance for the disk encryption + boot.initrd.availableKernelModules = [ + "aesni_intel" + "cryptd" + "usb_storage" + ]; + + services.lvm.enable = true; + + # TODO: account for multiple encrypted devices + boot.initrd.luks.devices."${cfg.device}" = { + # improve performance on ssds + bypassWorkqueues = true; + preLVM = true; + + # the device with the maching id will be searched for the key file + keyFile = mkIf (cfg.keyFile != null) "${cfg.keyFile}"; + keyFileSize = cfg.keySize; + + # if keyfile is not there, fall back to cryptsetup password + fallbackToPassword = cfg.fallbackToPassword; # IMPLIED BY config.boot.initrd.systemd.enable + }; + }; +} diff --git a/modules/common/core/system/hardware/cpu/amd/default.nix b/modules/common/core/system/hardware/cpu/amd/default.nix index 1c721a612..5b554cab3 100644 --- a/modules/common/core/system/hardware/cpu/amd/default.nix +++ b/modules/common/core/system/hardware/cpu/amd/default.nix @@ -2,12 +2,15 @@ config, lib, ... -}: -with lib; let - device = config.modules.device; +}: let + inherit (config.modules) device; + inherit (lib) mkIf; in { config = mkIf (device.cpu == "amd" || device.cpu == "vm-amd") { hardware.cpu.amd.updateMicrocode = true; - boot.kernelModules = ["kvm-amd"]; + boot.kernelModules = [ + "kvm-amd" + "amd-pstate" + ]; }; } diff --git a/modules/common/core/system/hardware/gpu/amd/default.nix b/modules/common/core/system/hardware/gpu/amd/default.nix index 9cc0a4803..00a602160 100644 --- a/modules/common/core/system/hardware/gpu/amd/default.nix +++ b/modules/common/core/system/hardware/gpu/amd/default.nix @@ -8,7 +8,7 @@ with lib; let device = config.modules.device; in { config = mkIf (device.gpu == "amd" || device.gpu == "hybrid-amd") { - # enable amdgpu xorg drivers in case Hyprland breaks again + # enable amdgpu xorg drivers services.xserver.videoDrivers = ["amdgpu"]; # enable amdgpu kernel module diff --git a/modules/common/core/system/hardware/gpu/intel/default.nix b/modules/common/core/system/hardware/gpu/intel/default.nix index c4f40301a..480bb80b5 100644 --- a/modules/common/core/system/hardware/gpu/intel/default.nix +++ b/modules/common/core/system/hardware/gpu/intel/default.nix @@ -8,13 +8,13 @@ with lib; let device = config.modules.device; in { config = mkIf (device.gpu == "intel" || device.gpu == "hybrid-nv") { - # enable the i915 kernel module + # i915 kernel module boot.initrd.kernelModules = ["i915"]; - # better performance than the actual Intel driver + # better performance than the actual Intel driver, lol services.xserver.videoDrivers = ["modesetting"]; nixpkgs.config.packageOverrides = pkgs: { - # let me play youtube videos without h.264, please and thank you + # let me play youtube videos without h.264 vaapiIntel = pkgs.vaapiIntel.override {enableHybridCodec = true;}; }; diff --git a/modules/common/core/system/hardware/gpu/nvidia/default.nix b/modules/common/core/system/hardware/gpu/nvidia/default.nix index 01f3cc8bf..a2b257e4e 100644 --- a/modules/common/core/system/hardware/gpu/nvidia/default.nix +++ b/modules/common/core/system/hardware/gpu/nvidia/default.nix @@ -5,7 +5,7 @@ ... }: with lib; let - # use the latest possible nvidia package + # only the newest nvidia package nvStable = config.boot.kernelPackages.nvidiaPackages.stable.version; nvBeta = config.boot.kernelPackages.nvidiaPackages.beta.version; @@ -14,11 +14,11 @@ with lib; let then config.boot.kernelPackages.nvidiaPackages.stable else config.boot.kernelPackages.nvidiaPackages.beta; - device = config.modules.device; + inherit (config.modules) device; env = config.modules.usrEnv; in { config = mkIf (device.gpu == "nvidia" || device.gpu == "hybrid-nv") { - # nvidia drivers are unfree software + # nvidia drivers kinda are unfree software nixpkgs.config.allowUnfree = true; services.xserver = mkMerge [ @@ -44,8 +44,7 @@ in { ]; boot = { - # blacklist nouveau module so that it does not conflict with nvidia drm stuff - # also the nouveau performance is godawful, I'd rather run linux on a piece of paper than use nouveau + # blacklist nouveau module as otherwise it conflicts with nvidia drm blacklistedKernelModules = ["nouveau"]; }; @@ -55,13 +54,13 @@ in { LIBVA_DRIVER_NAME = "nvidia"; } - (mkIf (env.isWayland) { + (mkIf env.isWayland { WLR_NO_HARDWARE_CURSORS = "1"; - #__GLX_VENDOR_LIBRARY_NAME = "nvidia"; - #GBM_BACKEND = "nvidia-drm"; # breaks firefox apparently + __GLX_VENDOR_LIBRARY_NAME = "nvidia"; + GBM_BACKEND = "nvidia-drm"; # breaks firefox apparently (not that i use it lol) }) - (mkIf ((env.isWayland) && (device.gpu == "hybrid-nv")) { + (mkIf (env.isWayland && device.gpu == "hybrid-nv") { #__NV_PRIME_RENDER_OFFLOAD = "1"; #WLR_DRM_DEVICES = mkDefault "/dev/dri/card1:/dev/dri/card0"; }) @@ -80,15 +79,13 @@ in { package = mkDefault nvidiaPackage; modesetting.enable = mkDefault true; prime.offload.enableOffloadCmd = device.gpu == "hybrid-nv"; - #powerManagement = { - # enable = mkDefault true; - # finegrained = mkDefault true; - #}; + powerManagement = { + enable = mkDefault true; + finegrained = mkDefault true; + }; - # use open source drivers by default, hosts may override this option if their gpu is - # not supported by the open source drivers - open = mkDefault true; - nvidiaSettings = false; # add nvidia-settings to pkgs, useless on nixos + open = mkDefault true; # use open source drivers by default + nvidiaSettings = false; # adds nvidia-settings to pkgs, so useless on nixos nvidiaPersistenced = true; forceFullCompositionPipeline = true; }; diff --git a/modules/common/core/system/media/sound/default.nix b/modules/common/core/system/media/sound/default.nix index 5855836e5..2e837ed5d 100644 --- a/modules/common/core/system/media/sound/default.nix +++ b/modules/common/core/system/media/sound/default.nix @@ -2,35 +2,48 @@ lib, config, pkgs, + inputs, ... -}: -with lib; let +}: let + inherit (lib) mkIf mkDefault; + inherit (pkgs.stdenv) hostPlatform; + + isx86Linux = hostPlatform.isLinux && hostPlatform.isx86; + cfg = config.modules.system.sound; - device = config.modules.device; + inherit (config.modules) device; in { + imports = [inputs.nix-gaming.nixosModules.pipewireLowLatency]; + config = mkIf (cfg.enable && device.hasSound) { # enable sound support and media keys if device has sound sound = { enable = true; mediaKeys.enable = true; }; + # able to change scheduling policies, e.g. to SCHED_RR security.rtkit.enable = config.services.pipewire.enable; - # we replace pulseaudio with the incredibly based pipewire + # pipewire is newer and just better services.pipewire = { enable = mkDefault true; + wireplumber.enable = true; + pulse.enable = true; + jack.enable = true; alsa = { enable = true; - support32Bit = with pkgs; (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isx86); + support32Bit = isx86Linux; + }; + + lowLatency = { + enable = true; + quantum = 64; + rate = 48000; }; - pulse.enable = true; - jack.enable = true; - wireplumber.enable = true; }; - # if for some reason pipewire is disabled, we may enable pulseaudio as backup - # I don't like PA, but I won't discard it altogether + # pulseaudio backup hardware.pulseaudio.enable = !config.services.pipewire.enable; # write bluetooth rules if and only if pipewire is enabled AND the device has bluetooth environment.etc = mkIf (config.services.pipewire.enable && device.hasBluetooth) { diff --git a/modules/common/core/nix/default.nix b/modules/common/core/system/nix/default.nix similarity index 68% rename from modules/common/core/nix/default.nix rename to modules/common/core/system/nix/default.nix index 5c7cc92bb..bf27f6287 100644 --- a/modules/common/core/nix/default.nix +++ b/modules/common/core/system/nix/default.nix @@ -6,8 +6,7 @@ inputs', self, ... -}: -with lib; { +}: { system = { autoUpgrade.enable = false; stateVersion = lib.mkDefault "23.05"; @@ -24,12 +23,12 @@ with lib; { "nixos/flake".source = self; }; - # we need git for flakes, don't we + # git is reqired for flakes systemPackages = [pkgs.git]; }; nixpkgs = { - pkgs = self.legacyPackages.${config.nixpkgs.system}; + #pkgs = self.legacyPackages.${config.nixpkgs.system}; config = { allowUnfree = true; @@ -38,27 +37,16 @@ with lib; { permittedInsecurePackages = []; }; - overlays = with inputs; let - nurOpt = config.modules.programs.nur; - in - [ - rust-overlay.overlays.default - ] - ++ optionals (nurOpt.enable) [ - (final: prev: { - nur = import nur { - nurpkgs = prev; - pkgs = prev; - repoOverrides = - {} - // lib.optionalAttrs (nurOpt.bella) {bella = inputs'.bella-nur.packages;} - // lib.optionalAttrs (nurOpt.nekowinston) {nekowinston = inputs'.nekowinston-nur.packages;}; - }; - }) - ]; + overlays = [ + inputs.rust-overlay.overlays.default + + (_: _: { + nixSchemas = inputs'.nixSchemas.packages.default; + }) + ]; }; - # faster rebuilding + # faster rebuilding, plus i don't use the docs anyways documentation = { doc.enable = false; nixos.enable = false; @@ -70,33 +58,27 @@ with lib; { }; nix = let - mappedRegistry = mapAttrs (_: v: {flake = v;}) inputs; + mappedRegistry = lib.mapAttrs (_: v: {flake = v;}) inputs; in { - # pin the registry to avoid downloading and evaluating a new nixpkgs - # version everytime - # this will add each flake input as a registry - # to make nix3 commands consistent with your flake + # pin the registry to avoid downloading and evaluating a new nixpkgs version everytime registry = mappedRegistry // {default = mappedRegistry.nixpkgs;}; - # This will additionally add your inputs to the system's legacy channels - # Making legacy nix commands consistent as well, awesome! - nixPath = mapAttrsToList (key: _: "${key}=flake:${key}") config.nix.registry; + # We love legacy support (for now) + nixPath = lib.mapAttrsToList (key: _: "${key}=flake:${key}") config.nix.registry; - # Make builds run with low priority so my system stays responsive + # Make builds run with a low priority, keeping the system fast daemonCPUSchedPolicy = "idle"; daemonIOSchedClass = "idle"; daemonIOSchedPriority = 7; - # set up garbage collection to run daily, - # removing unused packages after three days + # set up garbage collection to run daily, and removing packages after 3 days gc = { automatic = true; dates = "Mon *-*-* 03:00"; options = "--delete-older-than 3d"; }; - # automatically optimize nix store my removing hard links - # do it after the gc + # automatically optimize /nix/store by removing hard links optimise = { automatic = true; dates = ["04:00"]; @@ -106,7 +88,7 @@ with lib; { # specify the path to the nix registry flake-registry = "/etc/nix/registry.json"; # Free up to 20GiB whenever there is less than 5GB left. - # this setting is in bytes, so we multiply with 1024 thrice + # this setting is in bytes, so we multiply with 1024 by 3 min-free = "${toString (5 * 1024 * 1024 * 1024)}"; max-free = "${toString (20 * 1024 * 1024 * 1024)}"; # automatically optimise symlinks @@ -121,15 +103,13 @@ with lib; { sandbox = true; # supported system features # TODO: "gccarch-core2" "gccarch-haswell" - system-features = ["nixos-tests" "kvm" "recursive-nix" "big-parallel"]; - # extra architectures supported by my builders + system-features = ["nixos-test" "kvm" "recursive-nix" "big-parallel"]; extra-platforms = config.boot.binfmt.emulatedSystems; - # continue building derivations if one fails + # continue building derivations even if one fails keep-going = true; - # show more log lines for failed builds + # show more log lines for failed builds, as this happens alot and is useful log-lines = 30; - # enable new nix command and flakes - # and also "unintended" recursion as well as content addresssed nix + # enable new nix command and flakes and also "unintended" recursion as well as content addresssed nix extra-experimental-features = [ "flakes" "nix-command" @@ -138,7 +118,7 @@ with lib; { "repl-flake" "auto-allocate-uids" ]; - # don't warn me that my git tree is dirty, I know + # ignore dirty working tree warn-dirty = false; # maximum number of parallel TCP connections used to fetch imports and binary caches, 0 means no limit http-connections = 50; @@ -151,15 +131,16 @@ with lib; { # substituters to use substituters = [ - "https://cache.ngi0.nixos.org" # content addressed nix cache (TODO) + "https://cache.ngi0.nixos.org" # content addressed nix cache "https://cache.nixos.org" # funny binary cache - "https://nixpkgs-wayland.cachix.org" # automated builds of *some* wayland packages + "https://nixpkgs-wayland.cachix.org" # some wayland packages "https://nix-community.cachix.org" # nix-community cache "https://hyprland.cachix.org" # hyprland "https://nix-gaming.cachix.org" # nix-gaming "https://nixpkgs-unfree.cachix.org" # unfree-package cache "https://numtide.cachix.org" # another unfree package cache "https://isabelroses.cachix.org" # precompiled binarys from my NUR + "https://neovim-flake.cachix.org" # a cache for notashelf's neovim flake ]; trusted-public-keys = [ @@ -172,6 +153,7 @@ with lib; { "nixpkgs-unfree.cachix.org-1:hqvoInulhbV4nJ9yJOEr+4wxhDV4xq2d1DK7S6Nj6rs=" "numtide.cachix.org-1:2ps1kLBUWjxIneOy1Ik6cQjb41X0iXVXeHigGmycPPE=" "isabelroses.cachix.org-1:mXdV/CMcPDaiTmkQ7/4+MzChpOe6Cb97njKmBQQmLPM=" + "neovim-flake.cachix.org-1:iyQ6lHFhnB5UkVpxhQqLJbneWBTzM8LBYOFPLNH4qZw=" ]; }; }; diff --git a/modules/common/core/system/boot/default.nix b/modules/common/core/system/os/boot/default.nix similarity index 100% rename from modules/common/core/system/boot/default.nix rename to modules/common/core/system/os/boot/default.nix index 8529c980b..c48141432 100644 --- a/modules/common/core/system/boot/default.nix +++ b/modules/common/core/system/os/boot/default.nix @@ -1,8 +1,8 @@ _: { imports = [ + ./generic ./loader - ./secure-boot ./plymouth - ./generic + ./secure-boot ]; } diff --git a/modules/common/core/system/os/boot/generic/default.nix b/modules/common/core/system/os/boot/generic/default.nix new file mode 100644 index 000000000..64863bd62 --- /dev/null +++ b/modules/common/core/system/os/boot/generic/default.nix @@ -0,0 +1,126 @@ +{ + lib, + config, + ... +}: let + inherit (lib) mkDefault mkForce mkOverride mkMerge mkIf optionals; + sys = config.modules.system; +in { + config = { + boot = { + consoleLogLevel = 0; + + # always use the latest kernel, love the unstablity + kernelPackages = mkOverride 500 sys.boot.kernel; + + extraModulePackages = mkDefault sys.boot.extraModulePackages; + extraModprobeConfig = mkDefault sys.boot.extraModprobeConfig; + # whether to enable support for Linux MD RAID arrays + # as of 23.11>, this throws a warning if neither MAILADDR nor PROGRAM are set + swraid.enable = mkDefault false; + + # shared config between bootloaders + # they are set unless system.boot.loader != none + loader = { + # if set to 0, space needs to be held to get the boot menu to appear + timeout = mkForce 2; + generationsDir.copyKernels = true; + + # we need to allow installation to modify EFI variables + efi.canTouchEfiVariables = true; + }; + + # if you have a lack of ram, you should avoid tmpfs to prevent hangups while compiling + tmp = { + # /tmp on tmpfs, lets it live on your ram + useTmpfs = sys.boot.tmpOnTmpfs; + + # If not using tmpfs, which is naturally purged on reboot, we must clean + # we have to clean /tmp + cleanOnBoot = mkDefault (!config.boot.tmp.useTmpfs); + }; + + # initrd and kernel tweaks + # read what each parameter or module does before doing so, it will defo break something otherwise + initrd = mkMerge [ + (mkIf sys.boot.enableInitrdTweaks { + # Verbosity of the initrd + # disabling verbosity removes only the mandatory messages generated by the NixOS + verbose = false; + + # strip copied binaries and libraries from inframs + # saves some nice space + systemd.strip = true; + + # enable systemd in initrd (experimental) + systemd.enable = true; + + # List of modules that are loaded by the initrd + kernelModules = [ + "nvme" + "xhci_pci" + "ahci" + "btrfs" + "cifs" + "sd_mod" + "dm_mod" + "tpm" + ]; + + # the set of kernel modules in the initial ramdisk used during the boot process + availableKernelModules = [ + "usbhid" + "sd_mod" + "dm_mod" + "uas" + "usb_storage" + "rtsx_pci_sdmmc" # Realtek SD card interface (btw i hate realtek) + ]; + }) + ]; + + # https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html + kernelParams = + (optionals sys.boot.enableKernelTweaks [ + # https://en.wikipedia.org/wiki/Kernel_page-table_isolation + # auto means kernel will automatically decide the pti state + "pti=auto" # on || off + + # disable the intel_idle (it stinks anyway) driver and use acpi_idle instead + "idle=nomwait" + + # enable IOMMU for devices used in passthrough and provide better host performance + "iommu=pt" + + # disable usb autosuspend + "usbcore.autosuspend=-1" + + # isables resume and restores original swap space + "noresume" + + # allow systemd to set and save the backlight state + "acpi_backlight=native" + + # prevent the kernel from blanking plymouth out of the fb + "fbcon=nodefer" + + # disable boot logo + "logo.nologo" + + # disable systemd status messages + # rd prefix means systemd-udev will be used instead of initrd + "rd.systemd.show_status=auto" + + # lower the udev log level to show only errors or worse + "rd.udev.log_level=3" + + # disable the cursor in vt to get a black screen during intermissions + "vt.global_cursor_default=0" + ]) + ++ (optionals sys.boot.silentBoot [ + # tell the kernel to not be verbose, the voices are too loud + "quite" + ]); + }; + }; +} diff --git a/modules/common/core/system/boot/loader/default.nix b/modules/common/core/system/os/boot/loader/default.nix similarity index 100% rename from modules/common/core/system/boot/loader/default.nix rename to modules/common/core/system/os/boot/loader/default.nix diff --git a/modules/common/core/system/boot/loader/grub/default.nix b/modules/common/core/system/os/boot/loader/grub/default.nix similarity index 100% rename from modules/common/core/system/boot/loader/grub/default.nix rename to modules/common/core/system/os/boot/loader/grub/default.nix diff --git a/modules/common/core/system/boot/loader/none/default.nix b/modules/common/core/system/os/boot/loader/none/default.nix similarity index 100% rename from modules/common/core/system/boot/loader/none/default.nix rename to modules/common/core/system/os/boot/loader/none/default.nix diff --git a/modules/common/core/system/boot/loader/systemd-boot/default.nix b/modules/common/core/system/os/boot/loader/systemd-boot/default.nix similarity index 66% rename from modules/common/core/system/boot/loader/systemd-boot/default.nix rename to modules/common/core/system/os/boot/loader/systemd-boot/default.nix index f6f8e0e75..bedff3b8d 100644 --- a/modules/common/core/system/boot/loader/systemd-boot/default.nix +++ b/modules/common/core/system/os/boot/loader/systemd-boot/default.nix @@ -13,14 +13,12 @@ in { { enable = mkDefault true; configurationLimit = null; - consoleMode = mkDefault "max"; # the default is "keep", can be overriden per host if need be + consoleMode = mkDefault "max"; # the default is "keep" - # Fix a security hole in place for backwards compatibility. See desc in - # nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix + # Fix a security hole. See desc in nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix editor = false; } // optionalAttrs cfg.memtest.enable { - # https://matrix.to/#/!sgkZKRutwatDMkYBHU:nixos.org/$iKnJUt1L_7E5bq7hStDPwv6_2HTBvNjwfcWxlKlF-k8?via=nixos.org&via=matrix.org&via=nixos.dev extraFiles."efi/memtest86plus/memtest.efi" = "${cfg.boot.memtest.package}/memtest.efi"; extraEntries."memtest86plus.conf" = '' title MemTest86+ diff --git a/modules/common/core/system/boot/plymouth/default.nix b/modules/common/core/system/os/boot/plymouth/default.nix similarity index 86% rename from modules/common/core/system/boot/plymouth/default.nix rename to modules/common/core/system/os/boot/plymouth/default.nix index 40f0f314c..3020fc1e7 100644 --- a/modules/common/core/system/boot/plymouth/default.nix +++ b/modules/common/core/system/os/boot/plymouth/default.nix @@ -1,6 +1,7 @@ { config, lib, + self', pkgs, ... }: let @@ -16,7 +17,7 @@ in { } // lib.optionalAttrs cfg.withThemes { theme = "catppuccin-mocha"; - themePackages = [pkgs.nur.repos.nekowinston.plymouth-theme-catppuccin]; + themePackages = [self'.packages.plymouth-theme-catppuccin]; }; # make plymouth work with sleep diff --git a/modules/common/core/system/boot/secure-boot/default.nix b/modules/common/core/system/os/boot/secure-boot/default.nix similarity index 54% rename from modules/common/core/system/boot/secure-boot/default.nix rename to modules/common/core/system/os/boot/secure-boot/default.nix index 3bcca5b8f..22500ea02 100644 --- a/modules/common/core/system/boot/secure-boot/default.nix +++ b/modules/common/core/system/os/boot/secure-boot/default.nix @@ -6,22 +6,19 @@ ... }: with lib; let - sys = config.modules.system.security; + sys = config.modules.system.boot; in { imports = [ inputs.lanzaboote.nixosModules.lanzaboote ]; - config = mkIf (sys.secureBoot) { + config = mkIf sys.secureBoot { environment.systemPackages = [ - # For debugging and troubleshooting Secure Boot. + # Secure Boot, my love keeping my valorant working on windows pkgs.sbctl ]; - # Lanzaboote currently replaces the systemd-boot module. - # This setting is usually set to true in configuration.nix - # generated at installation time. So we force it to false - # for now. + # Lanzaboote replaces the systemd-boot module. boot.loader.systemd-boot.enable = lib.mkForce false; boot = { diff --git a/modules/common/core/system/os/default.nix b/modules/common/core/system/os/default.nix index 6881df3ac..d9d389e4d 100644 --- a/modules/common/core/system/os/default.nix +++ b/modules/common/core/system/os/default.nix @@ -1,12 +1,12 @@ _: { imports = [ - ./display - ./environment - ./locale - ./network - ./programs - ./security - ./services - ./users + ./boot # boot and bootloader configurations + ./display # display protocol + ./environment # system enviroment + ./fs # file system confiurations + ./network # networking + ./programs # common programs + ./services # common services + ./users # who is on the system ]; } diff --git a/modules/common/core/system/os/display/wayland/default.nix b/modules/common/core/system/os/display/wayland/default.nix index 8a01a41da..5e872f11a 100644 --- a/modules/common/core/system/os/display/wayland/default.nix +++ b/modules/common/core/system/os/display/wayland/default.nix @@ -5,5 +5,6 @@ _: { ./environment.nix ./portals.nix ./overlay.nix + ./services.nix ]; } diff --git a/modules/common/core/system/os/display/wayland/environment.nix b/modules/common/core/system/os/display/wayland/environment.nix index 174604f28..f832b478e 100644 --- a/modules/common/core/system/os/display/wayland/environment.nix +++ b/modules/common/core/system/os/display/wayland/environment.nix @@ -2,12 +2,17 @@ config, lib, ... -}: -with lib; let +}: let + inherit (lib) mkIf; sys = config.modules.system.video; env = config.modules.usrEnv; in { config = mkIf (sys.enable && env.isWayland) { + environment.etc."greetd/environments".text = mkIf config.services.greetd.enable '' + ${lib.optionalString (env.desktop == "Hyprland") "Hyprland"} + fish + ''; + environment = { variables = { NIXOS_OZONE_WL = "1"; diff --git a/modules/common/core/system/os/display/wayland/portals.nix b/modules/common/core/system/os/display/wayland/portals.nix index 5533aac36..28cd9f449 100644 --- a/modules/common/core/system/os/display/wayland/portals.nix +++ b/modules/common/core/system/os/display/wayland/portals.nix @@ -8,15 +8,14 @@ env = config.modules.usrEnv; inherit (lib) mkForce mkIf; in { - config = mkIf (sys.video.enable) { + config = mkIf sys.video.enable { xdg.portal = { enable = true; extraPortals = with pkgs; [ xdg-desktop-portal-gtk ]; - # xdg-desktop-wlr (this section) is no longer needed, xdg-desktop-portal-hyprland - # will (and should) override this one, set to false or remove this section + wlr = { enable = mkForce (env.isWayland && env.desktop != "Hyprland"); settings = { diff --git a/modules/common/core/system/os/display/wayland/services.nix b/modules/common/core/system/os/display/wayland/services.nix new file mode 100644 index 000000000..5f991d3bd --- /dev/null +++ b/modules/common/core/system/os/display/wayland/services.nix @@ -0,0 +1,27 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib) mkIf getExe; + + cfg = config.modules.system.video; + env = config.modules.usrEnv; +in { + config = mkIf (cfg.enable && env.isWayland) { + systemd.services = { + seatd = { + enable = true; + description = "Seat management daemon"; + script = "${getExe pkgs.seatd} -g wheel"; + serviceConfig = { + Type = "simple"; + Restart = "always"; + RestartSec = "1"; + }; + wantedBy = ["multi-user.target"]; + }; + }; + }; +} diff --git a/modules/common/core/system/os/display/wayland/wm/hyprland.nix b/modules/common/core/system/os/display/wayland/wm/hyprland.nix index 2536a5dcc..9f693ed86 100644 --- a/modules/common/core/system/os/display/wayland/wm/hyprland.nix +++ b/modules/common/core/system/os/display/wayland/wm/hyprland.nix @@ -17,11 +17,7 @@ in { xdg.portal = { extraPortals = [ - (inputs'.xdg-portal-hyprland.packages.xdg-desktop-portal-hyprland.override { - hyprland-share-picker = inputs'.xdg-portal-hyprland.packages.hyprland-share-picker.override { - hyprland = inputs'.hyprland.packages.default; - }; - }) + inputs'.xdg-portal-hyprland.packages.xdg-desktop-portal-hyprland ]; }; }; diff --git a/modules/common/core/system/os/environment/default.nix b/modules/common/core/system/os/environment/default.nix index 9a4a03f18..e2fbdf33d 100644 --- a/modules/common/core/system/os/environment/default.nix +++ b/modules/common/core/system/os/environment/default.nix @@ -3,17 +3,23 @@ pkgs, ... }: { + imports = [ + ./locale.nix # locale settings + ]; + environment = { - # variables that I want to set globally on all systems + # the below can be done for faster shell reponse time but it can break things, and it did + # binsh = "${pkgs.dash}/bin/dash"; + variables = { EDITOR = "nvim"; - VISUAL = "nvim"; + VISUAL = "vscodium"; SYSTEMD_PAGERSECURE = "true"; PAGER = "less -FR"; FLAKE = "${config.modules.system.flakePath}"; }; - # packages I want pre-installed on all systems + # packages that should be on all deviecs systemPackages = with pkgs; [ git curl @@ -22,8 +28,15 @@ lshw ]; - # disable all packages installed by default, so that my system doesn't have anything - # that I myself have added + # disable all packages installed by default, i prefer my own packages defaultPackages = []; + + # enable completions for system packages + pathsToLink = ["/share/zsh" "/share/nushell" "/share/fish" "/share/bash-completion" "/share/nix-direnv"]; + + # https://github.com/NixOS/nixpkgs/issues/72394#issuecomment-549110501 + etc."mdadm.conf".text = '' + MAILADDR root + ''; }; } diff --git a/modules/common/core/system/os/locale/default.nix b/modules/common/core/system/os/environment/locale.nix similarity index 95% rename from modules/common/core/system/os/locale/default.nix rename to modules/common/core/system/os/environment/locale.nix index 1770d187f..0d26af089 100644 --- a/modules/common/core/system/os/locale/default.nix +++ b/modules/common/core/system/os/environment/locale.nix @@ -21,5 +21,6 @@ variant = "u24n"; in { font = "${pkgs.terminus_font}/share/consolefonts/ter-${variant}.psf.gz"; + keyMap = "en"; }; } diff --git a/modules/common/core/system/os/fs/default.nix b/modules/common/core/system/os/fs/default.nix new file mode 100644 index 000000000..22ff93473 --- /dev/null +++ b/modules/common/core/system/os/fs/default.nix @@ -0,0 +1,51 @@ +{ + lib, + config, + ... +}: +with lib; let + sys = config.modules.system; +in { + config = mkMerge [ + (mkIf (builtins.elem "btrfs" sys.fs) { + # clean btrfs devices + services.btrfs.autoScrub = { + enable = true; + fileSystems = ["/"]; + }; + + # fix: initrd.systemd.enable + boot = { + supportedFilesystems = ["btrfs"]; + initrd = { + supportedFilesystems = ["btrfs"]; + }; + }; + }) + + (mkIf (builtins.elem "ext4" sys.fs) { + boot = { + supportedFilesystems = ["ext4"]; + initrd = { + supportedFilesystems = ["ext4"]; + }; + }; + }) + + (mkIf (builtins.elem "exfat" sys.fs) { + boot = { + supportedFilesystems = ["exfat"]; + initrd = { + supportedFilesystems = ["exfat"]; + }; + }; + }) + + # accept both ntfs and ntfs3 as valid values + (mkIf ((builtins.elem "ntfs" sys.fs) || (builtins.elem "ntfs3" sys.fs)) { + boot = { + supportedFilesystems = ["ntfs"]; + }; + }) + ]; +} diff --git a/modules/common/core/system/os/network/blocker.nix b/modules/common/core/system/os/network/blocker.nix index fb63da0d6..2890dafe7 100644 --- a/modules/common/core/system/os/network/blocker.nix +++ b/modules/common/core/system/os/network/blocker.nix @@ -1,14 +1,12 @@ {config, ...}: let device = config.modules.device; in { - # this should block *most* junk sites - networking = { - stevenblack = { - enable = device.type != "server"; - block = [ - "fakenews" - "gambling" - ]; - }; + # remove stupid sites that i just don't want to see + networking.stevenblack = { + enable = device.type != "server"; + block = [ + "fakenews" + "gambling" + ]; }; } diff --git a/modules/common/core/system/os/network/default.nix b/modules/common/core/system/os/network/default.nix index 472a150de..77aa6d5d0 100644 --- a/modules/common/core/system/os/network/default.nix +++ b/modules/common/core/system/os/network/default.nix @@ -2,8 +2,11 @@ lib, config, ... -}: -with lib; { +}: let + inherit (lib) mkIf mkDefault mkForce genAttrs; + + dev = config.modules.device; +in { imports = [ ./blocker.nix ./firewall.nix @@ -17,22 +20,21 @@ with lib; { }; networking = { + # generate a host ID by hashing the hostname + hostId = builtins.substring 0 8 ( + builtins.hashString "md5" config.networking.hostName + ); + hostName = config.modules.system.hostname; - # global dhcp has been deprecated upstream - # use networkd instead - # individual interfaces are still managed through dhcp in hardware configurations + # global dhcp has been deprecated upstream, so we use networkd instead + # however individual interfaces are still managed through dhcp in hardware configurations useDHCP = mkDefault false; useNetworkd = mkDefault true; # dns nameservers = [ - # cloudflare, yuck - # shares data "1.1.1.1" "1.0.0.1" - - # quad9, said to be the best - # shares *less* data "9.9.9.9" ]; @@ -41,21 +43,26 @@ with lib; { plugins = []; dns = "systemd-resolved"; unmanaged = ["docker0" "rndis0"]; + wifi = { + # The below is disabled as my uni hated me for it + # macAddress = "random"; # use a random mac address on every boot, this can scew with static ip powersave = true; - #macAddress = "random"; # use a random mac address on every boot + scanRandMacAddress = true; # MAC address randomization of a Wi-Fi device during scanning }; + + ethernet.macAddress = mkIf (dev.type != "server") "random"; }; }; - # enable wireless database, it helps with finding the right channels + # enable wireless database, it helps keeping wifi speedy hardware.wirelessRegulatoryDatabase = true; # allow for the system to boot without waiting for the network interfaces are online - # speeds up boot times systemd = let ethernetDevices = [ "wlp1s0f0u8" # wifi dongle + "enp7s0" # ethernet interface on the motherboard ]; in { network.wait-online.enable = false; @@ -67,10 +74,10 @@ with lib; { systemd-networkd.stopIfChanged = false; systemd-resolved.stopIfChanged = false; } - // lib.concatMapAttrs (_: v: v) (lib.genAttrs ethernetDevices (device: { + // lib.concatMapAttrs (_: v: v) (genAttrs ethernetDevices (device: { # Assign an IP address when the device is plugged in rather than on startup. Needed to prevent # blocking the boot sequence when the device is unavailable, as it is hotpluggable. - "network-addresses-${device}".wantedBy = lib.mkForce ["sys-subsystem-net-devices-${device}.device"]; + "network-addresses-${device}".wantedBy = mkForce ["sys-subsystem-net-devices-${device}.device"]; })); }; } diff --git a/modules/common/core/system/os/network/firewall.nix b/modules/common/core/system/os/network/firewall.nix index d1359a6e4..87cc1cb8c 100644 --- a/modules/common/core/system/os/network/firewall.nix +++ b/modules/common/core/system/os/network/firewall.nix @@ -4,9 +4,31 @@ config, ... }: let - inherit (lib) mkDefault mkForce; - device = config.modules.device; + inherit (lib) mkDefault mkForce mkIf; + inherit (config.modules) device; in { + environment.etc."fail2ban/filter.d/vaultwarden.conf" = { + inherit (config.services.vaultwarden) enable; + text = '' + [INCLUDES] + before = common.conf + [Definition] + failregex = ^.*Username or password is incorrect\. Try again\. IP: \. Username:.*$ + ignoreregex = + ''; + }; + + environment.etc."fail2ban/filter.d/vaultwarden-admin.conf" = { + inherit (config.services.vaultwarden) enable; + text = '' + [INCLUDES] + before = common.conf + [Definition] + failregex = ^.*Invalid admin token\. IP: .*$ + ignoreregex = + ''; + }; + services = { # enable opensnitch firewall # inactive until opensnitch UI is opened @@ -19,6 +41,7 @@ in { maxretry = 7; ignoreIP = [ "127.0.0.0/8" + "10.0.0.0/8" "192.168.86.0/16" ]; @@ -28,6 +51,27 @@ in { port = 22 mode = aggressive ''; + + vaultwarden = '' + enabled = true + port = 80,443,8822 + filter = vaultwarden + banaction = %(banaction_allports)s + logpath = /var/log/vaultwarden.log + maxretry = 3 + bantime = 14400 + findtime = 14400 + ''; + vaultwarden-admin = '' + enabled = true + port = 80,443 + filter = vaultwarden-admin + banaction = %(banaction_allports)s + logpath = /var/log/vaultwarden.log + maxretry = 3 + bantime = 14400 + findtime = 14400 + ''; }; bantime-increment = { @@ -44,15 +88,18 @@ in { firewall = { enable = mkDefault true; package = mkDefault pkgs.iptables-nftables-compat; - allowedTCPPorts = []; + allowedTCPPorts = [ + 443 + 8080 + ]; allowedUDPPorts = []; - allowedTCPPortRanges = [ + allowedTCPPortRanges = mkIf (device.type != "server") [ { from = 1714; to = 1764; } #KDEconnect ]; - allowedUDPPortRanges = [ + allowedUDPPortRanges = mkIf (device.type != "server") [ { from = 1714; to = 1764; diff --git a/modules/common/core/system/os/network/optimise.nix b/modules/common/core/system/os/network/optimise.nix index ea222197b..4f00c3870 100644 --- a/modules/common/core/system/os/network/optimise.nix +++ b/modules/common/core/system/os/network/optimise.nix @@ -51,7 +51,6 @@ in { "net.ipv4.tcp_congestion_control" = "bbr"; "net.core.default_qdisc" = "cake"; - # Other stuff I am too lazy to document "net.core.optmem_max" = 65536; "net.core.rmem_default" = 1048576; "net.core.rmem_max" = 16777216; diff --git a/modules/common/core/system/os/network/ssh.nix b/modules/common/core/system/os/network/ssh.nix index e1537b435..85fc6119d 100644 --- a/modules/common/core/system/os/network/ssh.nix +++ b/modules/common/core/system/os/network/ssh.nix @@ -34,7 +34,6 @@ in { ]; }; - # the ssh port(s) should be automatically passed to the firewall's allowedTCPports openFirewall = true; # the port(s) openssh daemon should listen on ports = [22]; diff --git a/modules/common/core/system/os/programs/default.nix b/modules/common/core/system/os/programs/default.nix index cb289be90..d2be97cf7 100644 --- a/modules/common/core/system/os/programs/default.nix +++ b/modules/common/core/system/os/programs/default.nix @@ -10,7 +10,6 @@ ''; }; # less pager - # TODO: package moar for nix less.enable = true; fish.enable = true; diff --git a/modules/common/core/system/os/security/default.nix b/modules/common/core/system/os/security/default.nix deleted file mode 100644 index 199953ace..000000000 --- a/modules/common/core/system/os/security/default.nix +++ /dev/null @@ -1,140 +0,0 @@ -{ - config, - pkgs, - lib, - ... -}: -with lib; let - sys = config.modules.system; -in { - security = { - protectKernelImage = true; - lockKernelModules = false; # breaks virtd, wireguard and iptables - - # force-enable the Page Table Isolation (PTI) Linux kernel feature - forcePageTableIsolation = true; - - # User namespaces are required for sandboxing. Better than nothing imo. - allowUserNamespaces = true; - - apparmor = { - enable = true; - killUnconfinedConfinables = true; - packages = [pkgs.apparmor-profiles]; - }; - - virtualisation = { - # flush the L1 data cache before entering guests - flushL1DataCache = "always"; - }; - - auditd.enable = true; - audit = { - enable = true; - rules = [ - "-a exit,always -F arch=b64 -S execve" - ]; - }; - - pam = { - loginLimits = [ - { - domain = "@wheel"; - item = "nofile"; - type = "soft"; - value = "524288"; - } - { - domain = "@wheel"; - item = "nofile"; - type = "hard"; - value = "1048576"; - } - ]; - - services = { - swaylock.text = "auth include login"; - gtklock.text = "auth include login"; - }; - }; - - sudo = { - wheelNeedsPassword = false; - enable = mkDefault true; - execWheelOnly = true; - extraConfig = '' - # rollback results in sudo lectures after each reboot - Defaults lecture = never - Defaults pwfeedback - Defaults env_keep += "EDITOR PATH" - Defaults timestamp_timeout = 300 - Defaults passprompt="[31m sudo: password for %p@%h, running as %U:[0m " - ''; - }; - }; - - boot.kernel.sysctl = { - # The Magic SysRq key is a key combo that allows users connected to the - # system console of a Linux kernel to perform some low-level commands. - # Disable it, since we don't need it, and is a potential security concern. - "kernel.sysrq" = 0; - # Restrict ptrace() usage to processes with a pre-defined relationship - # (e.g., parent/child) - "kernel.yama.ptrace_scope" = 2; - # Hide kptrs even for processes with CAP_SYSLOG - "kernel.kptr_restrict" = 2; - # Disable bpf() JIT (to eliminate spray attacks) - "net.core.bpf_jit_enable" = false; - # Disable ftrace debugging - "kernel.ftrace_enabled" = false; - }; - - boot.blacklistedKernelModules = - [ - # Obscure network protocols - "ax25" - "netrom" - "rose" - # Old or rare or insufficiently audited filesystems - "adfs" - "affs" - "bfs" - "befs" - "cramfs" - "efs" - "erofs" - "exofs" - "freevxfs" - "f2fs" - "vivid" - "gfs2" - "ksmbd" - "nfsv4" - "nfsv3" - "nfs" - "cramfs" - "freevxfs" - "jffs2" - "hfs" - "hfsplus" - "squashfs" - "udf" - "hpfs" - "jfs" - "minix" - "nilfs2" - "omfs" - "qnx4" - "qnx6" - "sysv" - ] - ++ lib.optionals (!sys.security.fixWebcam) [ - "uvcvideo" # this is why your webcam no worky - ] - ++ lib.optionals (!sys.bluetooth.enable) [ - "btusb" # let bluetooth dongles work - ] - ++ lib.optionals (!config.modules.services.smb.enable) [ - "cifs" # allows smb to work - ]; -} diff --git a/modules/common/core/system/os/services/default.nix b/modules/common/core/system/os/services/default.nix index ea07d7c0a..bcee7a383 100644 --- a/modules/common/core/system/os/services/default.nix +++ b/modules/common/core/system/os/services/default.nix @@ -1,6 +1,7 @@ { config, inputs, + lib, ... }: { imports = [ @@ -11,14 +12,12 @@ vscode-server.enable = config.modules.services.vscode-server.enable; # monitor and control temparature thermald.enable = true; - # handle ACPI events - acpid.enable = true; # discard blocks that are not in use by the filesystem, good for SSDs fstrim.enable = true; # firmware updater for machine hardware fwupd.enable = true; - # I don't use lvm, can be disabled - lvm.enable = false; + # Not using lvm + lvm.enable = lib.mkDefault false; # enable smartd monitoering smartd.enable = true; # limit systemd journal size diff --git a/modules/common/core/system/os/services/systemd.nix b/modules/common/core/system/os/services/systemd.nix index 404bfd3d0..91f856b7e 100644 --- a/modules/common/core/system/os/services/systemd.nix +++ b/modules/common/core/system/os/services/systemd.nix @@ -16,7 +16,6 @@ } // lib.optionalAttrs config.security.auditd.enable { # a systemd timer to clean /var/log/audit.log daily - # this can probably be weekly, but daily means we get to clean it every 2-3 days instead of once a week timers."clean-audit-log" = { description = "Periodically clean audit log"; wantedBy = ["timers.target"]; diff --git a/modules/common/core/system/os/users/isabel.nix b/modules/common/core/system/os/users/isabel.nix index 65b2bc8a5..44b168794 100644 --- a/modules/common/core/system/os/users/isabel.nix +++ b/modules/common/core/system/os/users/isabel.nix @@ -5,7 +5,7 @@ ... }: let keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC3AeKdY2eQmK78Ll3bms8yxmqe7BPWMph+QLZ2Fy33XGVDyxTSAK3LJWwfEmjEoQE/4UiFxnrzslrIsIuRYV//tV+aPfmyoBkAxbaWaJ3aujZYGpxD86MtnFwdfNRcl2fKJnTbPSAY0VM5p08A/eNe40WVwXAbXFHyJLbMn5Se1WGuZrWOtoD9reVjRNOh1EkpZVrbjv3rWpK4SDcJCdA9dGxxVXMsy7ErIOzit/g/4IQ+F8zEQRRbSToZYCU2+bFQP5Y1ujPMCxwtYfNEq0rrvgI73ejwhJAdjRHoKv2q8qN9HzYLm3nVipcj6mpV9T3ENHpKuyz1oB735lUh7vcJzu+cgix91RO3bKUtQ0yaUc1nogf8pceGTCbByHxy0qeNy9IgXfW1ZMJ7H1GttzUIsa4q1HLmj1MfbSvbdP4uU+gLflZgm1/9+N0IA4md4Ljpwgik9CsaVucaC/0vPnzASVTrvpMDNu/TlKLytdLKpbQ6Yk1YZPvUbVUZ3xfvJOE= isabel" + ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMQDiHbMSinj8twL9cTgPOfI6OMexrTZyHX27T8gnMj2 isabel@isabelroses.com'' ]; in { boot.initrd.network.ssh.authorizedKeys = keys; diff --git a/modules/common/core/system/os/users/root.nix b/modules/common/core/system/os/users/root.nix index 7a8b9b2f3..672bcefa2 100644 --- a/modules/common/core/system/os/users/root.nix +++ b/modules/common/core/system/os/users/root.nix @@ -1,5 +1,9 @@ _: { users.users.root = { initialPassword = "changeme"; + + openssh.authorizedKeys.keys = [ + ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMQDiHbMSinj8twL9cTgPOfI6OMexrTZyHX27T8gnMj2'' + ]; }; } diff --git a/modules/common/core/system/security/auditd.nix b/modules/common/core/system/security/auditd.nix new file mode 100644 index 000000000..974b8daeb --- /dev/null +++ b/modules/common/core/system/security/auditd.nix @@ -0,0 +1,16 @@ +{config, ...}: let + cfg = config.modules.system.security; +in { + security = { + # system audit + auditd.enable = cfg.auditd.enable; + audit = { + enable = cfg.auditd.enable; + backlogLimit = 8192; + failureMode = "printk"; + rules = [ + "-a exit,always -F arch=b64 -S execve" + ]; + }; + }; +} diff --git a/modules/common/core/system/security/clamav.nix b/modules/common/core/system/security/clamav.nix new file mode 100644 index 000000000..d52cc36ed --- /dev/null +++ b/modules/common/core/system/security/clamav.nix @@ -0,0 +1,77 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib) mkIf; + + sys = config.modules.system; +in { + config = mkIf sys.security.clamav.enable { + services.clamav = { + daemon = {enable = true;} // sys.security.clamav.daemon; + updater = {enable = true;} // sys.security.clamav.updater; + }; + + systemd = { + tmpfiles.rules = [ + "D /var/lib/clamav 755 clamav clamav" + ]; + + services = { + clamav-daemon = { + serviceConfig = { + PrivateTmp = lib.mkForce "no"; + PrivateNetwork = lib.mkForce "no"; + Restart = "always"; + }; + + unitConfig = { + # only start clamav when required database files are present + # especially useful if you are deploying headlessly and don't want a service fail instantly + ConditionPathExistsGlob = [ + "/var/lib/clamav/main.{c[vl]d,inc}" + "/var/lib/clamav/daily.{c[vl]d,inc}" + ]; + }; + }; + + clamav-init-database = { + wantedBy = ["clamav-daemon.service"]; + before = ["clamav-daemon.service"]; + serviceConfig.ExecStart = "systemctl start clamav-freshclam"; + unitConfig = { + # opposite condition of clamav-daemon: only run this service if + # database files are not present in the database directory + ConditionPathExistsGlob = [ + "!/var/lib/clamav/main.{c[vl]d,inc}" + "!/var/lib/clamav/daily.{c[vl]d,inc}" + ]; + }; + }; + + clamav-freshclam = { + wants = ["clamav-daemon.service"]; + serviceConfig = { + ExecStart = let + message = "Updating ClamAV database"; + in '' + ${pkgs.coreutils}/bin/echo -en ${message} + ''; + SuccessExitStatus = lib.mkForce [11 40 50 51 52 53 54 55 56 57 58 59 60 61 62]; + }; + }; + }; + + timers.clamav-freshclam.timerConfig = { + # the default is to run the timer hourly but we do not want our entire infra to be overloaded + # trying to run clamscan at the same time. randomize the timer to something around an hour + # so that the window is consistent, but the load is not + RandomizedDelaySec = "60m"; + FixedRandomDelay = true; + Persistent = true; + }; + }; + }; +} diff --git a/modules/common/core/system/security/default.nix b/modules/common/core/system/security/default.nix new file mode 100644 index 000000000..d6425872a --- /dev/null +++ b/modules/common/core/system/security/default.nix @@ -0,0 +1,11 @@ +_: { + imports = [ + ./auditd.nix # auditd + ./clamav.nix # clamav antivirus + ./kernel.nix # kernel hardening + ./pam.nix # pam configuration + ./polkit.nix # polkit configuration + ./sudo.nix # sudo rules and configuration + ./virtualization.nix # hypervisor hardening + ]; +} diff --git a/modules/common/core/system/security/kernel.nix b/modules/common/core/system/security/kernel.nix new file mode 100644 index 000000000..3c2ca6393 --- /dev/null +++ b/modules/common/core/system/security/kernel.nix @@ -0,0 +1,142 @@ +{ + config, + lib, + pkgs, + ... +}: let + sys = config.modules.system; + inherit (lib) optionals concatLists; +in { + security = { + protectKernelImage = true; + lockKernelModules = false; # breaks virtd, wireguard and iptables + + # force-enable the Page Table Isolation (PTI) Linux kernel feature + forcePageTableIsolation = true; + + # User namespaces are required for sandboxing. + allowUserNamespaces = true; + + # Disable unprivileged user namespaces, unless containers are enabled + unprivilegedUsernsClone = config.virtualisation.containers.enable; + + # apparmor configuration + apparmor = { + enable = true; + killUnconfinedConfinables = true; + packages = [pkgs.apparmor-profiles]; + }; + }; + + boot = { + kernel.sysctl = { + # The Magic SysRq key is a key combo that allows users connected to the + # system console of a Linux kernel to perform some low-level commands. + # Disable it, since we don't need it, and is a potential security concern. + "kernel.sysrq" = 0; + # Restrict ptrace() usage to processes with a pre-defined relationship + # (e.g., parent/child) + "kernel.yama.ptrace_scope" = 2; + # Hide kptrs even for processes with CAP_SYSLOG + "kernel.kptr_restrict" = 2; + # Disable bpf() JIT (to eliminate spray attacks) + "net.core.bpf_jit_enable" = false; + # Disable ftrace debugging + "kernel.ftrace_enabled" = false; + # Avoid kernel memory address exposures via dmesg (this value can also be set by CONFIG_SECURITY_DMESG_RESTRICT). + "kernel.dmesg_restrict" = 1; + }; + + # https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html + kernelParams = [ + # make stack-based attacks on the kernel harder + "randomize_kstack_offset=on" + + # controls the behavior of vsyscalls. this has been defaulted to none back in 2016 - break really old binaries for security + "vsyscall=none" + + # reduce most of the exposure of a heap attack to a single cache + "slab_nomerge" + + # only allow signed modules + "module.sig_enforce=1" + + # blocks access to all kernel memory, even preventing administrators from being able to inspect and probe the kernel + "lockdown=confidentiality" + + # enable buddy allocator free poisoning + "page_poison=1" + + # performance improvement for direct-mapped memory-side-cache utilization, reduces the predictability of page allocations + "page_alloc.shuffle=1" + + # for debugging kernel-level slab issues + "slub_debug=FZP" + + # disable sysrq keys. sysrq is seful for debugging, but also insecure + "sysrq_always_enabled=0" # 0 | 1 # 0 means disabled + + # ignore access time (atime) updates on files, except when they coincide with updates to the ctime or mtime + "rootflags=noatime" + + # linux security modules + "lsm=landlock,lockdown,yama,apparmor,bpf" + + # prevent the kernel from blanking plymouth out of the fb + "fbcon=nodefer" + ]; + + blacklistedKernelModules = concatLists [ + [ + # Obscure network protocols + "ax25" + "netrom" + "rose" + ] + [ + # Old or rare or insufficiently audited filesystems + "adfs" + "affs" + "bfs" + "befs" + "cramfs" + "efs" + "erofs" + "exofs" + "freevxfs" + "f2fs" + "vivid" + "gfs2" + "ksmbd" + "nfsv4" + "nfsv3" + "cifs" + "nfs" + "cramfs" + "freevxfs" + "jffs2" + "hfs" + "hfsplus" + "squashfs" + "udf" + "hpfs" + "jfs" + "minix" + "nilfs2" + "omfs" + "qnx4" + "qnx6" + "sysv" + ] + (optionals (!sys.security.fixWebcam) [ + "uvcvideo" # this is why your webcam no worky + ]) + (optionals (!sys.bluetooth.enable) [ + "btusb" # let bluetooth dongles work + ]) + (optionals (!config.modules.services.smb.enable) [ + "cifs" # allows smb to work + ]) + ]; + }; +} diff --git a/modules/common/core/system/security/pam.nix b/modules/common/core/system/security/pam.nix new file mode 100644 index 000000000..c80560e98 --- /dev/null +++ b/modules/common/core/system/security/pam.nix @@ -0,0 +1,29 @@ +_: { + security = { + pam = { + # fix "too many files open" errors while writing a lot of data at once + # was previously a huge issue when rebuilding + loginLimits = [ + { + domain = "@wheel"; + item = "nofile"; + type = "soft"; + value = "524288"; + } + { + domain = "@wheel"; + item = "nofile"; + type = "hard"; + value = "1048576"; + } + ]; + + # allow screen lockers to also unlock the screen + # (e.g. swaylock, gtklock) + services = { + swaylock.text = "auth include login"; + gtklock.text = "auth include login"; + }; + }; + }; +} diff --git a/modules/common/core/system/security/polkit.nix b/modules/common/core/system/security/polkit.nix new file mode 100644 index 000000000..5d9c7a053 --- /dev/null +++ b/modules/common/core/system/security/polkit.nix @@ -0,0 +1,20 @@ +{ + config, + lib, + ... +}: { + # have polkit log all actions + security.polkit = { + enable = true; + debug = lib.mkDefault true; + + # the below configuration depends on security.polkit.debug being set to true + # so we have it written only if debugging is enabled + extraConfig = lib.mkIf config.security.polkit.debug '' + /* Log authorization checks. */ + polkit.addRule(function(action, subject) { + polkit.log("user " + subject.user + " is attempting action " + action.id + " from PID " + subject.pid); + }); + ''; + }; +} diff --git a/modules/common/core/system/security/sudo.nix b/modules/common/core/system/security/sudo.nix new file mode 100644 index 000000000..b15c9ebd7 --- /dev/null +++ b/modules/common/core/system/security/sudo.nix @@ -0,0 +1,68 @@ +{ + lib, + pkgs, + ... +}: let + inherit (lib) mkDefault; +in { + security = { + # sudo-rs is still a feature-incomplete sudo fork that can and will mess things up + sudo-rs.enable = lib.mkForce false; + + sudo = { + enable = true; + + # wheelNeedsPassword = false means wheel group can execute commands without a password + # so just disable it, it only hurt security, BUT ... see below what commands can be run without password + wheelNeedsPassword = mkDefault false; + + # only allow members of the wheel group to execute sudo + execWheelOnly = true; + + # i dont like lectures + extraConfig = '' + Defaults lecture = never + Defaults pwfeedback + Defaults env_keep += "EDITOR PATH DISPLAY" + Defaults timestamp_timeout = 300 + ''; + + extraRules = [ + { + # allow wheel group to run nixos-rebuild without password + groups = ["sudo" "wheel"]; + commands = let + currentSystem = "/run/current-system/"; + storePath = "/nix/store/"; + in [ + { + command = "${storePath}/*/bin/switch-to-configuration"; + options = ["SETENV" "NOPASSWD"]; + } + { + command = "${currentSystem}/sw/bin/nix-store"; + options = ["SETENV" "NOPASSWD"]; + } + { + command = "${currentSystem}/sw/bin/nix-env"; + options = ["SETENV" "NOPASSWD"]; + } + { + # let wheel group collect garbage without password + command = "${currentSystem}/sw/bin/nix-collect-garbage"; + options = ["SETENV" "NOPASSWD"]; + } + { + command = "${pkgs.nixos-rebuild}/bin/nixos-rebuild"; + options = ["SETENV" "NOPASSWD"]; + } + { + command = "/nix/var/nix/profiles/system/specialisation/*/bin/switch-to-configuration"; + options = ["SETENV" "NOPASSWD"]; + } + ]; + } + ]; + }; + }; +} diff --git a/modules/common/core/system/security/virtualization.nix b/modules/common/core/system/security/virtualization.nix new file mode 100644 index 000000000..f3e3107ea --- /dev/null +++ b/modules/common/core/system/security/virtualization.nix @@ -0,0 +1,6 @@ +_: { + security.virtualisation = { + # flush the L1 data cache before entering guests + flushL1DataCache = "always"; + }; +} diff --git a/modules/common/core/system/smb/default.nix b/modules/common/core/system/smb/default.nix index 64ed5ec6b..b53a14e84 100644 --- a/modules/common/core/system/smb/default.nix +++ b/modules/common/core/system/smb/default.nix @@ -9,7 +9,6 @@ with lib; let in { imports = [ ./recive - ./host ]; config = mkIf (smb.enable) { diff --git a/modules/common/core/system/smb/host/default.nix b/modules/common/core/system/smb/host/default.nix deleted file mode 100644 index 0967ef424..000000000 --- a/modules/common/core/system/smb/host/default.nix +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/modules/common/core/system/virtualization/default.nix b/modules/common/core/system/virtualization/default.nix index 742f62f16..dfaad8cf7 100644 --- a/modules/common/core/system/virtualization/default.nix +++ b/modules/common/core/system/virtualization/default.nix @@ -3,30 +3,39 @@ config, pkgs, ... -}: -with lib; let - sys = config.modules.system.virtualization; +}: let + inherit (lib) optionals mkIf concatLists; + sys = config.modules.system; + cfg = sys.virtualization; in { - config = mkIf sys.enable { + config = mkIf cfg.enable { environment.systemPackages = with pkgs; - [] - ++ optionals sys.qemu.enable [ - virt-manager - virt-viewer - ] - ++ optionals sys.docker.enable [ - docker - docker-compose - ] - ++ optionals sys.distrobox.enable [ - distrobox - ] - ++ optionals sys.waydroid.enable [ - waydroid + concatLists [ + (optionals cfg.qemu.enable [ + virt-manager + virt-viewer + ]) + (optionals cfg.docker.enable [ + podman + podman-compose + ]) + (optionals (cfg.docker.enable && sys.video.enable) [ + lxd + ]) + (optionals cfg.distrobox.enable [ + distrobox + ]) + (optionals cfg.waydroid.enable [ + waydroid + ]) ]; - virtualisation = mkIf sys.enable { - libvirtd = { + virtualisation = { + # qemu + kvmgt.enable = true; + spiceUSBRedirection.enable = true; + + libvirtd = mkIf cfg.qemu.enable { enable = true; qemu = { package = pkgs.qemu_kvm; @@ -38,17 +47,45 @@ in { }; }; - docker = mkIf sys.docker.enable { + # podman + podman = mkIf (cfg.docker.enable || cfg.podman.enable) { enable = true; - + dockerCompat = true; + dockerSocket.enable = true; + defaultNetwork.settings = { + dns_enabled = true; + }; enableNvidia = builtins.any (driver: driver == "nvidia") config.services.xserver.videoDrivers; - autoPrune = { enable = true; flags = ["--all"]; dates = "weekly"; }; }; + + waydroid.enable = cfg.waydroid.enable; + lxd.enable = cfg.waydroid.enable; + }; + systemd.user = mkIf cfg.distrobox.enable { + timers."distrobox-update" = { + enable = true; + wantedBy = ["timers.target"]; + timerConfig = { + OnBootSec = "1h"; + OnUnitActiveSec = "1d"; + Unit = "distrobox-update.service"; + }; + }; + + services."distrobox-update" = { + enable = true; + script = '' + ${pkgs.distrobox}/bin/distrobox upgrade --all + ''; + serviceConfig = { + Type = "oneshot"; + }; + }; }; }; } diff --git a/modules/common/options/device/default.nix b/modules/common/options/device/default.nix deleted file mode 100644 index 60e8d34b1..000000000 --- a/modules/common/options/device/default.nix +++ /dev/null @@ -1,53 +0,0 @@ -{lib, ...}: -with lib; { - options.modules.device = { - type = mkOption { - type = types.enum ["laptop" "desktop" "server" "hybrid" "lite" "vm"]; - default = null; - }; - - # the type of cpu your system has - vm and regular cpus currently do not differ - # as I do not work with vms, but they have been added for forward-compatibility - cpu = mkOption { - type = types.enum ["pi" "intel" "vm-intel" "amd" "vm-amd" null]; - default = null; - }; - - gpu = mkOption { - type = types.enum ["amd" "intel" "nvidia" null]; - default = null; - description = "the manifacturer/type of the primary system gpu"; - }; - - hasTPM = mkEnableOption "Whether the system has tpm support"; - - monitors = mkOption { - type = with types; listOf str; - default = []; - description = '' - this does not affect any drivers and such, it is only necessary for - declaring things like monitors in window manager configurations - you can avoid declaring this, but I'd rather if you did declare - ''; - }; - - # bluetooth is an insecure protocol if left unchedked, so while this defaults to true - # but the bluetooth.enable option does and should not. - hasBluetooth = mkOption { - type = types.bool; - default = true; - description = "Whether or not the system has bluetooth support"; - }; - - hasSound = mkOption { - type = types.bool; - default = true; - description = "Whether the system has sound support (usually true except for servers)"; - }; - - keyboard = mkOption { - type = types.enum ["us" "gb"]; - default = "gb"; - }; - }; -} diff --git a/modules/common/options/programs/default.nix b/modules/common/options/programs/default.nix deleted file mode 100644 index 4715b8dbb..000000000 --- a/modules/common/options/programs/default.nix +++ /dev/null @@ -1,91 +0,0 @@ -{lib, ...}: -with lib; { - imports = [./services.nix]; - # this module provides overrides for certain defaults and lets you set - # default programs for referencing in other config files. - options.modules = { - programs = { - # "override" is a simple option that sets the programs' state to the oppossite of their default - override = { - # override basic desktop applications - # an example override for the libreoffice program - # if set to true, libreoffice module will not be enabled as it is by default - libreoffice = mkEnableOption "Override Libreoffice suite"; - }; - - # TODO: turn those into overrides - # load GUI and CLI programs by default, but check if those overrides are enabled - # so that they can be disabled at will - cli = { - enable = mkEnableOption "Enable CLI programs"; - }; - tui = { - enable = mkEnableOption "Enable TUI programs"; - }; - gui = { - enable = mkEnableOption "Enable GUI programs"; - }; - - gaming = { - enable = mkEnableOption "Enable packages required for the device to be gaming-ready"; - gamescope.enable = mkEnableOption "Gamescope compositing manager" // {default = config.modules.programs.gaming.enable;}; - }; - - git = { - signingKey = mkOption { - type = types.str; - default = ""; - description = "The default gpg key used for signing commits"; - }; - }; - - nur = { - enable = mkEnableOption "Use nur for extra packages"; - bella = mkEnableOption "Enable the isabelroses nur extra packages"; - nekowinston = mkEnableOption "Enables the nekowinston nur extra packages"; - }; - - # default program options - default = { - # what program should be used as the default terminal - terminal = mkOption { - type = types.enum ["alacritty" "kitty" "wezterm" "foot"]; - default = "kitty"; - }; - - fileManager = mkOption { - type = types.enum ["thunar" "dolphin" "nemo"]; - default = "thunar"; - }; - - browser = mkOption { - type = types.enum ["firefox" "chromium"]; - default = "chromium"; - }; - - editor = mkOption { - type = types.enum ["nvim" "codium"]; - default = "nvim"; - }; - - launcher = mkOption { - type = types.enum ["rofi" "wofi"]; - default = "rofi"; - }; - - bar = mkOption { - type = types.enum ["eww" "waybar" "ags"]; - default = "eww"; - }; - - screenLock = mkOption { - type = with types; nullOr (enum ["swaylock" "gtklock"]); - default = "gtklock"; - description = lib.mdDoc '' - The lockscreen module to be loaded by home-manager. - ''; - }; - }; - }; - }; -} diff --git a/modules/common/options/programs/services.nix b/modules/common/options/programs/services.nix deleted file mode 100644 index 3bc5a4522..000000000 --- a/modules/common/options/programs/services.nix +++ /dev/null @@ -1,43 +0,0 @@ -{lib, ...}: -with lib; { - options.modules.services = { - smb = { - enable = mkEnableOption "Enables smb shares"; - host.enable = mkEnableOption "Enables hosting of smb shares"; - - # should smb shares be enabled as a recpient machine - recive = { - general = mkEnableOption "genral share"; - media = mkEnableOption "media share"; - }; - }; - - jellyfin = { - enable = mkEnableOption "Enables the jellyfin service"; - asDockerContainer = mkEnableOption "Enables the service as a docker container"; - }; - - cloudflare = { - enable = mkEnableOption "Enables cloudflared tunnels"; - id = mkOption { - type = types.str; - default = ""; - description = "The cloudflared tunnel id"; - }; - }; - - mailserver.enable = mkEnableOption "Enable the mailserver service"; - - gitea.enable = mkEnableOption "Enable the gitea service"; - - vaultwarden.enable = mkEnableOption "Enable the vaultwarden service"; - - photoprism.enable = mkEnableOption "Enable the photoprism service"; - - vscode-server.enable = mkEnableOption "Enables remote ssh vscode server"; - - isabelroses-web.enable = mkEnableOption "Enables my website"; - - searxng.enable = mkEnableOption "Enables searxng search engine service"; - }; -} diff --git a/modules/common/options/system/activation.nix b/modules/common/options/system/activation.nix deleted file mode 100644 index 93647096c..000000000 --- a/modules/common/options/system/activation.nix +++ /dev/null @@ -1,7 +0,0 @@ -{lib, ...}: let - inherit (lib) mkEnableOption; -in { - options.modules.system.activation = { - diffGenerations = mkEnableOption "diff view between rebuilds"; - }; -} diff --git a/modules/common/options/system/boot.nix b/modules/common/options/system/boot.nix deleted file mode 100644 index 716b0e0ea..000000000 --- a/modules/common/options/system/boot.nix +++ /dev/null @@ -1,50 +0,0 @@ -{ - lib, - pkgs, - ... -}: -with lib; { - options.modules.system.boot = { - enableKernelTweaks = mkEnableOption "security and performance related kernel parameters"; - enableInitrdTweaks = mkEnableOption "quality of life tweaks for the initrd stage"; - recommendedLoaderConfig = mkEnableOption "tweaks for common bootloader configs per my liking"; - loadRecommendedModules = mkEnableOption "kernel modules that accommodate for most use cases"; - - extraKernelParams = mkOption { - type = with types; listOf str; - default = []; - }; - - kernel = mkOption { - type = types.raw; - default = pkgs.linuxPackages_latest; - }; - - # the bootloader that should be used - loader = mkOption { - type = types.enum ["none" "grub" "systemd-boot"]; - default = "none"; - description = "The bootloader that should be used for the device."; - }; - - device = mkOption { - type = with types; nullOr str; - default = "nodev"; - description = "The device to install the bootloader to."; - }; - - plymouth = { - enable = mkEnableOption "plymouth boot splash"; - withThemes = mkEnableOption "plymouth theme"; - }; - - memtest = { - enable = mkEnableOption "memtest86+"; - package = mkOption { - type = types.package; - default = pkgs.memtest86plus; - description = "The memtest package to use."; - }; - }; - }; -} diff --git a/modules/common/options/system/default.nix b/modules/common/options/system/default.nix deleted file mode 100644 index ca998407b..000000000 --- a/modules/common/options/system/default.nix +++ /dev/null @@ -1,64 +0,0 @@ -{ - lib, - config, - ... -}: -with lib; { - imports = [ - ./activation.nix - ./boot.nix - ./networking.nix - ./security.nix - ./virtualization.nix - ]; - - options.modules.system = { - # the default user (not users) you plan to use on a specific device - # this will dictate the initial home-manager settings if home-manager is - # enabled in usrenv - users = mkOption { - type = with types; listOf str; - default = ["isabel"]; - description = "The users of your system"; - }; - - mainUser = mkOption { - type = types.enum config.modules.system.users; - description = "The username of the main user for your system"; - default = builtins.elemAt config.modules.system.users 0; - }; - - hostname = mkOption { - type = types.str; - description = "The name of the device for the system"; - }; - - # the path to the flake - flakePath = mkOption { - type = types.str; - default = "/home/isabel/.setup"; - description = "The path to the configuration"; - }; - - # should sound related programs and audio-dependent programs be enabled - sound = { - enable = mkEnableOption "sound"; - }; - - # should the device enable graphical programs - video = { - enable = mkEnableOption "video"; - }; - - # should the device load bluetooth drivers and enable blueman - bluetooth = { - enable = mkEnableOption "bluetooth"; - }; - - # should the device enable printing module and try to load common printer modules - # you might need to add more drivers to the printing module for your printer to work - printing = { - enable = mkEnableOption "printing"; - }; - }; -} diff --git a/modules/common/options/system/security.nix b/modules/common/options/system/security.nix deleted file mode 100644 index f974aaec0..000000000 --- a/modules/common/options/system/security.nix +++ /dev/null @@ -1,8 +0,0 @@ -{lib, ...}: -with lib; { - # should we optimize tcp networking - options.modules.system.security = { - fixWebcam = mkEnableOption "Fix the purposefully broken webcam by un-blacklisting the related kernel module."; - secureBoot = mkEnableOption "Enable secure-boot and load necessary packages."; - }; -} diff --git a/modules/common/options/themes/default.nix b/modules/common/options/themes/default.nix deleted file mode 100644 index 7987ff8f1..000000000 --- a/modules/common/options/themes/default.nix +++ /dev/null @@ -1,139 +0,0 @@ -{ - lib, - pkgs, - config, - ... -}: let - inherit (lib) mkOption mkEnableOption types mdDoc; - cfg = config.modules.style; -in { - options = { - modules = { - style = { - forceGtk = mkEnableOption "Force GTK applications to use the GTK theme"; - useKvantum = mkEnableOption "Use Kvantum to theme QT applications"; - - # choose a colorscheme - colorScheme = { - # "Name Of The Scheme" - name = mkOption { - type = with types; nullOr (enum ["Catppuccin Mocha" "Tokyo Night"]); - description = "The colorscheme that should be used globally to theme your system."; - default = "Catppuccin Mocha"; - }; - - # "name-of-the-scheme" - slug = mkOption { - type = types.str; - default = lib.serializeTheme "${cfg.colorScheme.name}"; - description = mdDoc '' - The serialized slug for the colorScheme you are using. Defaults to a lowercased version of the theme name with spaces - replaced with hyphens. Only change if the slug is expected to be different." - ''; - }; - }; - - pointerCursor = { - package = mkOption { - type = types.package; - description = "The package providing the cursors"; - default = pkgs.catppuccin-cursors.mochaDark; - }; - - name = mkOption { - type = types.str; - description = "The name of the cursor inside the package"; - default = "Catppuccin-Mocha-Dark-Cursors"; - }; - - size = mkOption { - type = types.int; - description = "The size of the cursor"; - default = 24; - }; - }; - - # qt specific options - qt = { - theme = { - package = mkOption { - type = types.package; - default = pkgs.catppuccin-kde.override { - flavour = ["mocha"]; - accents = ["sapphire"]; - winDecStyles = ["modern"]; - }; - description = "The theme package to be used for QT programs"; - }; - name = mkOption { - type = types.str; - default = "Catppuccin-Mocha-Dark"; - description = "The name for the QT theme package"; - }; - }; - - kdeglobals.source = mkOption { - type = types.path; - default = "${cfg.qt.theme.package}/share/color-schemes/CatppuccinMochaSapphire.colors"; - }; - }; - - # gtk specific options - gtk = { - usePortal = mkEnableOption "native desktop portal use for filepickers"; - - theme = { - name = mkOption { - type = types.str; - default = "Catppuccin-Mocha-Standard-Sapphire-dark"; - description = "The name for the GTK theme package"; - }; - - package = mkOption { - type = types.package; - description = "The theme package to be used for GTK programs"; - default = pkgs.catppuccin-gtk.override { - size = "standard"; - accents = ["sapphire"]; - variant = "mocha"; - tweaks = ["normal"]; - }; - }; - }; - - iconTheme = { - name = mkOption { - type = types.str; - description = "The name for the icon theme that will be used for GTK programs"; - - default = "Papirus-Dark"; - }; - - package = mkOption { - type = types.package; - description = "The GTK icon theme to be used"; - default = pkgs.catppuccin-papirus-folders.override { - accent = "sapphire"; - flavor = "mocha"; - }; - }; - }; - - font = { - name = mkOption { - type = types.str; - description = "The name of the font that will be used for GTK applications"; - default = "RobotoMono Nerd Font"; - }; - - size = mkOption { - type = types.int; - description = "The size of the font"; - default = 13; - }; - }; - }; - }; - }; - }; -} diff --git a/modules/common/secrets/default.nix b/modules/common/secrets/default.nix index d93d365f7..8dca4b139 100644 --- a/modules/common/secrets/default.nix +++ b/modules/common/secrets/default.nix @@ -1,9 +1,13 @@ { config, pkgs, + lib, inputs, ... -}: { +}: let + inherit (lib) mkIf; + inherit (config.modules) services; +in { imports = [inputs.sops.nixosModules.sops]; environment.systemPackages = with pkgs; [sops age]; @@ -14,30 +18,71 @@ age.keyFile = "/home/${config.modules.system.mainUser}/.config/sops/age/keys.txt"; secrets = let - mainUser = config.modules.system.mainUser; + inherit (config.modules.system) mainUser; homeDir = config.home-manager.users.${mainUser}.home.homeDirectory; sshDir = homeDir + "/.ssh"; - - ### servers ### - secretsPath = "/run/secrets.d/"; - mailserverPath = secretsPath + "/mailserver"; in { - ### server ### - cloudflared-hydra = { - #path = secretsPath + "/cloudflared/hydra"; - owner = mainUser; + # server + cloudflared-hydra = mkIf services.cloudflared.enable { + owner = "cloudflared"; group = "cloudflared"; }; # mailserver - mailserver-isabel.path = mailserverPath + "/isabel"; - mailserver-gitea.path = mailserverPath + "/gitea"; - mailserver-vaultwarden.path = mailserverPath + "/vaultwarden"; + rspamd-web = {}; + mailserver-isabel = {}; + mailserver-vaultwarden = {}; + mailserver-database = {}; + mailserver-grafana = {}; + mailserver-git = {}; + mailserver-noreply = {}; + mailserver-spam = {}; + + mailserver-grafana-nohash = mkIf services.monitoring.grafana.enable { + owner = "grafana"; + group = "grafana"; + }; + + mailserver-git-nohash = mkIf services.forgejo.enable { + owner = "forgejo"; + group = "forgejo"; + }; + + isabelroses-web-env = {}; + + nextcloud-passwd = mkIf services.nextcloud.enable { + owner = "nextcloud"; + group = "nextcloud"; + }; # vaultwarden - vaultwarden-env.path = secretsPath + "/vaultwarden/env"; + vaultwarden-env = {}; + + # miniflux + miniflux-env = mkIf services.miniflux.enable { + owner = "miniflux"; + group = "miniflux"; + }; - ### user ### + # matrix + matrix = mkIf services.matrix.enable { + owner = "matrix-synapse"; + mode = "400"; + }; + + docker-hub = {}; + + #wakapi + wakapi = mkIf services.wakapi.enable { + owner = "wakapi"; + group = "wakapi"; + }; + + mongodb-passwd = mkIf services.database.mongodb.enable { + mode = "400"; + }; + + # user git-credentials = { path = homeDir + "/.git-credentials"; owner = mainUser; @@ -66,11 +111,8 @@ path = sshDir + "/openvpn"; owner = mainUser; }; - # Luz and Edalyn are now dead replaced by bernie - #luz-key.path = sshDir + "/luz"; - #edalyn-key.path = sshDir + "/edalyn"; - bernie-key = { - path = sshDir + "/bernie"; + amity-key = { + path = sshDir + "/amity"; owner = mainUser; }; king-key = { @@ -78,21 +120,13 @@ owner = mainUser; }; - # my local servers / clients - alpha-key = { - path = sshDir + "/alpha"; - owner = mainUser; - }; - alpha-key-pub = { - path = sshDir + "/alpha.pub"; - owner = mainUser; - }; - hydra-key = { - path = sshDir + "/hydra"; + # All nixos machines + nixos-key = { + path = sshDir + "/nixos"; owner = mainUser; }; - hydra-key-pub = { - path = sshDir + "/hydra.pub"; + nixos-key-pub = { + path = sshDir + "/nixos.pub"; owner = mainUser; }; }; diff --git a/modules/common/secrets/secrets.yaml b/modules/common/secrets/secrets.yaml index 6d3f1e385..95069d90b 100644 --- a/modules/common/secrets/secrets.yaml +++ b/modules/common/secrets/secrets.yaml @@ -1,22 +1,32 @@ cloudflared-hydra: ENC[AES256_GCM,data:XXOt3t4FgbmSvtBrwPZRo/8xSg2BxUUYs2zAjQ2GuXVNiGEOP3YlJrHipKyS1HddNrTiiff4JkZ44XdknSFY/9HuS3Go3nzW8a9meuT9QYIM8uhu4qZxJp2m/PZirVo4sdB+0X+mkJ2hKaYQv7Y2YbclKbVUIpHR5J6jO0p5FY3ElbIJk9wmzzWfXWhgirWQiOTmqvoj+rSoZwpYePtwoRt/,iv:E7tfKiECbLoXo7z0Y/Cc/BI9jBGzECHWDSbFMKEICbw=,tag:2ptEB9HZQqyDnYnhDA/5Lw==,type:str] -mailserver-isabel: ENC[AES256_GCM,data:ebjWB7VzqNQJZNd/MYn+zg==,iv:f4KkiKRZp2nDNe8fc3M+pK8jpootv54KryOVOa2hPEo=,tag:80waQs2PAjpQnRDAsyGzAQ==,type:str] -mailserver-gitea: ENC[AES256_GCM,data:g8MSFZeWnna7nH9pkhAvCnzvRZClW/HNJVPHJQMjovk=,iv:i7yw3l5ABc63jfRZgMAkwFhvfqgckR3DN/fS4z67JfA=,tag:ZTGDQHs/oGQFlbEgsYZ4cQ==,type:str] -mailserver-vaultwarden: ENC[AES256_GCM,data:B+5hxL+tO6Kpi8sxYtXM7WwOtaKp+sO6MTcqm4hKWbw=,iv:DvdYuisz2C3iy+FEjWVte26XDnH9SBW6EfrgrjBjUqw=,tag:vHzTKGfkNeb8LlgHe6bWnw==,type:str] -vaultwarden-env: ENC[AES256_GCM,data:AymALRm+yJYvV9QLIuVH38rBQaPOboGOvr9djLJrujjccGKS2yuBxIdBO3N0/jeSIKVgDUuY9YvPuf0qUi4TgPWLCpTTyXvaXAFmKg==,iv:5Y2zwhc8q5L0YOQz73DSTRbvOle1tLy+WKV6+80+aWQ=,tag:Rfwp/BICqycgR/hnxuSyDw==,type:str] +mailserver-isabel: ENC[AES256_GCM,data:uNP6R523G13QJECxiOvB+VYlQxaoa0s/KHZNqju2vKk8hmwVO15q2bju3ReSLXEdlJgnztHQlYawmGUJlQ==,iv:l0NJJbuGdrZlcj13q3E6hiyZ5CQnzniVEH8wcE/Bm2s=,tag:MoYXL64pBvLH3GbjpNAY0g==,type:str] +mailserver-git: ENC[AES256_GCM,data:zHazBIRM8nZl0oZtbGaZknetYLpBWpQJ9dGarLeMpN3oGcYvmrNAcRXlEEBLH+6FHZrlpXSutGysn+h1qA==,iv:F6s5GesS9XnvYe3J8n8Ryey3ozAhptLZqUgvaJGVHDk=,tag:kRt+g8jXCSQkGPMUpzUNew==,type:str] +mailserver-git-nohash: ENC[AES256_GCM,data:xl+iPzMOhI1M04z6v2ZQdqDPR4jnJwklAdqM9VGQ2I/s,iv:1VLO+aPuja5vSWR8iC74T8bvyVx03MYyY19ydO7GAWA=,tag:w9KgfCVyPxD8n5hw6AbILg==,type:str] +mailserver-grafana: ENC[AES256_GCM,data:8jLMabqJ7TkIOJGzYyBkkt+iyc7nXQOGXP+N7TyfRuEKaU0YP+zoAzSv4jM31wQyjl5/QrMvSwE13AS1Vw==,iv:cjkGDdJvT7DrZSB7htgVLp+TsHyFqX0eeFRjB5lbfPI=,tag:7j0tw/39/Z3tUGci2IKTPw==,type:str] +mailserver-grafana-nohash: ENC[AES256_GCM,data:SAHerwdB0jFI5PNX5Ot9liqVPl0WQn/ZL1xerzODMjLi,iv:/2L/f9rx8pHRiK/4a7fzPBt6yMIU1yZaz7BO1jiBUq8=,tag:nhCWGLnCwKW/vyOD6dZHbA==,type:str] +mailserver-vaultwarden: ENC[AES256_GCM,data:/rvxrhm3TZza3dFuz2aFp06W7iDG/whjxreg3+kJuAufIYNS46Hl6pLoZDbKelXFkn+1Ugvykef9DBEL3Q==,iv:ny/H1R7cHKmp3r+4YtFbZbC+1MACn3KVX5ROd80iYKM=,tag:4h7FrCFTRRD7sePfOAzhqw==,type:str] +mailserver-noreply: ENC[AES256_GCM,data:NgOZ1JI6cXRQG2AH2Rx3zXai/MYtZvrJ7DpwknTTCuPi7bYBwAiRyOBynUltnItjZb/MDmM5tJ6cX30P2g==,iv:F/vkLAbtNVpa2/1o6cz05OFcQnsBFZuZZ8rG4E7gS70=,tag:CX2/7SmiH6qu5i/Oi/hL2A==,type:str] +mailserver-spam: ENC[AES256_GCM,data:QJKHyzY/GAwsc0sJfoCR7IEJAoakJ5KS94qIbi4fIoH4CqhJ+qjaLLvuI39Mu2Hrp2gCSvfBJ3oQlN5brQ==,iv:Acashw2STfzbzGBaXrFtHwlEc/AqSkBHKYXwVHOKC6Q=,tag:2Z6UXbe4fTxZq095vbKAZA==,type:str] +mailserver-database: ENC[AES256_GCM,data:HR+U0nieGQjWX9iws2awtw==,iv:+Vc+3xGrZibBXZSBx6REW3u//0tzUi6a8ODNJhngS5w=,tag:oKyi1s7FzLYzEieGzuLR5Q==,type:str] +rspamd-web: ENC[AES256_GCM,data:jgwF2Pix4QpWGJBKNibPXfh1yfs+5z2oq9XQ1B/C3xZ4BYAQ2aBIZcNoJj1U,iv:8mPIjqC47fX+8Zi5946aLMkGIeTbhVMHSpp7bTx58AA=,tag:e5hYLkgTULd1hJ/XTDwmSg==,type:str] +nextcloud-passwd: ENC[AES256_GCM,data:2XRFDsIU4D6KgneafD9SurL3pA/9g0RN4egMo209fhnp,iv:aAPGBJDlTeoVHneDiQ2FQAsadzB5uzfdEAf2dG3ubYw=,tag:5n63TU3oor6VEMkRxHIzhg==,type:str] +vaultwarden-env: ENC[AES256_GCM,data:RZltkcbeTObbSVPIx4x2yP/e6o/WvAuChfmLki8gkX0L5NXYbm3hBOfA1cKMN34git1xNfPyckHm1zV4ZumTfeWtyBOvUZd1TqZxCObh0v67jZUH2pXWybot+LAd+MWf4dYphxiq8/yvvmOwH5WG82HAudOKcnkQ0qDjv47gEbD87IRgeFod3su2h8zd60iMIHTb6G+ErV06XpWizEsnDxWZzpl3k1WO2V30coVY48D/Sh3FQSrEceL4xMBZzRmVhu8Xh3cOqcSejEjS/PkNUYf+7IwDMn5hFXC6/yzgHHva4w==,iv:w6u+8ME93rGbXirMIS/hSSDwiRBKFbSEcLFQjxTHGak=,tag:rDY68+rvgzvVC29Ko+69bw==,type:str] +isabelroses-web-env: ENC[AES256_GCM,data:pw5+wVbZXkqp4jvUIGqLkiJcbIJ8pMG31Py237TKu3Fml/kYyV5NuvwZIBvvzryTfT1f1ElefVrtaQyEbV1uA5MEZYZ1h4K7Aw3iWWCzZAyMUhEUUJP5ti46YIc6hyaQeuoWkLQkLmHbazg=,iv:Dcsnj6riFUM/CWljcQeMF/YgI2M3uUf/ZFVWpbSxyI0=,tag:JxNh5LESxMtiNaL8mHxL6g==,type:str] +miniflux-env: ENC[AES256_GCM,data:v7miyr71dg2fcMHKtmBlnlFQXafkfXLQBPOGfIA2EYs8Ew3VzhFMDfPe+zZ6upVACIZlXNcd,iv:s2SQno1o0ZyV/aZlUsXDwlOHckvTmdq41VXHzdAPaQ8=,tag:/0vFN4sR5gebiHYjPd/QXw==,type:str] +wakapi: ENC[AES256_GCM,data:UvEIqRA=,iv:HAlUVfWN/Ge6yVPJAD8hPGO9RqHOpZXUJrfoMpw1SXk=,tag:7iiqY4c23BPXK1/YQOF+dg==,type:str] +docker-hub: ENC[AES256_GCM,data:FQDe9QSUzneP2fqMnLbzLJm8EE8nN1kTb0ihfWmtv01VSG9YIQ==,iv:Se0zdr/FHRjXvg0XtAIqUG5L8Qt5nOq3VqjmS6jXJO8=,tag:d9cr2Z7U3Xu6Ygrbk45jag==,type:str] +matrix: ENC[AES256_GCM,data:LEUjNHM6aANmKERyoNupklMev2ulWJ259wSmqBaaX3dyNZJ7DrddATPEd6MpM6t2b0l7mm3XQdu2f2ar3VGUqjxi7hpTMv/TtbvVG5BIlCK8w6g06sYSI0nt7BXd,iv:PBwnavu02rk10eJQA6hCpoOzG6mzrrPHvTCOQYpFFaM=,tag:LtxowRBRB9OFBhTuv+zMiA==,type:str] +mongodb-passwd: ENC[AES256_GCM,data:DRekPgzwmERBvA==,iv:bnC5IGKFnTYFofYDqPn73InWxP2vWeO1SFeXB8ba/BU=,tag:IQGL1p70tq0u92uWay12/g==,type:str] git-credentials: ENC[AES256_GCM,data:MEqWBzmGoAi1H88oXQ17Az7J4FLfS9sXryCCFjh6btOZHdURZ4M5gGf2xErjiWdlwTGa95EsS0Ez2WY3sZR8iMxlws04MWc=,iv:hjgqCiiGFBY2ypX6ZZO5t5HWlCvPvFzZzzxIGBQwMr0=,tag:hSra3Wasnod0OQRqTbHJ6A==,type:str] gh-key: ENC[AES256_GCM,data:MZdpFYTLeYOifCe2dpyON62PjWad0mdgZLAwFYCW2tp7tv+l2s+qUgKnvQdyrAWeI4PdGTlcPWyYhoY3a4R6OV9kYX6HYy2RbNRwHFKJiDlQB22ZA69E41ur9GjLjSMzSvKb8I8OGacihAEx5JeDjGxZHjeBypWIgdunolvY6SfDs85kEG+bMlPkuA3kgWKGb5DN9QNVl6cJTLjg9DJW71f+C5tKZKlgVJCeaXDXfVXlmHdliNoZ1YwR4xheAXPTqT1c4F57AaJ7ZrH6lanzb40bwTK4FsTvBLdWOazxt68AoYCNJYExZz//z2ZKAyHQdUtpilM8xMuYj6sFN4+hMIX13ZQQ/BpGcUAPChKi13i728WhU54UzK8IkiBTAnix1luvuD4fCPaHU/sn5AkCHkt+rGTX53ZzzMUzXsyYuLFYPpPOFenBB4ft6BBYCNEePeUjlreInkG4IX8myBFbFy6ciXHkwtqXXNq+Wh3MbIs40tA45k2nFqZeoyC1br+vhz8LRejdTN7PCz3pIgCGC8h0ZNwumf7gTQhcO36gq2NsDS8=,iv:648FzsZqu6SJAzG4kdITPovXHnDukKMJyuZL03xoET4=,tag:apqEhJlLUrC2E/bJL97mNg==,type:str] gh-key-pub: ENC[AES256_GCM,data:MJy8bIwRp1F6mPT/WhMTN89t63SlMn8dfp3NhLVcwHwPtPc0Og2LnWlCR3XanL0x5Bxn6QBedOM+V9cwzXJNHBsA93ZGeJkQSgqtq/Avsv+9CWPVV5U3bPMOj22lbsPhdfwKNraeug==,iv:SyJTUHwE6mxXADCXGBD4e6ag9Mdnl7mkac2TdU1Kkfw=,tag:CSKUFOJsKG/tMhizHRjYww==,type:str] -alpha-key: ENC[AES256_GCM,data:pfYUpPUSALll+js8GegDaTZ+dW56drx2MgVUc4d7mLjUPrj0+ofR+jfaOiitw5VRMqKLVwjej6XD4aPsxThgVt37Yvc0Y3vtTCgnBsut2wZL6H1sf8JkcvMxFMnDkxcZTber9aFCfkghaeiqcSztq3RJUdrl7jWx3/4MtIOwHzFnT+Tv9L99egGH5SwL75evPBacsVgpAva2/or1TrFPNalNRzAlXUtyOS2Qc0+P1Fx2crObJnIW8pjv21DIrYtFlXOuaa7Nq4bFGYonLfTvdgxOchd1RIvhmBm7oX719JJrmHFN2Tj27zjRxn8L2VFmXddHxSklmug/LG7lkz58YaUixAz+ora+cfS61a4NNI2h7aitqAlLV0eSn4n9j8lAaGwCtfIPtpHDSdN2iJ/qTmogXyT25KnMCWeDZ7VxXavzs1OZyPT/GfyShH6gOWdVTINuJyy8sKpaC4aAHvi7HldjfDz6KQonfKN+KODALc2N9V2id3XrFLx6t62S01OQ3uSP7n5yL/zbh97kxTu6aFaCKkIbg0dAeR3K7WZMTU0DOM5vuNTmjd0GdYqKXXBDRp8PZlsZtEAB74hkfnm6dMvnE7i1vCp2JUPu+LuxQ+mYrhuwXkxs0VI1dCHiPRkPfHjtvlqrjalT/EotEOOfIUw+fo986XiT4k6LDIhG3ZdS7WeUNvpVh8kGuE/HubuoCcY5W3iYXwHN4QrIxWf5KXSeid8quhuUssG8+XPy8ARqqaheXhtpOIWf9ib+e7auDgNpPqCLsPjJhtbwcZtrhGw7lWh/UCHfv45S8zzXdI3/IKu4cJlFL9n70jEqHhXDQpRSeLEXkr0Ldh7iv3QrbEtMYcNh4KKZFv5Uueg9LzhhNQTpYRFUAX3h0caCRIuLKDf6G8E/BbwauYVgObNj7RniLjhteZag3tbx3Drb+EIqyZX4rCCh8655BTwQYpEDDnWDB67QMznIyWXO0ujc0O/jyLzOzZUbslvlrvA2P5NbTfHYcM2GGyifTBajKh/Bp6sokVmHYU12Sh+YaWpIrWX/kCyR4pZ97/Kw2VYZaRFp4lOPPbHyLvB6DtMdfnLQ3rOBLfrWxTHmW9PprOJFl+dnC+l6XTV38LzS1WA4hMlKqUYXU9HbueRIpkFX+9lm2l09+MqpBc9N6vy5aA1tM/owxcGU5vbKYOphIi/cgrv2vD4WGrlWTZbnTkGGRwQ2UTAKBaTom4RnipwyS793IRVRXjS4PzEeZRemeOgPRsJ163n49KzzG+xG3FtwRTtzetwFCQLmCJlj3F3BIpM8UvljoXSqZlOZSHJrliFvFU3uAcMBFONHLL34xN9b/cUiSRoMn8OqEiJO6kBVUQx/uqRLn0KmIub1gr7KWNtW5/uQIbyj102WrfWpiMbkGK3wIw5gBihHL9L2of8GLhxuIoCiyQ/cBx7/GMrYNsGYIg5bXbZoW4xpkKx2nxyiYJcGBrFiKDKHYuYy5acV/TSSUpHUI+kCiFE4272+rum3lXwGplpQlOPlsPQuKn3CgXqAiuRhl6PW0PzRL5590ljInd0yjePX8c6uN7z/i4gpCjH5O5uvCJqJtWRtsssxChXkyRGnJkAHunBgw48IoDW0iQw6SV28klDpVxX0CipFrJO6SbyuMblGdMRIu/4N8l6zxqWeB4K5rnnHTWywE5lRncDIKwr9+DJppLl7EyeSpRDTF0x2LbclLba9hWaRVs3h/BtyJeDuuM1iahhwHJ02ZuVMQ/OdZLuUYcNEcHRtHjCwDImXfUp8yNKTuxW0H5nEFmn1vfwv++xl0T+pdUxBRIiQLN71xdT6iQsqsCkrps+jom5M41jUeca+WYRkMgPZLNnYA5/A4FlHzoLIe2TVW8m3k6csQtIfZz80LjX8l4sc2B/6+Rbyt4AZVSiOYTYBhkGFnMnAFqBkd2ucBoY8KlmThk32imo+v8eR19klMoSiUx2RdNab18nHkN2xcLX1OR5T6WEqiLilUHOsGBms0KMQtAx6EL/mWrxzZ2vL+UQJpkG4aPDX0UFbgWnUUM5HFkY/Jv3tDSzTKXnIGn/hBMESOZd/i7nJbG34Wtp5a8b53cEoH2Med0lizSS2DDfq8/4k0Oryg3WzKoLrAroppYYVGQG8TmpAeubY/2v+ur7e6F5fSD1gbcDDxr5dM6nu77ILj06eUSFmPdpn5Rg+h5pNC6aEDsHb7ljdciUpOiEHZ3MOcMdl0mtKbsSr6RJyWLuEbEedtNwMzceW/2he0breEKvtPS1ekDxGadWi74BbURc9Q8ABDtTyJusyB3Kd7Y2nc7VaLQGLQ0m8zVTLb9+5F1zsuuF1PoTRevvCra8bGttL5XtFvzBMg4R4i3OFyioAEKtSonHO2cF38idzIPaqvZVN9BOLBT9xu42VpHdUMMghkimE9PWrbodV9qlYoEO3Q7v3xnkpjteTxKWPL1r1fzb5fM3mH/e8coHdbnm/9pMy14bn/bhyF/ypheJj3hXXDaID1U0pA8aFiINAJnmlwEiYobgY8UFtQeVwnwrh0lBWAia4C8kuihvflRJ8xYtr6upWUy7Cv8Wte/etlA2yByQ4+SWWktilYkCsw+K96tc7U/9xrVWIpUyWfND40iIPX6FHinDC3WfYefqlhC3ZCcE3SdZp/wmoSn/t+SfBvK0U6DXjHtLJ4gvx69a2h74zz4biIAS7ZHC3goNC2ohQaqOv5A7c2NtGdAi9QOglY3y7YJEzc7DYxbLvfM1kWBEPCfE5NbKHanF51BIepnOUmFxIfboICC+F3ow0n/LhomoIDcS2mfUszdKFLyyspOixykfDbKXPeRL6tFwbrHwx+aV+vU2/uR5B1BZtbQ5A5h8VbMMduUa0pZrVUhTFHhcv8h5FcM1712gPkA0cfLWsgoOLRY03rfjfhaiRCfibh5R9vC2CPVoNUKuIFqjulpTSH74/MB8ebzuRSjjjEhoBQtnBDGLn4WQrLfN/OrJ+vtMbuFNciauErM+y2u+WL2nCAHUDusIlgOFS9fVbJUYQH7d3dAbB16azYrknRQ/dgGH0GesYuDwWXViWviOMjhvgAVZizggnOfm01VXXW0Cco9Keu6G4gkd+ePTPdZKJ59qWv+O+RH9OSf1KNBOtawyKnT1WnohSpau4fRiqkNzsjXNM3TEjDPVipAJJGj97MwZuKRDwj3zh6vrC1fEkEWqcLJs0UEKBXpNcmXdGn/7UJqugAwz5LzX23OAFGEdYH2tcvPRbz9geF6zh9GnHkCcGUIXNglEuSXBXstF/rYcG7lZl3LKbhbG6Wd258VK6NPd8EV2vaDl5Cojjgyd+N331UrkUo6aTo1ucfK7pIssoSCP64ozL6We840T6IPIhzO3bZCO2Ku+AOhzp3/nliIMAUfRL7OtLbv6nrLJJ9hKC20SuAWsHQNGmzMktWvbq9K3ww1SzwTusJU/G/HwUjbT1HTIJT/Ot/JYnPO+9Ds6dKFXdfULGLqDOvyZT29It5obORiWx9mwRPM3ky+TL9Tl6jyj3XWROPhGADm1it0NkaIqblVSUjJHejll6v6kFaaeJJ+cTLoN4pRNX/84HAFyJcMaelsCxyX9ybqFgVo0C8mIrypM1vN+frKmJdhlkqFImAK4EjKxlRTDThGCSmz9w+RVuZvTkTqIzkMl3BqRYF3w0Qu3LSdZSkaORz2GoaMHSN+EBbrdtNOxOQhLR96gotbphBbS2qQR3QxB3TIfL9ojxcA1z9WOVjrAgyA9uCU3BYvMpxNTBzX26tigHYHawG1/lvwUTViZMaVm4ri1qyN+UwtEQH3YDxm3n98qolRLRnuDD8ax6rKVHIPoaRAnndqVuBOE45PH9wcuaG/IRcxz4b+LEuJJlVexAw4J+3U1Dt2+yh/b4rvbpa4ADIsb4nA5HG5DUhlabzfXWMpNzxKqg4Ps9izcWTPuLXukAFVI1avRkk2J9Qo9YRam1s+BoLKeeEFHnTbVI9Hd6hSYQXNQsvD6kyp9l8L8wVgXkWZmn1OZcO/iDD4wkbQ++MKKXPoJSVRut+QXNNcxCPc4DFSvu7MUpMOBkBzYkm85p9NxteZrmYNB7GReUEt49uvpOyFwyWbwD4sPd9UVcMX38K9+W4LNyItwogoGUtN6gbH8wY2qqueyJ2DLYGCrMM/sUdNtBJHHMrDeIoNLVXc5VvUofjNzkwvBvlcUVMRnM4gmNbI7U5CQoIJsVQ3+yJl72KMwotYBcdi6EYIYCK7dEjjto0KO/wU/c15OtZbhPci28Icv+KgWbU0ChoTbIJZXf2A7SJW/o8KaJv8t1aCrJHj4CJBFh0p8hTd0ntb+5UZVZuH7sddLl+sr7S07lupAcNI5Twt0d2VTbI2CZlTTHkuhOeU6TeVM+r1+WzsqDkXuM6cWnSettl+lu88ecuC0vKYZ4EzUIFmDFBP1o8Xn+O01M36JcINDA2lg2oq/qVdjc6Suwp4iMGnse/0clFHNIHvvWu82ERMgMuHBErSyS7JAg,iv:vzuvBC/9wxHlmPCV3jHIK4dB9Qvo0vqSgOvTRpc+9zc=,tag:1VT4dmDiqv+QjnlVElbEPQ==,type:str] -alpha-key-pub: ENC[AES256_GCM,data:ffvo7e9jCnlPgX+A0QpaJBjzpBHyJjR2+NhideXvFCazEBXXOTXgWfwG1HscDvyQfLCI2nztldUOHnX3SrM0Q+aCXapyc7cBaf+vgZ76XIC2dzmyR1NrRQDdAxr1KOWXKEs+y6ce320em31fxXlTiGQrajrDewiSlYZE1PdyptyqMrjzqHYJ7H8k/gM/HoGK84LE/7ZlyhnCRQpAOlBKFIqrkLXOu6x5LfsQM17WkXDGRuKX362yPspx/y6gIqfR3D/hVX8sKGarkHSGu6aQP25qoCXJ0fshOdGA7eXYEOZ5QDc3pKkh6zM/M9zLbYdur3mnrolZ45SpOOIOLRM7ahEER8IZ1JeSIysa5IqE66OXKCGMubVdOPMQOCeaDY0LGjzSGJQzC3YP71VauHidTX3fJQP72SOXaMYgKda0Ht2JleEwLlEo+xRcEqgBH2nCOPCqOy/R08mhe7FUZebRz5VulM9UmIXkOXeMUC7fQYgSVX4h1DSPTZAjn3z/lNNn1G6KRwd2e2yiWrV9FTJjdhMJoEgKcrBM765wFo1VkE4p8s26KTo1nhpWx32kVvPW0HGdwbKOXB6aSKHr3m3H90PZYUe73ljpp8cDxiykIedRMoPUz1AeoxJscLE3Ia+r3BLkL0CVAHrVKDfnSUDmEBBZLXtwsQdZpcTOaB1BWjpNDD/z1GBVikcXpjgUYZi5Kc95mqApuhDdpfW64qSrz69UvFzuTKlsXnHgTTZWB7q8VMPJDHO8m603cU1bWMsMFIGd10LoewwLvzH7zji7LTAatvaSaYcw0QQ9RJd5Up7Y7S8EuUVKYRFxJbNBrptjmwZ/S9EwLJ0umzo+Wlp5hNWzDw5Uzk83GiNvLGxEcngPplmLfrbK98NGAmpLeoZ/nKpngXr9q4rD3vXjtOBooNn6r8VBw4kpWpeREAg9/jtdEwfxNdCVKsDF9STZ0mTe80un9nX2h/R9nlY=,iv:o/DHr0lb0dDKv78RczQqDwy8t14ql7RLUP0DdGS4P2Y=,tag:uJjGY2jgdSoUCRVQVnXLBw==,type:str] aur-key: ENC[AES256_GCM,data:Bo52EEI/tjH8+hXx5cguTWYofDSsWWq+Nmph8uiMfelKYkPMy8wcmB7nQFp8vTwfMXObh8R6tP5Tj5Hgg/psoRMQy9qNbW9PKUfrZj7XeNAEUSFfTYzLqOc+Y1iPjVSQey5G4fMaCSNNDWXdjsl4g0StrjLeoziCLf6Ms/mlK96RNkPJvY3bfBtNe7mEvj9GnXP/4qJGD8X6pbp+/BCwW0pPfELcNz88ng2CDZJanCDZHovl4C0UsKlqS2Teb5APBZyjVj7postCsRTM3j45rPAyBX4l/e2Q1iC03bcmrBlxf27+3nyYf6eCeXLpgvnQ6DUD8kF1nnrnuK0yJWpXhXx8YWuFJqcnGIkI0+ehN77/fXWjVG0go41vOMMvZvMOezGObGPrlfGQ30P2dfgREunSS5NAGdNqezxw2grYVwwI5SAH3oYxHYkzV7J0rSOw8YAPucyJaOeH+3q9BlGmzMyGJ5dh8GecQHAICqMeNfisc4VZSkiRVwT1R1Sczn1EC+MIEXwDnp/DKOUcbOp4Brw/wRTWH+wDbMI9h0iLfPdHdhHvbFI+oJa+jZ1aymgkrEvGVB2eWEOv7Sq/YOdiAK8uAFEflo3W7smPo6wlgs6Htw/nRFEiHY7u4WavIx256qVxO2QGSD1xkdAHdroDPy695DX9I5DR+rwRQ+0U/BaZuqcE42fh4zZf5Njq+sY7eBI7yWvzW9BqWp6COIXjbzqdv7TBXxI8hFTTfX0eF5n5l7cqLQcLvxJksPemXC+JlHb8ICKT3GfF5UZxj0JPdsSGbj0x6PYjPkuv+C0JPF34UkN+/V0s5Rx5TQLacQsHAnytZVrwAK4+Akzv9VZYMxDy36p7PUpnsZ4J4XPLPSGtXktrOsM4DYAel054YSGhVExLqrMiQzDv3nuJmBMoh//bKBC7myNLt9wmUI15aiXx+gGSVoqUSyxqzXfAsAae1TBbSW14F2blLEMxIiHSENCk6OFrMyrXWjYOSaAUivgKpzPi6dDp5tgKlTfidW3l1Sj+qBBb51mPDZG11uCHwM6Vuhxtuds/JSB7+UFRZNLYQI1HBMbXBt9d55XZ0AFHATPkZ/gLpVB8WjEikbfbPLURCU/OktanIck2Pgwsv/6jbudBCwwqWWYWYlZciB95R7rx5xpbtMWBIfeJxeYWp1E+/27mALoJdJymHqqUpLRs31AFfHmpUE6qzqEWnJGDKQ2HY5/W6sGjVi9BVOtWTB1Bz078eAiiA6vXcj/T6wm6qbI+cixlXHRfONGTVDVCb3zMukwO0NOb1mD3dpd1HAXoNq29J7Ya09v7iY73AywPk4/Zh0GbyiXKMFPfak9NPu2brWTTMGjyvrCuk7i99UTUDcuzG8Jio6/tC89+5UvnK9OWYtcIo3WFw2OUD2IxGoSMlosIEUJgvYERhGdvIBPSTqC2lHcQd1zJwBJPYfkRL4sNBgbkJ1XSkYMmN40hxbA5+/IpQ4EzO5LjoUH8afWeFED0zF5/qJ8zidbC2An8FdEP1Y3xcCLNY9kgLzXBHW+vfW2oGlBAEow98SuAfdP9R/VYO9VXuUAmGx/eV/OYmM6v17yb7BUs6/5qqssQ3ijRki25OsOSZMx4GZjWFo8py1g96LS9N6ZWK6vU+6ka7RrQ8GmK3F0QY03+WDlg9SchCeWp++OwYueqCtRUKxdJnxhxSIuAhRQqOJt8ncM3FBQC3c4RnotPEJo3OttuPRWt+EB9M/eeDbXkgxsR6tW5N42NsSLdWw5rUCvAsNUjTRw7qfQ51CelGWoNMxLB9dsE77Q929q1SsirbF1b3WMa8avJKxYQnKfb9Thw6lrHKr2lKHbYdjqzUPKSnrVSWhvfzEpUyBtbQHGNHZbl10fZUmi+80myIgXf3k19u9HSQ/OrgVXqVMhNmp2DaB6UKoF6izI+7wMtRCGbSNiE7cDiFqt+8lwOH3VTZULe8lWngf/ijMIr2PRCS030ffJ+/KhDZUBFxSbBsKKzbA+aN7STEZxlid79cscey4Be2SXOS+5I4YyPZHubye7ZMa9UNi6Osl4RoU26LbGro/Efu3jZ8hTL5hNknPv8U5cgnViqOXq2tyfk1GQVhXwFVTsh15/n0UjeAY2m9ZjzAzIWVsqLgX1dh4/ASv1j6eftVTVAA9lShnOGawl/CZZnIdNMAl9TA29t+cuJ0+I3QXnkxa9KgFluPLKN4pZT56zbLqpfOYiDA2dqIfjKavrsZ6z+d791f2vcCgo9HxnCf8S2pc6ruNJA6nwwxod/rSg76N4Si6PDtmFrd/ZfRfqDP3XUJNupHfe2MXzP8gbcCcu9gN/tvMtF9vJsrDTPuojEcQzWFHsElcQN5NYPlXElkkt/IYCnznJh7xE0fCdsZTyEAGAgIQQmG4OU/iPQT0EKh56HsikRwXoUFWOcowgz65rWbJJZbkGoEni0qzlfiZ9oDwG1WfGaouIzt6N5xIGA2C2iagvhIG01khD/e5pGQm4AQuQ9p8VtSTMoQ0mfIpNNh9eLNBoFBOyLnIVFBszGIA3Bi0t3cGeu65A98mIoTzyBEBpFlPEu0pgOzGfCqxoP4dyLET4To3UNpZqNqSVSQ6qY4WH52bW4l0nqgggGsSrT0381WQ9Ua2tkouRTuj0lJ2DAPHDmGzNpnZzIOa4XHaNVhlOyHn3GAJw9RIxDcjMaNomBSyxFUEP8/IIt7Fj5v3B8CLsgZPhf7/E1dR/+JnjJyHovMbcs2r77cuggXw/HzEKBlyCCefzTsUbTUI94w+7yX6DIEg8WdWtlez8uS87Bk57pFrG4lwElETt2klWycsGrVfw0tSsJj+s6Bwl3awXYGCI2TsIYvZWnOOlaVoEjoG3oN+SrVz4QMsu60E58uXfPT+8A+RZCkF5c3rzXhShqsjHknjQiS5FirVewRQfmWSCghQEUwCRuAVpgBdJOkpgtfPvjeVghDeVCQ1Z/RkAHyciOfqJYkIqihWuOlhSQLTymfH2ZHFNiZPX8tXSsNg06gccbmfOuJgx3C2d1zWamWYcNXmVNtAGtVrsyKKwNOxuPrqApQm8ZVwZSFnvRr/O6MwKY9Ay58qstanrJTU+vqrM4nSaD5K2eS54sPa5s2AiuZaBR/fjgoJwtQGnQFgwofK/1kCr+bxjiA6O7zpQ0s3UaHyYZXYTOXhYt59XIL9dDe/AYV6/H+4DKxbhs5+pxfKP9+R5H2WwCa9r1rI4CFV887ohbofv4jq/NkXbXdMZqb72+ZaNtZfrL54H1Q8vLm4h2viCO+8KJIVjDeceDvdmCx6mZtjkC4Yemmid37NSvCEWZrekH2JyiSB7PtnMcAYjXiCO1W+kR2vnRriyDQGSbx1P+QaJLIVb1QXwXTRgCCrgdeCKEBuEzawZhYtQeGNnuJiQugrMW4A+fbkqCs4qY9XhMBKgo1rFfK/0uRXZ2KepvUnACyVD+AfsCh7do9VNDRjLFiA==,iv:J0tWeNW5JMlKnNhN/5MP3fTVJnRSkNTU/AMmZ0yrGdw=,tag:q+bVtSKlhfcotKmNme4i9w==,type:str] aur-key-pub: ENC[AES256_GCM,data:bQCNAQaZp4YPVTrUHJM2IUH2hR1rXI3BHCguEK0G5em9Tq6g8CVS7BcDIB5zmUs53dUJikI0CToTTLTZ97JUwR0i7WmueE2d20nvrnyPXo6QaC18KUvWKDafjXuGyrMoZr4jkWe5csH5wew3u6H3xMPsLRBNexIYE3ogTKpiijr2sHCGsU3NMesDRMP5ufNm8/P1/nuEbbg/y17EDdgk+fE0oR+VePpve4xN0v4SdCwZlnCWu7WthWkMWwnKNmSRzbbRc2M2YLx5Cec052hhSjjBbglqlfWFFaoSa2//q8ElE/4hs28uTPM/6hxpagTxKwqBs7khfed6S5mrFf+68A0yyctSXeXEmxlnnH4q9WsMHOv9pOWz8I23P4vciNXk48UF0iU1TvfAQDVj+89OO48ZWFCQSNLfRjxaWg30xocYoJoPxMRE3OpL94FdUc9HgMXMadgB+QU/0xsUVTZps5UeymRKcLb0M7/BGlef8Nmzz/Jfk1Z4IFxwWZoqFviOzAdgXSpuGPLFbGlDwTDE1YjTo2EEyvsfwe02XeB2WVO3dXOTW68aM3Mpf7v4YSVGsC4eyLg+CawqVRQ9YFMWJfI7kUxDwkLBdpYZoiUp4c+Q/CtNEzouuxdp0QwHKqPfZ4RvQa1uRaFYXcXevWvz0aifCj6zil+9Va7J8VX5Nm8ynbFFEUMO86Gn2tLY1xMWdGlFSluMWuryrHzSbiQ2qdod5GEXR/fcXYOT7zWDbw==,iv:M0JJGDqM8pr27VvUvR6qWqc9+js/ZaWVTwhrhc2pwQM=,tag:1aDACQ1orj7lu2CAp4Ylmg==,type:str] king-key: ENC[AES256_GCM,data:lW9ChEUE3rY7v6FyGUolHF9KoSNTKW5LDOC2eCONbpGN253KXNa3aamyYxBnZFF7QHEVEtUL52atGxTKKlY5oHARH4D593mruTe+ePMitfipUOJUYZDWZ/UshOo3ozcXSio9Mj0U5l7FqYn8Mtvu3Kewe0/BYw3axovcO7n+l98f/uWOEX1HijlD1xtEqyAEHR66Vx+N4dIC1YgrWFhIBiX40RVo0Ydn51DewbfxgwE++LkEjApxosCyhrfO0SGSuh7H9HAq89wUVyeNEzBkqU+Lwg74BOcqF+CGFVTqjfthHXHTFEc6GCGp7d5M2RrKhBpbNeRhb8WzD0gipwYozkg622Jt0p3vi5tpwbKWIroZna5Jwz0BVWhJEOeNeBJv2G/hPYzxz4RJ91w6YHIuX1m3cVHkLEfKErAw4d8yyR5TyQPpJjxHQ8/FvqZgd/1Pv04u40bbfhUBdDs0ToEi8jfJgy9m2mETdyryrnA5BmpUHKh2tiBXA8COch1wbTNuagmF6XYdT1yeSHyNcN3dRcnK1ntenmWf3Z0NfOaKLffdEaS+CE75lmgMKWk/BsQ1JUBY89HlE/wzfgSRYEHCzMKQjV3ilJKLyYGqVw/0QqXz8Wakx2xyNsawyuqCVnPTuaEq065sq+GEpw7iSz/4gAf1CQEvIBVZhkcY6ebaFBMVgQYl8mGg0pj/YaU5Mb6zTNz/vdDuweVFdzYAiOX0qs87sO5YOQ1xhbHTBjTihr0zBpIkJ/iSTADSxvxOlE5XaTlc2ODwfO05CXx6I5B50m4v2NggZ5A/HzEGJCPl3LpxXWefcnCqf7U+eRuJTF4zNxVXlkBeXFGUqi3s3Af1Z/Xi6RM7GMkSrH59npJATpf3IUqJcM+pKKWWVOu5Ugfh+/aaMO3yBnFSj0L4mQXNAZ6CCamkfj2IEDLz1zjAdOBUsLrMURPpstNyh+Dd1Rtf5AmYxVZbdYbmRhryjNK0Ushb0HvZ1yJa7knybMyu/l79ddVR3SsF2DsxlevxEZK69NruKyebN1mnm31zKZRIHx49K4M4OUSdF9UnuFuTpOy9l1FdytD61CzRIwzxRvlMddaMvKdVM1AduvQUtiBPDsAE8AP9twalad/NGFwgMxTqiTSBhd7fsSsGvgiMx60lcZcSCZXAtfpFBASFpDXRAZNGmkB+gzzWceuTq6D3KkSRue+WFwAIq3zBqvK2cSxgTn0EifhQ9l7qF9px09WJuY/stOuoceYt56gzspMOttXUlpA9X6kcNrHTeX+nyDd0eQLgUuxQj04Ek0lDlceHHOpUhvws9mGfCOl9BPrps3dm8qxkrWoghACYp7ZfYovf6jmqX/x9rtvgdv1AOwhjvk9kn6z7kV3T7XJSK5/zDBAI53Lk1940cmJAIk+BrILFL65ZnHu+pxK9dGbk/wuMx3E6r8byd211w6nnqp9jBqChT49WO6VlwQHxiYH0ERDD9aPUrWvEsWZjZBAHrfT89w5ERdgxy5koc2oX6uzmeN6EdM4HY7iiGfZF04i3PKhy3M5n9IMCdqH6D54mu52X3T0Bt2Fe5nATqFpooavVocJ57zbo1CKcaexEu4I3blzUd//K9SY8FXBzAjwJRy0+PeGbUjjbMlvtjfPIK7vVeXK+8hED8qO2USBiVQo41WF+3djn2cJQjaV8zgM+rPn19zyZWUvDeal5EAyQQvVCd3Q9qPZCozMJeO4z9b7PZPR1CsygZm4P7ZMNq9Zn6Mkc4CVjeOH+MXpF9V1o1rB9T2QnFSxNS2TE/gOaPgXjbAk0KDxY4/fY1LB4JlybD9DxAaWO9Q+oRix8hScHmS79ToDU4y6700jUYT6NhTe6tirHwPMloOmbIASOfd1/6unk+jOv2Ge1D6cWOqKnq7AHRsFBwneO1X7Xwg7+8LepHNAyFWHhd17gW2ZSwSuFfdrg4sTTqGsKv7beHcu7pLXMWkvCLcf9J/IicSsl26sCcb/SgbkWeCEppQFMhcb6/3v8VaIY5ICtrVto7G6xiLdJi9qOV+6t3nZU+ESXR5yLiKiP42IwlstZCfeYccUHFpmkSW/G0kUAPya2bnjXIKcKsKEH1V+8YWSuLyGrddRd47cpwvK8alvSFOIB6itiv+icIMHXkkiMO4Jc+KWSW2wJZozmoDVeT/FvscHVnOB1QU+QkmJ5/srtgnLSwdRNaB9tNatY10VWcBBDIh1HVBlyrWN+8+67IYtWN9xGZ4M2t1s=,iv:Oz7POALgJhk00p0vq8fToeT3p3GP822/omuiX08lRvE=,tag:jnqVNKSax9hlGkIEoAOgtw==,type:str] -edalyn-key: ENC[AES256_GCM,data:wrUcLsS6Wh5Xe613qNDpkH4WDa3Nc5fADM0TtA8Mt5S8u43kFcwDAZ8bgDSI2tAwu20VIxP+GRqLcRfq+A2v2PvqhxtBM5ctcMgNh50fZnefkaQX23XXw72DJer9tDFq4TgX2NvO5wVY4BMRa+/itvnmlYPJlL33hWKuupxH1ss2ZKyCcX/tcwvO+YDc1eEvVnSgfzJaB/k4FV1AYfm2AMsm9eiOSYnBQXFBHdW/pVU5d4ZcYYFYxbygTlsP98uHTMGT2AndAvK+QNNmkCk9TlSsVrVBUi/h9JhJwkaQW6YxE/Nx/dvj7uEbR8zxL/xNHKI1vwykR/XV8JgJQCk2U3dIzCzcZgy7MUo9EkPnxy5t1N5m3Ie1cGS3bzZqztD1BD5ZAvsHST/AvEzdIv6yWz9XPYFAB6GQ8CxPufyL1JCzUleliRvO0V2Ut1zwBoiqXxpVeSY+Wk0xgVxcPCI4+obfsRcLSyq3cUNW6lJx3es1SJbbIVn908uYNfHbUXNrll00OPWhCJu9cpWKDA96Oaj8RKR3gxsHUADLAqx0imu6BEWfKp8sZBhEjT03XkZ1gjWQSZHA0qvIzNRcavGImSlKZwLmg5ceCfFVJ/1km9L4mM/BVTJ47DwBMgHwKjbFZWTsZqDRj2cHi2CVJFE3gzoc+iot1UE4YDVR2dV60TkbFr+N5iFeTBf85H8B2bhCQYY7k8NaXM9Q0Kt73sX77X9amEAtB4jG3a1r49RPmjlCxbtaJ7zcvtFQEdqUamzvK8tuMjNnV5URI72bVe8o8jgv50zasslW9AgGNdqtCO+j+/nLXM+5e7Nlo53aLnR2udij70YrTSScyf5vIin3BhQXyTK8OhnjyKE59v3dO89/E3xVlTlTNUCjd8+Khs0S2pCrbBCQPB3LQZGj4jFGx3roozAedoha5qG4FJqpFonIFG5I0wEAWs6fRsGYpba7vqDWNTqyo5iB/05K4JsVbswBicHktflFzLCGUXCXLcHNs2fsewKBfIIfFGY2W6Ay1or4pU0EvKgVm34t2rjfixeIZhD9xIW8gDnk5UiVmjwXwMZjt7FypM+EnKyOhxSDbBmLbS0JT9YWH0mR5DONH9hSjwZYxqDbkXU5bKYniIYLzFgcTVnEu82LxfdZpH5Ls6L/HQSeY6rSfYG+6eO30Th6r11ocwEEVp7fnI1aapX3DSQh44uI6RrnXeHHlYc876Kyjjg3PSw0hbUSOTbw506AsdY9n/twDwo/a3XHTPvYtT/We0xsYTKiRhipbgR1Z08phBsmzoGpHpywCKixKLzzRVB1AyStzIh9cINGl6a4ckTxXq/opNSUvZ7u9U6mIhq4cgtZmGUe1ZGR1KbEmEh7XGZ12CPdhpDejBTwswyLnLBHKhh9LynmdPXsr+iOr37asUqvcAU4vqmMAsdaj37Bq2nxTFOTMhBkXXvDpLCJIhzJ14vn4luzai+MTkkmiv8jn+MXwmUme/vSptYCY0XO23pOoRlSJN6XSgxsSSokHrgLI6gO4feZmOoQh86wBpK96zGiKx7YSdV3H30Q30HH6KCB4awhKMhpVW80wzBHETWivl9QNOv9l+UdTFqeNuHWa6Y5TYAPzHiOBEo2GXFzgCaZXe3AvZl+OPXTl7D8jgD3FKFyUlwVDunYAKEDjg/bL5ygv2tfapassOBn2ifLjtQYIF7VlWOSQc5m28E0ALy4Ef2oHAyP0pLwjbHWg67ZkiUnXZmloGX9LW2b7ewEtMLO6MzZP+4GMzQj2k8qBphDj1iCrdYxDwK7Ashlifcypi9gFSAexZ6IkrAw71/GHvVbohRyhUndIsn7L3JnndFiGD8kk6/mw5B6TIA/UEJNziYFYwPHEoLZfULGQ4p0zSX6kXsss5hlIpNn2NSuREG1xL7eF85pRxii+COtp7DBzqOChgTKOjv1BKsQipZ3L+e/9TfN/K/IYlHv8PcrIHLLoMDswwKZeoVZ1PQWnfR+t3BMVeJT04gGmp1Kh2T6H29OCNgj2sbh381rbICoLjA4dxXwzU0FJ6oUoqbsR6ct+L5diViWo39Rs0A+sY9Yqink1qvRpacy+KLy/ctjziskL6NhURs4knulhHr+gC7FrLYJtae2KUyCUcs0ybgKc0vz6o/Y6ZraqdjqdMAOCSjG4mDL5Px1iOSFk4Gqk6zumwAtREYpinTjpkqLPbHd/m4oN+lF3U2v2TWb5KBPYSsLmNGa+m0EZA==,iv:nLnfRA8PL4TNDhZ/dRsDJ7ZYdqsisEPE9JQDvevcWv0=,tag:HTlfI8w288l38H4LK1UM6A==,type:str] -luz-key: ENC[AES256_GCM,data:+7kmm3Qk049eBZ6RodwCPSQPiWaCtJIHfQTVZAXijMYfjU00JAc2vfAjeuMbnTG1bIj6nl2aTNnOlX6FYI5Jl1trPBwJrKgLlJ83rvxv7WFBhnk16Zm02rRFtYXL+W+CtLqZUSgjbqQZepEbJcEyM0lBC28/frAbr5PqNSd3XPDhUqVwG3ZR/eIt0D/fHZ+zx8LEqtkZAawTylO+PRpBrZ+ZlxA+1/8SLRhnffrWSbUYREAini+pPjAe/waTPsbpNuBtLezWNg3sZ3hgQBahtdvhZKA7mzE5X8Zq+prl4tgbgZ5CCM0kCXcFEW9SX/C00xl76kRmd+jg5P3FEVQ8L3+EwRnqwr5j4oEM4MMJstJ2OUOxxcs1hq3thOnBjVNpxcoxBULZMx1IrZvGWlv2l5Shogf3DL01aiWuMM5DwBaN/8CZrZjMSyxT71IVNpR23lfdiIbZNPPFBT4JX+jmV1DnhutwLAo9oPQV8BecSFqRI7lUp9hgEYbObbZtS3tsGdNkWsA3s/ugpO4du53dNzAtsEM5DJgT94X2cbS3XB/gxJGeXh7tG7Z/+/iqc9cfwZyOqj5GmswaiM6TeM1d+s1xhike9zHPdR/V1M4N1wasMfFdAFFDpiWMG4loY1Fjads3Q88kB1+B7SNn6/V+cIt5o2D8e7SZUg/4Mfw1xk9gtgzQuR5pm/cIUrEOYgWNoRK4MsQ+n0/M2u1mXHCburIWAFNknU1dKN+tG7dI7qqScKwPO8O9lgrL1W7tR1BQe/bYYC6Z/Kfm8dNBSMvnBnCbTfEashF6ltP3S3JHrtbh5tdSmL0LeAR7CVC0ApYauX463tHvwiu1KaKtJze8T2dAuDjybk5D9+uApcw+cvaI/8XNrZBCA/Zocw4DIXh0B3yPKGE1784NRyNOwGBcnMqgzrFnJiMFtJKGp7jGstwXFYbYzlhe+YUFo/jyBLP7gCrKOdwYM7nel5VtjLZsqJZ+ZuGQjgDIGlY8Sk3SwLn02FFrz7VbCEFVGKX86L0Tm0Y278jL3AU0j4uAo2XxdVVkN7SXVUC5jLdxFiLHfYnI0STw7BVxZ6UyfSEo23b4bzYasRSfedh+yVDq0tQVFTyymb7t2WFCLhFkmvupPryw6EWzNmeMRx7QIqrodUb061zpZ74ymKfpOY2cMq9zJuLvsBMCjqYP8mupsW3n9y8neOAP4P5KuTSaaHMuQVKA7THFX/otzGtp53znlSPm7stSkO0hyku+zEkzcbb6HDBHM3x3Y4KOgAmLfjZMVnJ6Yfxc5uCTEzaZgIMJzE4H1/rpX9YJ6lyhZOpCd4bgGupffjv89MPa9hmnynIrgadE8tuiA9VWrRDCXm6gi1O6FtibMXgF+hftctEqA0tWayfeOCY9FjiGpp/Fwnd6HTmzx6ngD6A8IGHOKmMsOTKe5bvkIorZbM0wKjSDpJMxqb0pJ+SWCcSjXBoVp2oXN2G6u1G7yFGeu/ji/JdyD7Aep8ElGeSWCjI+8bPoaw/DKBDz0bTlhbENQrhN1S4BISS9tJnh0PJCeH8RLBOo7nObE0g/lpasmugWJvl1nY/WPU0UMDt7YVqwL74fYzm3qLDrJL42v+j4sYGHpAyoWD3ndX3d/0ZAn/jdVIoGTHwOBleDPbVsEe15SeporyLt1w2O53CKE/Dr2amhrxxHHXe6ZW5zG/dmV4IWmJ5SROls/OTuLDaYyVF4zsRbLNSVQ5oXoriX74cecfm8wqU3a0K5PXmAQEy4a2szJNYLLXcUbITns0/mAJUs6bjTnPykp9EfdcFdmIcERStDzL8VJH490SbigAxcrBkhuwA4sOhgOw+R1Z1gwiEE68LxK80tv2rHRSInpXj0oEN1MaSLaYhiCv2Mz8j90ixhCacz5vqQChXIr7OqSbs6DxruG60B1rDBKUQAEFmYTj2aoipdxSZieVYJHiVN34AdOPSTtMGtqRigfa4Ib2Sw+n/FO5pzUKq2vbICRHtXRRYSkkjHX3MflMPosuEUCNmSoAMoNJGqrz987fTf1gJqdb5UOCpxg3eXnV4v9ZcM3SM5lu5jgcDVk86t8Hyg3X7Ftw1NMh2AOwpaqr29j53hRtwk6w/Iw0O0v+46yxDeZftiOyLlsN3DTXxCDihqs5Mw7eOScZA91gdeNQhsxlU5ZX9aPhHn5OusS8JFw/vE2i/ODwsBZWDV+ZQU7ZPhnBeeqjMAkF6F7i6luvW85diVDPJmJ6o9sqk=,iv:KaZxvOKLJKFRggfiSKpE6CylO58eNQpRN24q8MlALQ4=,tag:XcITCHBz2h+ihZe4p981kQ==,type:str] openvpn-key: ENC[AES256_GCM,data:Rn0OVYwwB/gnJ1cdypPuiiQVTp1yqC1ozFPcUCBlWdcdbyytS9RVZwTePAST5DxEkd/ChDFid2pBQ3+JXwtzrq+sDAi64zPKLzDm0TBJMPLL/Npv0cKQf+pfp25REP24Ajo93ZAFinXT3IJyYF70P9VJ1AaAIvz16CreM3ZkQdV4M6AfXQvPf7/OmXThG86aDqvNXE2rPxTe6Q2JrhWkmKuGUdAQ/Nfqvk/bfK/0k3MbN1zE4NPftXNm69HippiIzJlrFAS08ANZGR67u18yj9bCXdaujyUHxGlnWoYh8HBrJozcKRh+xd/aKJb73dB9+6ZcLPG5S6aYjnqGoTwk4fFlhQYtSGb7199Z08xpDZ9e9yyAs3mHqh7Bts8+ikTmMZCO9NqxAzSgXn1xNRi+buLDMtwg7f6cyxCc6wEz5FZwXBvk9x1shCThNeQ/F3S7wT0jPzU/ZzW/zEpsSMgQ75V68yTW4rxtv63gSnNJZSOlLLKT+9CRym0doiNqd67uw9hP9A1YBCx/1wQg5gTYZ7xevhNFDAR5My0EDsQ0V11SsTRlct/ShHVAwAQocgjfcLDNMDl1xZ8FNOpk1RFhJiPIu9X6qrxqIfS1E3TGGDZZyXiC1GpHvqwqcpKmFQYHTmEXJUTIu6fKPky3cksrBgXfvt+/eNcDMTvkFOcD50i4w2u4ugb4WzGTGw0fh6OtZYMpwIZDbOzPZQM5q3IBy+UnhJzaBDq7b8qHMEdjcM30BZagrjFAvOx1hrVLNG1+rgDzz8Oq3+auEVPnWi/y+dLBdG723Hb/ruTD+NMd3EGLpo/+X63XgIsPludNNdbWi8Rhh1rzSNKXZ098kWRy85IuuUizyJfPIsqyS0I3s0iXvpv7k4ULBQQeISPqWKgs9jVSLy7MORUtnq7dfSxyrXRCxSuryN2SpRR77MBDhum4BtLz4LuSz3x35TBmTk/lmaDuWrQzCU5O5OTO5PBZ9Imgu4xEsGG9DVnQ4NbnibTLq+pTJDrUG9M1FcRX3NXp0Um/yrMmYZvg9zgt31WREVnTQYwsOu/yPCU/2Yrd/5/pndRjRuSiD35Y4k34h2R5k0XJp3hn6OJ+60oVHN0UPU3fH6GEA7zqVPZzx5Qo3Fpjl3QsSzsYZibdd/sq4hDx5WbFzizI23brYJU0FPyBxrk+vClPjotDfUUI63xOXfhHpR2yiUNqBxIOaXidCQv5rScIETSDnWd/B8wiYl2BQ75vp/OYzNvXg95baekCDvmR5ShvAIvmINfYOx1lToiMFr1L9KHKawrdW21cNCrPXkYbEHtDesLyuSohGyIJCXlQqPjvtCE2m7ikcN2WBpJJlWP3j/HgdmZxhdy5hQv4Mups+BN/zSdPJEiPONP3songdseXHNwmmTR32BS1cwKyFPk5t2Q19i4JpPdBnLypTu+0iHBT3ESLKnHxLNwOiR5RWJpdQ9jKzKc7Re5soiaxE1Qq3VcMfC2mxNalvMa2gWZg/kUMKa0l93HLbRCBet2icZuKP/02cbrxBoxb4sUhQ9gyHbIJlDKmjm8j9pX7s0+N4/i95gwA+o3mSFZjKV+VuWRSKEhCrVgMLdLrnScWVlzXnttwTL/qXj4ZP50RXVrEl8bO1GSgZTIPQ0ULFBCgZi0y/xhahUQZvRRY/iS0EIh2xE6HRyBx7OlCvD0gFHPi9oesMTkG1SUniOGOZfsR9oulV7Umzy9qojeKU4js2h3Dy0Y2rRaG3+0LZZ5SiZNbC4mrT6wUeEqv7ofo4jrnW6TtT3EP8fWKs1nvDYLnd9MojX+xmVkWj9y6/rIeMoqaYcxO1wdvWclTeL38gSL8neTpvOuaPf2IoXmf643h4/iUlEElq2LiP7RcwoU2zJpOfd+9cA41zI31dl3R3BTMg89mBmOnYAO4t32JklQ9Ah3hd7aulvUEG4uEUCGPR5wQJtWNoU5jeAeIAnVPr1U6Dzcy6LAWBj3ysegSMZCGGiyqEHffX87X7oYYK4dBFZR1GaAzWDa9jOLmKz46ivcO7GrHb6eBDW9/KYvM8+aikL05ZS2rO6Hz1bHcY1y4J4KvQozJQrVo1I7/xikxQfQ3fX0h/YrNK2abYobKQXz6xjFqIxbqivCQRGsTcLMJuVcfJVecDG4Ntg3qdDgd+i8Wqk3S42pK7JjfXOdrWyQo42SRnj/JDdS1RhBVwvrkAW59icsS6r6Xdz1ytHIAsxN8zzMyNabpHtBCdFPAlJ4=,iv:gTgcdNA/mKt18eNXoiaN0dWPMxjlH/iOkRPmsohN2Wc=,tag:sRhQABYI9t3JvqEqYPKUjQ==,type:str] -hydra-key: ENC[AES256_GCM,data:O5Xix1LDJRiG/LGeyzjnsSNpCxNebza7FxTjX0Q+vqOka8UZs3OCLiWxsaGzf5jwvE9IoUPZyvsD1cUPoZ6PyQvv/m8krGQZglyPWDv3Q5tpR5JjB9mVCqTI0k9Z88IJagGjpLnDC9excnig6s2vA3/01FHOnbXR0WIYBEoUMlOGUSlU5vFrHsog9MV1yHM0VYN+pxjqIad2P2IIbimEb8IaHhm+ZS1ReOXkGFU15c8t1xmGwr6bqOx9QltY6h1YhsWHuS5idq7uiDwhw0Yqcy+BGS/7fTRYkfot735wzAcaAHMkafcgxyvPZLFavkD0iAfYpQUkEy2+HExTYWP0QeA4RZ2RFI4dnn93hLiwFg+GV3xIooE+h/HY0h/Rwk/2BY9CqLdszwAaxeHisGLo5qsEIG3VXZGDLWs/qarur/WBcfsnFcLMxF41+aliCGMNOjNvQkNkkDx/0JSTqv/o3E12exPQbDbq5+1pX9UqGvKVRmpXfBvkqn4e6nKKUNc1KBiNbg0qnC3idMaBCYFiuGmhVHbVxbKdIUVJ32E/5DLu8tbl0ERmh9umh+5IFxjqQJGVuNCtre7Hb9jPNHyHsOCNJlc85BhjBfFKI9LRhMIQQTSGwIoaNHuwZX5j0VdN4PGz4WCg5vFqVMTTDgHRysqQnXs5/sGtO3l4MK3sBqGVx+Qjeo6CC8p3HSAd1qv48XxbmnBdwJ9wxqoRSloSymP2N2tVDdcay3rkAGj/5Lm7JtNfuSdcjjbpR3djXoV4f2AUl855rgYGJqXND0do47SSNoBio00036y7mMWcmePhwXbpXvul6F+J6IZC1Pcy6m98G8RqC+VzFf/2HAsM6fK84sZptL71HuydWHEfLbc60BPLu6CwhNZ6tn14c39/Rglonqi/RBcFjYzasY4FZwwWqadTDkDmY4XZJGYOuexPpOyJW/AyNLBLQPnR+GzC8Q9dhSuxL036JVFvI6YFv7aNDWi8Tb0tGTxhYDhIpHvQ4Lz8yQud6gu79LhM2N71TNkep9r85hF0nAlqtBZm/2pCDO/EyMiZRB9jTC5POvMW59hAkEiNihkfMnH7tCD+jzZGZ+r7rF52FlIiz6jgpHnUynZajcMfX8DziY/YG0jv7A7QsWf82rDYmvCuGPKHWZ73pSwXMat189QgDxOmmPTYhsi7ID13tTPz6Fyr9VWyXTuA2GFI8qZPthfCKiPBylw9hZokBH43EvRXjqc5cUX65WzICtl0f2bTlg9nZ5fXVH7sTDU6DJfG7GW+0Cc0Pd6Uj1bOTU42JOUmn+YdrCs6tBuEQTmn6vv59eMVXhWjLHMhhbwOJIbrkjs7yCv7w+1Rqy0l77lxD5dLgiCg0QppasmF6bSIR00aLQPUyj+CfcJ91NMXeBI8EkOG5xX2wM5hl1WrVFqUztGsSZ41y28O2Z/dpdcsZrvASZNhsaM85Qb3mHL4Nc7UaF5ui+308G50C9A6rWtr1JJ/EMAGSIf/gvqr5MMVSWj+A2yHSUNIMzFdy/pI5QC2gpt/KgAeNsafrcsCXgM4Ptx2Ze1uohZVo8ZnJ65Be73vaOrIEbvhGpAhDuY0azvexrvUjQyQPvnor2BSQ0wIWaXJS785v0L76dFcQC5AKWOC6XSiLMRsKBrc/m9tD2FkKryR3yUB6FLTrg6bV6LnC8NXKrL1HLwqY+DA5kh9wmKK6ETI3NvKe4nTYY26pfhdMHY79jj6WIHspZTLHgyb7qjijWNpB0f0m9SkvLgq2oxstwaFrnSs/hB00XUIPdgVVbLLj+E+QhZ0uwycQXI2b+w9j10spqxj9EhlDz6mTAjmwj6QUQA8jRxH/vREIGoKCpiqJ7B3cUUEpgLDbn7PKeT6JZOzzlsy2XuH0JU6/ypfmyx4E8BMmTQtdAOx0ywzJKAVUdW2NJFFwYqWu+zzCjme+0XhSAkV3rG9rVDQ88SJZRtWJxjyH8zgWj8LWKe55Qs2ltIaQBepxJ/5KFbvQDMEahqrahQfHvok8siH5YG6Xvwx+xVrTrFgzhPBJ60wILvLEk7iDKyprG/2sqy7wQn5PAVVAmut3uic+8Is+FtVfDwRM7/ZtP3xDDFx1Mn1oj4HbFub35qrX1g/jNTHtgR40wG3C7EtHd2ver+E3VA+WWMDFoL2GmLu+5SmFxBqYKUXjEyWjmuqgNiArmzsLJQO2BH5JdX9dqJFo8KdN4+PtfrB50+htMDTXYoNR0N+o5GiQX443j0QHfYCK6U0KFiQVjRI+rwyInxToop2uufKXxLYiEdk6DHeb0UHUDVQbFvZ5S1PG+MGCA54rYuEw96jHETHdpEs5F+F7xtw/PmTcxlFdvfBN5HZeD/cVYnegCsGSDAJyKOWjD0mhCogbDJt2/xoHIjq0oenaguCGX+msdFLiWg2EBD6aLBH6x/algM7duTouYubgol1XCpUxY8qWFfqWpZytYw6nYssVbAPWHqP/uu/Pa/Mi2ijwtk/Lyq1cGNjGaambvKfP51Kg6+hqr/nZmpYt1kb2pNNeSF/Q5uyetfRr79g7EblueikA+iUUF5JVxdhhjfEOV5/Duy2Ie9VH4Eyr+NH4PE1rJyoJgN+LdzV6kzY5GZnvNBBUa4WhwGNkKLZ6ZxPeFMPDLvJA7u3RV091T+HVqxhpb1TRk8lBq81Y9H+opgj5HvVuZRNqHOpFQDik/YSmajp8CksyS76ECwoAderrrL9x64huuhTZayCQ4fpG92Y8Oc5iu3pWTxwjQU2+zCZcpHW0ChJZ4zWftGJeL+MjxplglaqWhCChq1ixpYi2hvCFar7o+qRQrQjJIggJvI/cZzdXZN+zPP1Ynf1VtFd9+cbhxp9c4KVLPHbn1IPF0y1oJ/cfcySzeOhFBSOwyP7AxSWQldBvT8bBV2f3Azkgn0aVsaE3aWJ7DTd0AJY2dj5Sdu3qze7mCRnn5Ma5TY0fL4E0dwsNX8wxLa9yvtF1jBPn5NNb8k/r+/v1o8bLyBjBMbs6Vj0PDGXoxUsJj52VyFEwsp6aDmAkA6wcRdCUZve+DSSfwFYnX3sVwYXLseskfRIC+OCB3BO8a46h+hh4+jjLm4RaJ08k2HaFE12cyuLBl6hKwj6kV8ks1mOQ/8yTv4yjI4Cf0Y2PP8zqlq5gqlzh/qaVvF/bRa0Wrhk7Z+HvXr9vAfK+Dd6tpbUsoc5A7nF3OH1TM5d0OH0Y4KxY4PdZLyFgMZshoKQhQ/spMImx5YwoiRm2s9fKLWKK135U/GO09jjo3ZNHEge0e5dqB/qK+OtTjJ9OHOQKYCbRfW/zQZZEwLa+uCDnjA8NOd+f/we3nRGCihki3IhVd9nqHZ+6+wNfYjEk+Kxvjk4BIa1qEQjUUeuYrBy3shKz6/lP4tmf/f5FkPw8YlQeVmMYP5Cne4jMQXXY6MPa2PTL+JGgyR6LSr88Z+M+qDiVuYYNZeYqryRaYSc/XIPOySGAMmP7A==,iv:FYjKCz5cklkjzExq+9uzNtGHaeSGZCDQdyhXl7dKH7M=,tag:HKpWbsJnxkoCAvY3PX9Pbw==,type:str] -hydra-key-pub: ENC[AES256_GCM,data:ljYq3S2ktde1Lw/E68x9gKaw6M3jakA2hYXRlJgCmQWRUIaGuVmIcb0z7DhzAVQmfGZ5J+iPgH32nVk/84/OXexByxOLHaj9W3gPTLxZIPtu4AXPpwIgySUO9jFYzdJcv27J8o7m/tR77zv/RDJcp5l/8oKB9/Z6gOoG3qZ00URsfDaueljoQ4FBMvI9cT2UEivo+AYP/w7uJm85PLgP1Ana5PdeiNOuYVvR1YXI4OP+pKr9KHm84RtuFFdB0p1nZc6k0AX5R/pxvx7fwOA61bQFUnFodLo0TnjZLWe5KgKMXkNktnR/ozRDD1g0QcYOoiCl5kYKfgRnNhvWP/JS8IPzY6a1mLDkB5uwYiIhw4PJ/wM4mG2TvmGSJ30W4E6MW2V9P99Cnatq62KaaY3H2hvzJn3aNjspaN+lq+bxxPROykb1+N4xOmbn+1bCavforOVOiJcHXZXHHVLzAlXTfN27au0w1WqKOQBTxb2hdKn3OAn9vTFOXXC5BIq63gakH/aSG0+FTF/LL6Sx3YRLxWIDynsekecLq4PLc7gLt3CjfHh/DzCRGsuaCSNw9+CwtmrDI/qN3ISzjsMxDrZ0szcoMcqxS5eIOA8lx/6omqj6XV+Wy34gi0NtmUOnJreSBXP2TW6f4KamruRo/fdwr+i3EIign3Aw/hKf2wSG/YMLsxmlkIXYQZAkXBuU+eqKeZxl4XIlsziNW5izvlRuSGJgheZH8eDPHtszG9vlIQ==,iv:Q1aT7V6aCZdPxpWgszmbRBLiAeknKEpn+m/3umRzGLo=,tag:ttabAuYHhFeOA3szf8q4XQ==,type:str] -bernie-key: ENC[AES256_GCM,data:n9v6tR4SJ9rj8epYWtvr0bJGY/yPwJ9DBQA9O6HiHsOPChdYobn9jHuIccep9lRh8eoRmQjQHHyvhZHTS1XHvk8icBCu6SUJ7TKJMqJ0ACSRCKXKck6USDcYeRvX18T33ID9hQJW2bDWwnuWBlrbeiP4yRXKCD5pTYchXn88oARpLiTG+tIRvCD/I4sfoR707YyU/m3frR0QSPoUyvX1FnykpJylyz5ioIZv+ukwbqU7quzbESme/12NAc9RQEHf7puPfURctblRO7LlbSR0qgVy331NjBDOzqfxAtTZ4DfIq1aQRPalU/X8gzBDeJvdzwoWkzC0M4SfdRAnbTrtPHduZGAFjEsr8WCIcEjMUrF/TKR+K4EXBdA8CugKlHOcBwW2bTJK5CdmdTN9rzs2JLO6MlSZopO2vpkzQM3mEagOnM0MXia3rDgUnQKrBGbKDGuazRDIFbz0jAn2XQF+6izJUMakczX4YJme/NHb+/00PoOAEgpavHDkogfGpBBjCiE9eXnI7e6t2/1DOQNtxqVOqTwkU1pd3R6iK7ctGq9Z0+Qllrxz6Yivm6/jpD4TX0PMyOnWPVAO0p6x7y/zhOffXWU9huEMppiKu56TnuIAi1LVpZm5YW/W01jzK31s6/SdhVn6o1so7TbRxqtfeDa7yAnc7He8MDvvFBKwr/Ra4lt/Sz8x35EAS8O1J2IZQ0te9WP77Cto/c4l00wzoQyfPF167OzrSzSD9t/7qO189HbB3F22TBuwuOSZyntgODPAgkHbmcf6L7QWrazNYlAEN+xtdQwm4k8z1M9hHv+4N+qtd+St3Ty0iEiKgp6kB2spPWF96btllsIeCOkQH4hpMY0XMINnN9IeoigrSXFiEB9d7Lx5isksFIZ0JamEc+RgR1mYmBMllf5CSYMIs80aGhNqBePW2EnSrC+q3DP9d01Gfpt0vpGFtL3FONJVIW8Ga+mh2nFFa/B+RxaVMwBhXrClQo03979WLzctmsjuxj6CYD1jJKr9sWcEJchhWC84k9SQGGJF1VgnPhiI9LIugIGOOdZIKb+Nb5MyHLjnrix7nXlS8ufmKIEVanE18K3W3p4mF09vd9xA/83Kki6HGajt+f8TJyX9JX9d+gKVvm1mqBrpG4e5+ruLO176MZtWfiXtFRy1LBrcxuUt3UV7F7yetJ6YBiJW7m0znD2aW57B7rtmfv3NdRZxwZSarpcLB1EfVnFKJVvn1n92VnhyRXnrm0zTCwYEuszLgRyb2P7jY8ae5ZJpGp2cYVsQEeZz72BE+l0oj6aD2qtam9E/1bmnOogY+BQ77Q40PlXSKMIMggdNqmBHJN9nGEiElimRCuKMrpSHZa2l6MXVcplxBgEHtMvHulEqjnbd/8PyfFtN4h+vedkPPvzHexMtdne79hHTd7qE4CqECQguRHBdRcb+pBpeBM0+DIw5ZLGl19PGwbjPUOdJX5ubuxmxPaHvZXsNpQdu51SJOpZ8IOe1Ma7cQE2oL6ay0v/KrT4jd5slvnpjxI91UIjTVWIXZjVaO2z5FtH0h9w4J0P4GwnaQQkK4ArguKblCXAnQQMr0uQnd9v40FlLsoYBz7FdwFlQJZqZPo6aLNLRfqtRyy4Bolib1U3XJ+CuvBgc3O91G515PgO5+TfV/jjpt9r0ytrzzwbBkWbnIS8plU8gpWJ/Om3OYj4X0pGEcSd924cjUV5SiKIMTM9A6EYjv4KXqxqfCWD0INHfVUCoGrVN/Td6GQBikFHt2ta1MESciqfi+4CwBPcwHT0bSmwnb+GHDquTQf+3fGW+LMiYQ1uIVBWbYFyHmfJeGExGOZjNt87AU2cuIjjqU8B2nLSpxyZMkTperxLXx8LcDJSDQiy6v/kldpopVm1lvwvloAeeSGGEn2Ed2RKusXD0P8TcOkuxUvR6NY8nKDhj7igdFkiTnJ1kiGelyiUyss1pToOEWmfJyCPU7apgIWN0LRfrsWEg48jql1zkUer+pbMFm+W+PHvBwTMvKmztD9OlhNNQ/aFjJrEcXdKkaaK9s1YHNrYLLlsHfGq4/kzmCerI6/B26j1mHvj8ZUSQy+wHTj8NjM8Ir5OZt2xZ0p/ziivz7muWLbndPBoLiT/gjKOZzJPxwkSmbZ/MxBIoOStnLm+wgJg6RXy2PHduJslHHp2zUwdZwW+BjxZGlb/u+r7IhvNRp6hZxfv7HXqFBFascKnqGhfBbeaXk7WqXTltxmX0jMPTyCBFavL8y4553gh0fYDN6Yb1Unj7WFrPucjY7AsgtjKGnmhDSgH8+k8fBLODbWLhb3XK2vdbQTFm1mAn1X7ZXjeC+qNG0Z6llOLvZ5sNGmxfvY1vCFnYgXfqYW2pjerPi3jjLMiSwid50Uq0ZKO9BSwqEkYPN9qtSLUxOn291rdfOHaYbsHDL7NXbFvrCf/Hse1FT6FR0IqextuSZCRSrW/xj33IbigAKez3nd8jj2NDeusCiXms/rp26JP58ChX9H2lpVPRurvm1Ae8uLnJEG5FMnMk8l8P0wx3OF3HhRedc8wM4Po+IaNbdvd4m1L/SP+jzPJcsiVnadw7cb6WWG/Ycqm+GeYDo0H0Ew02erkHZpsm3Bc4n/0f9ya/XuCyYdDifxCOBHYT685qpHM7mK/3qNL+m7gESEEiHVBSxyjOjfuadMQAzIThSFUmvChr+hFME4JenIUJt9b/eW3jZ155RZr9y8M1N49pAFZgTZ/Zp8m73NYgs8oP/BXsbcHVDbg4nzc7rcL+wPwMEbTwn1aWWDhieib6NEsHAFQL64VuXoMcigJrYcOEulc1hexqDo+HTKM1rQI0y8nDnLANPgoONdVQ6RxWe8DwApPfYn0o9CywKW3vbuoEeUg/MwzlowNb4+XrAnxirZtCI/0D29Nc9gMi+frnikVhV6SIkqSUMImma8isuyanm1Pil9EAZAMtbP5m353bm0UtrldJ38mX2yUHqpbD9oEq2oCMTWamhERUJbrzV9TAqT76N3CTxmwMIJKKOFOkCgSNBuab/+e/f2zA4926qkK4lvVdEir2xx6PRme3xzhJNJInUElcGYLcZIkHJHed4nav5O7Ba/xz7HCrTqqtOf0kvs5rzPhqxC+C33M5HQ1aIQpyd9qAXqgGQAhw2tEegLxtDz9gIaIIFECFV0ReriWd2NRjntTYbaz4+3SIgMEu03z5vw+d5BRRBC9jqTre8NUAjEwmMBKSFhRcFOHXs4l7GHbIt8XeI8TpgeSi9UZmH4ZpeXqvy/chLrfxQB8O4J4+D0ct9qd6Dq03K1hEVkTNeQGKcGLNb1n53jWuhIOmAtOadF+dYpGOrjzre7yRuEg46ystyYddLJdytKJopK77bMEYwKxBSS+S6pnmR3cwahLrl+jr7GicCL+3Et57axLMxTXb2CcG0hwJCQ69ihEVO4dbTW6MRmfsrK2pX1hb1upul8cyS4lkWEUlQCpCmg==,iv:vygMsq1+zxUMHdu1+rtoZKWw4U2nkIm5Xd+r0S+Updk=,tag:KE5dpipxaMmear1UELtKsA==,type:str] +nixos-key: ENC[AES256_GCM,data:IEAp3ic6GYgS9432X2u0TTS+uykDAjsZFeo64S48mqphUQe0R04xTUz8qa4/QhdeiZeBysK86D5Wk9V7T/RMRw/Fzb3E0+xdvwQy9b6IFAWOxKXziyJzZAJRoHYIjiV6TsmkuwG2/tc0pojo9JeFPJhRwtgOax45i2VAwcyw6OeSdNn49YHtL1T5R7t5SCWLaRP+55Vp5gnr1DvnVMr439kOvAVFNB/HZ0515lH9iOXU5QPkcINJ4Mj1zx2iI6O7xL61Y/HfDX7F4E2baQQmqDqsiiKHS5vmqs29NSG1pd1G/8l2CsLpxnKiwYR8r0LyGIbD3PmMQod5lvvW8MDzw+/R3IiTbcJIwhFewRBNXwhCYd90Zr3YgntuNU35DeQ8z5xuELNkjwLSKpTCV2AAAIgtQk/8fUXaTCNaHLL7ZAEAah3twDa5E0ggwf009HCvwTBI3/F8H1i1+YZpCtdBDMKY5ldKPyXhIWChW+YbfaiIu8C+U5Cm+TiDHEX0zGnU2oq36BUiwB7CGsSgkX4XUVxE6SzeZ1xEx5LrFnKDcIzTP0g=,iv:75Sp1pZbVDqW1oZjigMoxvIuCpvZmyImHV0wgKEPvvY=,tag:74/GHjpktd8fm5qnoe4DHA==,type:str] +nixos-key-pub: ENC[AES256_GCM,data:NxnOa49ek2h8b4Fy1enRc+9l3+QEkqp9pUFWmJE9cw0/ACPbyqpNP259wINolwChbYA50Q5Oy30ix0Cvkw4CVxC1mwOHxk5z0wIKzNCBKIfxs9XzcNOT/Drc6Df3ycM4WU1jVXSFig==,iv:NflErE1TuZWTtGoWM3DOjWtdtCE/FYcIDtjhHSy+fJY=,tag:LYvz8rtNeDzLMmZU6s9FMQ==,type:str] +amity-key: ENC[AES256_GCM,data:YOqI+DT9EXkQuLaepKXXG44CG95KZ/mUdmmwaizjpw3kFzZkCDbm+Wuau4gCM7Y/BX0J46ZHxU85jo7Sh0kOi84ZmxlU/fCc62P7woxhTbWRUmBsmjH+PeZ4XORXPKQxVkLNl+vdLZxI9nag2+xE00CC9FeOFUJB7qlOyG1Tjn7xr8XpPgvrYfy5qdhl2X2sZfnBCvDTJsfL5c5nceriJsFDgH7AHsvk0k7XvY9TlH/FFTrTZ9MWUeHP9K/0wHC7glvl86RX8ME87CmDRMOfXY/mua3e/5cEqfzHwxU1pt4npEu7m+5whlNCzeLZ7GgA3Mr03soKky0YBctdrP/dOvvbMD9M9nEgFBOSfodkwyYJsUFT8TvTFl4BqPm+IfmQkJV4sP9BqMQT3I5fKSqqUnkh4q2H1Xfk0YlKZhtQRz/a8tUR/I6t6z7c79KzeDKVBT1DgAyEXdAhyFjoOvQcJuOHHQkYvu/SYxdwPgCiItwio77izljy9yOn9Da2v5L88i/TmIkz3N7Ddh4SVSkmWXHxO6V4yN8Yvrd6pyeN3V+gLy1M95/isj8mjB9g4qaVOLhtYRjqEs66/Zu9OB9rhY+9uwCi2OOGKrb4ifnur25bNQPQEsd6o9oISIsqAxhuApcVyyR/mBMsZm0hl2QGo3Rn4kkpFRfqf9PwFSVltvdW5GrMUwc0OVau8ZMHxfypck7/Ti6FeLR2Y+LS6g3LnWsanpgy9V6xIAOqs6zh+n3zNp8yIH9QvEr/aICHeo9QZ0l9OcGIgWJmsBb0FCacSPIuS3jp5MTB6x7z4NEddmQNIB7GHydI7Ai5GhfePKAzwicX4ZkxTnjPX888gILv/YikrNhSJs8s6nhbKZ6HtlxI/rm0E6knKbNzP+WNdeJW+xgLJS55hXFhaOFDlSPalZ3KDYVDLOKjEliJffIGxpBZvbhZhdw80Y2Va3I6fuBchP1LT3LBlbgV7pJ8fhgvsidJYTieR9ciPSTO5bvXIRShP71txiJxDfI23NVXsKbAIMJWa0990co3HW3RsphRp02CU3XvWrq268CgfeC7QHvLV4GoVqX3uyOMPxEFtWBzC4I+TtgQc5MiA7Ox6U3ujVYs+F6iMopcmXGdzku56EbFu+RJsKcfnRaCqv/WR3JU9JRD9Uvux6iyhthIusaUu0t6LQ47eVSjcfC3p16bGLqjGxotvI2KWrKfqRjRTTpXDWIiLCf4J34vOyrLPZM5JeWzaZH7Muyo/3EJMBT7AKtREpZ/MggyRX6XLTrXNbx/u3ciidqLcKk8kRGiP2SB3c/FWlPUUDIHowZ/hMIXYBxZFIbfYmBBRKmRtWqqDdlPEAv/dy+T/HEocKbOGXUIF7XeujOVQePhXpd4Lo7trpEHh52MWselL0+3O2kFXMQBtwZl9pypZWlbimx04TCfl78Pi1kv0mMQ1CvsQscB/8OMGVv451z9/8ZOWt+kOdRM/nCbIR3UuufJ+0uao+iSqLDNlHhROoUrABbViffVHjhOaWAk+ITgzrVnVugqpV1K40M0uRoDwUe+9a/pdXe2QbbS4f86052dmwQioMuvkV00A09YbwWa4twKTifODMDwiD/AFNlgCSNyF4W47vhwNJ8HdgTsM0K1LRovi5ouSuanDtQ+KL5Ww1r+0blq9GybP9eIgvrSi7Y084Z8w5DQfCCsFS9gcqaA1Wx6/0XLzVmMAeEtY/LfkvKW+udX/yyCBXBwm/6rl8GAYpmJFGn2gVg0K/bKm1bgLXBtxg9Vc1dQb+m+7M+RAPb51msKSl7C7V5hPCQwBUyx6RNe7MbfQXURkTG8CsAW8hRprpLyYFohVyeEznfrjnIGyJ7rLbVSlprygr8jbCURyu4Qduq95PkXrWiUTqEpDZEhiF9IYxaLAPqckeSlRjw2clB8de0Ic4+8ptrlRA/qsJoJ52IGDMRiyuOQCNybrTr0ZXfezESfF8B+USSlXZFGCZeQb4qF1gHJByllEEtnFNds97gR2JdR5uewKQO/UOuKc8HjbQbGgFTToFtoA0OPM/BlJ2QXJkAsfl9tg8drjPuruOkNxtZqYOyG+KyzUOifx+3g8clUmf8B4RI+idWfGiLOYplMxnlnulQb9DIj0e3BHyRneMa3SdqyYqYB2yhHltppKn+nrsXtQ8H1CGuC6bYnmYtMbjpvaKkaNJZrnEQA8JkoK3gZV3vN/ArVN5+20mPGnnTc9YjmgF8xI/KSR/Q5OXVtBVRM4UbsKuPeypjQZzAFnwbOF9IK1O+BTIoM1+S3ocztLnXQ2AGN6RyG9+dI93svGTMbUb82+YzhZryRTkLwpR4OeGD6+ERk7yzM/DhX/mOytledOJ1FjAuWrNpc9hgyEHjPQxPwyPp5D1Jvnnl4HJNBuNKe786qwyP4IQf6FoT+K308CBTzi2doRsezxoZ6qjukAxi8HeekXe4GSo77GEk1GLr7Txjq7+5EI5jX6ctIBFj8sK8OLPQaq3miqkljaTlLC7ZQgljbuuVujNCG09W+FiekIhHfoBMgHJJeu4+llwNcxLxfE2qxt2AQScRvJV66HJbbW1Ar9h8jJq9jhO8y8h+ObWRRrfiKZ+TczvzpgGmSQGqXJLqc7zuNIisMyhFOZ3g+whreZNbytU7nTYh3A2/dZAtCa0WSzPQX6omnz2+KulfrteqRGG8+kjTFi217zqDFMUiMQbHnPt4fPKr36ut5XSLOy8NX4pjJhwy5y+rvWTKt+t2g5r4OvdJlLeXDZRl2+5hDz72ZtP4m+NfLaG5wrenm5upEK2xSxiLjGoFNa3Jm8jtu24KOLogYBnkZRZedQSNr9ZMs/hAiDnLLeJ+7SsgSkyhwO5O+Lzll1VbMMFuyyssZwRanmJnxt7epW8UY8b2PgjYuiyILWp9cjN85OmgGPHDU7kwWs5Sj0Z0NFevUjbe4k+1Hob12iP2yrFCc9DX4ff6YhEvHNww+6RmjV8MYpvDMb24zMXeyu2QYgT9izJ9M4byq/fZyq4GSZDiY2OtprudLbaQUCBAKD43gMG+1gSrS7n4oc/+CqNjNlxicgFoa0HoMdJg4s6OYOPl1QQZJ2+0fxTFIVFgznT7fu96CSwD/Oq/d3e/EgMah9yZKlUTKe8XNLDDFFEaX2DF9vhCsWeJ+QK/TD9jFAO3q8vY0XO3UE191lawBV4vvbwkpeawJjq0Kdsb5rvcxhHEzlVKheKN2WkH8RExhOhEDBLkbAruNZbYWm71qsEEvN1YNenXzr7LHBKETwQnavag7yChcGNNUE+kuwCaYbv8LwB04RBTuyC+dVqOiF8nX5U7VNpI3CCzj0Ny08jwRxnzT0OM7gv/csxCJ9rBd40m/EtW47Nt6GzKLHCXRfFOgQm3R39inSqz/K/fXiNQqkuQwcN9iMATnQXzTbCllOoUPyzvcz+T4eEXF23mFFO+ridibha2HdsgylPnAqXTweAjm0Tg/WQ==,iv:s7/Q+eQJpRnKLFKweNfI4NXM3TWm97KPDHIFu8cAwqM=,tag:HXJDO/YmKtZiUKhI0VSEuw==,type:str] sops: kms: [] gcp_kms: [] @@ -32,8 +42,8 @@ sops: cDRpZkkxZWhiVmN1Y1FSRm5seVpmbnMKl7CHdNdXOr67tCjYp+jhUSYImndyvhQP heUpcdBCJADlE9oG6lDr4ngwdHFqVrN757uMqZWEbT80hzZUXVRArw== -----END AGE ENCRYPTED FILE----- - lastmodified: "2023-08-18T19:45:59Z" - mac: ENC[AES256_GCM,data:1dNhVFD2+V8tlIjC2/0X7m9cpBZAN7iIkSLqZJfeGYVBWreBS1Bst0n+jw41mCsM5KTz4S2jE559M+P552UAcqsYBCu7CmHtmBcLuGuouL3Nl0rlGsJLC+61O1/7bo2qg7OP+Bu9A40mtl8rSfCU4i4Axd3kBTN0Z+upNBG7f4M=,iv:sEymKxdswbUZweMw3xMpwdYZ/75vPGvtmVU7WZzlE2w=,tag:ZkAMomlWe+dg1Nsfel8FYw==,type:str] + lastmodified: "2023-10-26T22:09:17Z" + mac: ENC[AES256_GCM,data:nNAr/yIJ15akWZ+qQx4ax8LxNBjChkYstCKPzi89jAxmtRZNH1Io4zrDmNE4JWO4wjb9RYPtVlxeQkGZ0HeGAp5GfXnlEM8XtpMEPDfk6fLJ2yxPHdHwQs0BAdSB2QuAfDheGCJYlxSAyaUuN4EUlPHcbgFWBokdUb96JuPY1eM=,iv:wm9kq2S40pwXPCfFI2H/WwWGNofqB3PTYfxf2FSA3A0=,tag:9RPArhEwTYNEzBCX0UANSA==,type:str] pgp: [] unencrypted_suffix: _unencrypted - version: 3.7.3 + version: 3.8.1 diff --git a/home/isabel/services/x11/default.nix b/modules/common/types/desktop/default.nix similarity index 100% rename from home/isabel/services/x11/default.nix rename to modules/common/types/desktop/default.nix diff --git a/modules/common/types/laptop/adb.nix b/modules/common/types/laptop/adb.nix index 2c915b01e..ebdbf6f77 100644 --- a/modules/common/types/laptop/adb.nix +++ b/modules/common/types/laptop/adb.nix @@ -4,12 +4,10 @@ ... } @ args: with lib; let - device = config.modules.device; + inherit (config.modules) device; in { config = mkIf (device.type == "laptop" || device.type == "hybrid") { services = { - # TODO: move android adb rule elsewhere - # this should probably be a device or programs option udev.extraRules = let inherit (import ./plugged.nix args) plugged unplugged; in '' diff --git a/modules/common/types/laptop/default.nix b/modules/common/types/laptop/default.nix index 4328f787f..d3c6a3f2e 100644 --- a/modules/common/types/laptop/default.nix +++ b/modules/common/types/laptop/default.nix @@ -1,18 +1,7 @@ -{ - config, - lib, - ... -}: -with lib; let - device = config.modules.device; -in { +_: { imports = [ ./power ./adb.nix ./touchpad.nix ]; - - config = - mkIf (device.type == "laptop" || device.type == "hybrid") { - }; } diff --git a/modules/common/types/laptop/power/default.nix b/modules/common/types/laptop/power/default.nix index 7f47b5a06..408f4fd35 100644 --- a/modules/common/types/laptop/power/default.nix +++ b/modules/common/types/laptop/power/default.nix @@ -2,13 +2,16 @@ config, lib, pkgs, + inputs, ... -} @ args: -with lib; let - device = config.modules.device; +} @ args: let + inherit (lib) mkDefault mkIf; + inherit (config.modules) device; MHz = x: x * 1000; in { + imports = [inputs.auto-cpufreq.nixosModules.default]; + config = mkIf (device.type == "laptop" || device.type == "hybrid") { hardware.acpilight.enable = true; @@ -17,10 +20,29 @@ in { powertop ]; + programs.auto-cpufreq = { + enable = true; + settings = { + battery = { + governor = "powersave"; + scaling_min_freq = mkDefault (MHz 1200); + scaling_max_freq = mkDefault (MHz 1800); + turbo = "never"; + }; + charger = { + governor = "performance"; + scaling_min_freq = mkDefault (MHz 1800); + scaling_max_freq = mkDefault (MHz 3000); + turbo = "auto"; + }; + }; + }; + services = { - # superior power management - auto-cpufreq.enable = true; + # handle ACPI events + acpid.enable = true; + # a very cool user-selected power profiles helping my system not die 5 mins into my lecture power-profiles-daemon.enable = true; # temperature target on battery @@ -29,6 +51,10 @@ in { package = pkgs.undervolt; }; + /* + # superior power management + auto-cpufreq.enable = true; + auto-cpufreq.settings = { battery = { governor = "powersave"; @@ -43,6 +69,7 @@ in { turbo = "auto"; }; }; + */ # DBus service that provides power management support to applications. upower = { @@ -63,11 +90,12 @@ in { }; boot = { kernelModules = ["acpi_call"]; - extraModulePackages = with config.boot.kernelPackages; [ - acpi_call - cpupower - pkgs.cpupower-gui - ]; + extraModulePackages = with config.boot.kernelPackages; + [ + acpi_call + cpupower + ] + ++ [pkgs.cpupower-gui]; }; }; } diff --git a/modules/common/types/laptop/touchpad.nix b/modules/common/types/laptop/touchpad.nix index b1b42d8ef..1d9592bd7 100644 --- a/modules/common/types/laptop/touchpad.nix +++ b/modules/common/types/laptop/touchpad.nix @@ -2,29 +2,30 @@ config, lib, ... -}: -with lib; let - device = config.modules.device; +}: let + inherit (config.modules) device; in { - # TODO: touchpads shouldn't be enabled on *all* hybrid devices (server/personal) - # this should be an option under the device module - config = mkIf (device.type == "laptop" || device.type == "hybrid") { + config = lib.mkIf (device.type == "laptop" || device.type == "hybrid") { services = { # Input settings for libinput xserver.libinput = { enable = true; - # disable mouse acceleration - mouse.accelProfile = "flat"; - mouse.accelSpeed = "0"; - mouse.middleEmulation = false; + # disable mouse acceleration (yes im gamer) + mouse = { + accelProfile = "flat"; + accelSpeed = "0"; + middleEmulation = false; + }; # touchpad settings - touchpad.naturalScrolling = true; - touchpad.tapping = true; - touchpad.clickMethod = "clickfinger"; - touchpad.horizontalScrolling = false; - touchpad.disableWhileTyping = true; + touchpad = { + naturalScrolling = true; + tapping = true; + clickMethod = "clickfinger"; + horizontalScrolling = false; + disableWhileTyping = true; + }; }; }; }; diff --git a/modules/common/types/server/default.nix b/modules/common/types/server/default.nix index 32d413966..e6eb35f38 100644 --- a/modules/common/types/server/default.nix +++ b/modules/common/types/server/default.nix @@ -1,53 +1,6 @@ -{ - config, - lib, - ... -}: let - inherit (lib) mkIf; - inherit (config.modules) device; - acceptedTypes = ["server"]; -in { +_: { imports = [ ./services ./system ]; - - config = mkIf (builtins.elem device.type acceptedTypes) { - sound.enable = false; - environment = { - # we don't need any x libs on a server - # noXlibs = true; - - # print the URL instead on servers - variables.BROWSER = "echo"; - }; - - # https://github.com/numtide/srvos/blob/main/nixos/server/default.nix - systemd = { - # given that our systems are headless, emergency mode is useless. - # we prefer the system to attempt to continue booting so - # that we can hopefully still access it remotely. - enableEmergencyMode = false; - - # For more detail, see: - # https://0pointer.de/blog/projects/watchdog.html - watchdog = { - # systemd will send a signal to the hardware watchdog at half - # the interval defined here, so every 10s. - # If the hardware watchdog does not get a signal for 20s, - # it will forcefully reboot the system. - runtimeTime = "20s"; - # Forcefully reboot if the final stage of the reboot - # hangs without progress for more than 30s. - # For more info, see: - # https://utcc.utoronto.ca/~cks/space/blog/linux/SystemdShutdownWatchdog - rebootTime = "30s"; - }; - - sleep.extraConfig = '' - AllowSuspend=no - AllowHibernation=no - ''; - }; - }; } diff --git a/modules/common/types/server/services/cloudflare/default.nix b/modules/common/types/server/services/cloudflared/default.nix similarity index 62% rename from modules/common/types/server/services/cloudflare/default.nix rename to modules/common/types/server/services/cloudflared/default.nix index 2ab402d6d..2153ab12e 100644 --- a/modules/common/types/server/services/cloudflare/default.nix +++ b/modules/common/types/server/services/cloudflared/default.nix @@ -4,15 +4,15 @@ ... }: let inherit (lib) mkIf; + inherit (config.networking) domain; in { - services.cloudflared = mkIf (config.modules.services.cloudflare.enable) { + services.cloudflared = mkIf (config.modules.services.cloudflared.enable) { enable = true; - user = "${config.modules.system.mainUser}"; - tunnels."${config.modules.services.cloudflare.id}" = { + tunnels.${config.networking.hostName} = { credentialsFile = "${config.sops.secrets.cloudflared-hydra.path}"; default = "http_status:404"; ingress = { - "tv.isabelroses.com" = "http://localhost:8096"; + "tv.${domain}" = "http://localhost:8096"; }; }; }; diff --git a/modules/common/types/server/services/containers/default.nix b/modules/common/types/server/services/containers/default.nix new file mode 100644 index 000000000..b3456eeb2 --- /dev/null +++ b/modules/common/types/server/services/containers/default.nix @@ -0,0 +1,29 @@ +{ + config, + lib, + ... +}: let + cfg = config.modules.services; +in { + virtualisation.oci-containers = { + backend = "docker"; # podman hates this image + + containers = { + "isabelroses-com" = lib.mkIf cfg.isabelroses-web.enable { + image = "docker.io/isabelroses/isabelroses.com:latest"; + ports = ["3000:3000"]; + extraOptions = [ + "--pull=newer" + ]; + environmentFiles = [ + config.sops.secrets.isabelroses-web-env.path + ]; + login = { + registry = "docker.io"; + username = "isabelroses"; + passwordFile = config.sops.secrets.docker-hub.path; + }; + }; + }; + }; +} diff --git a/modules/common/types/server/services/cyberchef/default.nix b/modules/common/types/server/services/cyberchef/default.nix new file mode 100644 index 000000000..5e7f1dec5 --- /dev/null +++ b/modules/common/types/server/services/cyberchef/default.nix @@ -0,0 +1,24 @@ +{ + self, + lib, + config, + pkgs, + ... +}: let + inherit (config.networking) domain; +in { + services.nginx.virtualHosts."chef.${domain}" = lib.mkIf config.modules.services.cyberchef.enable { + default = true; + forceSSL = true; + enableACME = true; + listen = [ + { + ssl = false; + port = 8000; + addr = "127.0.0.1"; + } + ]; + root = self.packages.${pkgs.hostPlatform.system}.cyberchef; + }; + networking.firewall.allowedTCPPorts = [8000]; +} diff --git a/modules/common/types/server/services/databases/default.nix b/modules/common/types/server/services/databases/default.nix new file mode 100644 index 000000000..8d3d569f2 --- /dev/null +++ b/modules/common/types/server/services/databases/default.nix @@ -0,0 +1,8 @@ +_: { + imports = [ + ./mongodb + ./postgresql + ./mysql + ./redis + ]; +} diff --git a/modules/common/types/server/services/databases/mongodb/default.nix b/modules/common/types/server/services/databases/mongodb/default.nix new file mode 100644 index 000000000..faca428d2 --- /dev/null +++ b/modules/common/types/server/services/databases/mongodb/default.nix @@ -0,0 +1,25 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib) mkIf; + + dev = config.modules.device; + cfg = config.modules.services; + acceptedTypes = ["server" "hybrid"]; +in { + config = mkIf ((builtins.elem dev.type acceptedTypes) && cfg.database.mongodb.enable) { + services.mongodb = { + enable = true; + package = pkgs.mongodb; + enableAuth = true; + initialRootPassword = config.sops.secrets.mongodb-passwd.path; + #bind_ip = "0.0.0.0"; + extraConfig = '' + operationProfiling.mode: all + ''; + }; + }; +} diff --git a/modules/common/types/server/services/databases/mysql/default.nix b/modules/common/types/server/services/databases/mysql/default.nix new file mode 100644 index 000000000..cc31916de --- /dev/null +++ b/modules/common/types/server/services/databases/mysql/default.nix @@ -0,0 +1,30 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib) mkIf; + + dev = config.modules.device; + cfg = config.modules.services; + acceptedTypes = ["server" "hybrid"]; +in { + config = mkIf ((builtins.elem dev.type acceptedTypes) && cfg.database.mysql.enable) { + services.mysql = { + enable = true; + package = pkgs.mariadb; + + # databases and users + ensureDatabases = ["mkm"]; + ensureUsers = [ + { + name = "mkm"; + ensurePermissions = { + "mkm.*" = "ALL PRIVILEGES"; + }; + } + ]; + }; + }; +} diff --git a/modules/common/types/server/services/databases/postgresql/default.nix b/modules/common/types/server/services/databases/postgresql/default.nix new file mode 100644 index 000000000..ff8acb966 --- /dev/null +++ b/modules/common/types/server/services/databases/postgresql/default.nix @@ -0,0 +1,60 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib) mkIf; + + dev = config.modules.device; + cfg = config.modules.services; + acceptedTypes = ["server" "hybrid"]; +in { + config = mkIf ((builtins.elem dev.type acceptedTypes) && cfg.database.postgresql.enable) { + services.postgresql = { + enable = true; + package = pkgs.postgresql; + dataDir = "/srv/storage/postgresql/${config.services.postgresql.package.psqlSchema}"; + + enableTCPIP = false; + + checkConfig = true; + settings = { + log_connections = true; + log_statement = "all"; + logging_collector = true; + log_disconnections = true; + log_destination = lib.mkForce "syslog"; + }; + + ensureDatabases = [ + "nextcloud" + "forgejo" + "grafana" + "vaultwarden" + ]; + ensureUsers = [ + { + name = "postgres"; + ensurePermissions."ALL TABLES IN SCHEMA public" = "ALL PRIVILEGES"; + } + { + name = "forgejo"; + ensurePermissions."DATABASE forgejo" = "ALL PRIVILEGES"; + } + { + name = "grafana"; + ensurePermissions."DATABASE grafana" = "ALL PRIVILEGES"; + } + { + name = "nextcloud"; + ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES"; + } + { + name = "vaultwarden"; + ensurePermissions."DATABASE vaultwarden" = "ALL PRIVILEGES"; + } + ]; + }; + }; +} diff --git a/modules/common/types/server/services/databases/redis/default.nix b/modules/common/types/server/services/databases/redis/default.nix new file mode 100644 index 000000000..e0b7999a8 --- /dev/null +++ b/modules/common/types/server/services/databases/redis/default.nix @@ -0,0 +1,40 @@ +{ + config, + lib, + ... +}: let + inherit (lib) mkIf; + + cfg = config.modules.services; +in { + config = mkIf cfg.database.redis.enable { + services.redis = { + vmOverCommit = true; + servers = { + nextcloud = mkIf cfg.nextcloud.enable { + enable = true; + user = "nextcloud"; + port = 0; + }; + + forgejo = mkIf cfg.forgejo.enable { + enable = true; + user = "forgejo"; + port = 6371; + databases = 16; + logLevel = "debug"; + requirePass = "forgejo"; + }; + + searxng = mkIf cfg.searxng.enable { + enable = true; + user = "searx"; + port = 6370; + databases = 16; + logLevel = "debug"; + requirePass = "searxng"; + }; + }; + }; + }; +} diff --git a/modules/common/types/server/services/default.nix b/modules/common/types/server/services/default.nix index 67b234ee8..e486ef9d3 100644 --- a/modules/common/types/server/services/default.nix +++ b/modules/common/types/server/services/default.nix @@ -1,11 +1,19 @@ _: { imports = [ - ./cloudflare - ./gitea + ./cloudflared + ./containers + ./cyberchef + ./databases + ./forgejo ./jellyfin ./mailserver + ./matrix + ./miniflux + ./monitoring + ./nextcloud ./nginx ./photoprism ./vaultwarden + ./wakatime ]; } diff --git a/modules/common/types/server/services/forgejo/default.nix b/modules/common/types/server/services/forgejo/default.nix new file mode 100644 index 000000000..dd2948754 --- /dev/null +++ b/modules/common/types/server/services/forgejo/default.nix @@ -0,0 +1,147 @@ +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.modules.services.forgejo; + inherit (config.networking) domain; + forgejo_domain = "git.${domain}"; + + # stole this from https://git.winston.sh/winston/deployment-flake/src/branch/main/config/services/gitea.nix who stole it from https://github.com/getchoo + theme = pkgs.fetchzip { + url = "https://github.com/catppuccin/gitea/releases/download/v0.4.1/catppuccin-gitea.tar.gz"; + sha256 = "sha256-14XqO1ZhhPS7VDBSzqW55kh6n5cFZGZmvRCtMEh8JPI="; + stripRoot = false; + }; +in { + config = mkIf cfg.enable { + networking.firewall.allowedTCPPorts = [ + config.services.forgejo.settings.server.HTTP_PORT + config.services.forgejo.settings.server.SSH_PORT + ]; + + modules.services.database = { + redis.enable = true; + postgresql.enable = true; + }; + + systemd.services = { + forgejo = { + after = ["sops-nix.service"]; + preStart = let + inherit (config.services.forgejo) stateDir; + in + lib.mkAfter '' + rm -rf ${stateDir}/custom/public + mkdir -p ${stateDir}/custom/public + ln -sf ${theme} ${stateDir}/custom/public/css + ''; + }; + }; + + services = { + forgejo = { + enable = true; + package = pkgs.forgejo; + stateDir = "/srv/storage/forgejo/data"; + lfs.enable = true; + + mailerPasswordFile = config.sops.secrets.mailserver-git-nohash.path; + + settings = { + server = { + ROOT_URL = "https://${forgejo_domain}"; + HTTP_PORT = 7000; + DOMAIN = "${forgejo_domain}"; + + BUILTIN_SSH_SERVER_USER = "git"; + DISABLE_ROUTER_LOG = true; + LANDING_PAGE = "/explore/repos"; + + START_SSH_SERVER = true; + SSH_CREATE_AUTHORIZED_KEYS_FILE = true; + SSH_PORT = 2222; + SSH_LISTEN_PORT = 2222; + }; + + api.ENABLE_SWAGGER = false; + + default.APP_NAME = "iztea"; + attachment.ALLOWED_TYPES = "*/*"; + + ui = { + DEFAULT_THEME = "catppuccin-mocha-sapphire"; + THEMES = + builtins.concatStringsSep + "," + (["auto,forgejo-auto,forgejo-dark,forgejo-light,arc-gree,gitea"] + ++ (map (name: lib.removePrefix "theme-" (lib.removeSuffix ".css" name)) + (builtins.attrNames (builtins.readDir theme)))); + }; + + # "ui.meta" = { + # AUTHOR = "Isabel Roses"; + # DESCRIPTION = "A super cool place to host git repos"; + # KEYWORDS = "git,self-hosted,gitea,forgejo,isabelroses,catppuccin,open-source,nix,nixos"; + # }; + + actions = { + ENABLED = true; + DEFAULT_ACTIONS_URL = "https://code.forgejo.org"; + }; + + database = { + DB_TYPE = lib.mkForce "postgres"; + HOST = "/run/postgresql"; + NAME = "forgejo"; + USER = "forgejo"; + PASSWD = "forgejo"; + }; + + cache = { + ENABLED = true; + ADAPTER = "redis"; + HOST = "redis://:forgejo@localhost:6371"; + }; + + service = { + DISABLE_REGISTRATION = true; + EMAIL_DOMAIN_ALLOWLIST = "isabelroses.com"; + }; + + other = { + SHOW_FOOTER_VERSION = false; + SHOW_FOOTER_TEMPLATE_LOAD_TIME = false; + ENABLE_FEED = false; + }; + + migrations.ALLOWED_DOMAINS = "github.com, *.github.com, gitlab.com, *.gitlab.com"; + packages.ENABLED = false; + repository.PREFERRED_LICENSES = "MIT,GPL-3.0,GPL-2.0,LGPL-3.0,LGPL-2.1"; + + "repository.upload" = { + FILE_MAX_SIZE = 100; + MAX_FILES = 10; + }; + + mailer = { + ENABLED = true; + PROTOCOL = "smtps"; + SMTP_ADDR = "mail.${domain}"; + USER = "git@${domain}"; + }; + }; + + # backup + dump = { + enable = true; + backupDir = "/srv/storage/forgejo/dump"; + interval = "06:00"; + type = "tar.zst"; + }; + }; + }; + }; +} diff --git a/modules/common/types/server/services/gitea/default.nix b/modules/common/types/server/services/gitea/default.nix deleted file mode 100644 index dbbc32da2..000000000 --- a/modules/common/types/server/services/gitea/default.nix +++ /dev/null @@ -1,79 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: -with lib; let - device = config.modules.device; - acceptedTypes = ["server" "hybrid"]; - cfg = config.modules.services.gitea; - domain = "git.isabelroses.com"; -in { - config = mkIf (builtins.elem device.type acceptedTypes && cfg.enable) { - networking.firewall.allowedTCPPorts = [config.services.gitea.settings.server.HTTP_PORT]; - - services = { - gitea = { - enable = true; - package = pkgs.forgejo; - appName = "iztea"; - lfs.enable = true; - user = "git"; - database.user = "git"; - stateDir = "/srv/storage/gitea/data"; - - mailerPasswordFile = config.sops.secrets.mailserver-gitea.path; - dump = { - enable = true; - backupDir = "/srv/storage/gitea/dump"; - interval = "06:00"; - type = "tar.zst"; - }; - - settings = { - server = { - ROOT_URL = "https://${domain}"; - HTTP_PORT = 7000; - DOMAIN = "${domain}"; - - START_SSH_SERVER = false; - BUILTIN_SSH_SERVER_USER = "git"; - SSH_PORT = 22; - DISABLE_ROUTER_LOG = true; - SSH_CREATE_AUTHORIZED_KEYS_FILE = true; - LANDING_PAGE = "/explore/repos"; - }; - - attachment.ALLOWED_TYPES = "*/*"; - service.DISABLE_REGISTRATION = true; - ui.DEFAULT_THEME = "arc-green"; - migrations.ALLOWED_DOMAINS = "github.com, *.github.com, gitlab.com, *.gitlab.com"; - packages.ENABLED = false; - repository.PREFERRED_LICENSES = "MIT,GPL-3.0,GPL-2.0,LGPL-3.0,LGPL-2.1"; - - "repository.upload" = { - FILE_MAX_SIZE = 100; - MAX_FILES = 10; - }; - - mailer = { - ENABLED = true; - PROTOCOL = "smtps"; - SMTP_ADDR = "mail.isabelroses.com"; - USER = "gitea@isabelroses.com"; - }; - }; - }; - - openssh = { - extraConfig = '' - Match User git - AuthorizedKeysCommandUser git - AuthorizedKeysCommand ${lib.getExe pkgs.forgejo} keys -e git -u %u -t %t -k %k - Match all - ''; - }; - }; - }; -} diff --git a/modules/common/types/server/services/jellyfin/default.nix b/modules/common/types/server/services/jellyfin/default.nix index 8bf784379..f4d6701ae 100644 --- a/modules/common/types/server/services/jellyfin/default.nix +++ b/modules/common/types/server/services/jellyfin/default.nix @@ -4,40 +4,14 @@ ... }: let inherit (lib) mkIf; - device = config.modules.device; cfg = config.modules.services.jellyfin; - acceptedTypes = ["server" "hybrid"]; in { - config = mkIf (builtins.elem device.type acceptedTypes && cfg.enable) { - # NOT docker - services = mkIf (!cfg.asDockerContainer) { - jellyfin = { - enable = true; - group = "jellyfin"; - user = "jellyfin"; - openFirewall = true; - }; - }; - - # with docker - modules.system.virtualization = mkIf (cfg.asDockerContainer) { + config = mkIf cfg.enable { + services.jellyfin = { enable = true; - docker.enable = true; - }; - - virtualisation.oci-containers.containers.jellyfin = mkIf (cfg.asDockerContainer) { - image = "lscr.io/linuxserver/jellyfin:latest"; - environment = { - "PUID" = "1000"; - "PGID" = "1000"; - "TZ" = "Europe/London"; - }; - volumes = [ - "/home/isabel/docker/jellyfin:/config" - "/mnt/media:/data" - ]; - ports = ["8096:8096"]; - autoStart = true; + group = "jellyfin"; + user = "jellyfin"; + openFirewall = true; }; }; } diff --git a/modules/common/types/server/services/mailserver/default.nix b/modules/common/types/server/services/mailserver/default.nix index f61e59bbf..2c7e534f1 100644 --- a/modules/common/types/server/services/mailserver/default.nix +++ b/modules/common/types/server/services/mailserver/default.nix @@ -4,45 +4,64 @@ pkgs, inputs, ... -}: -with lib; let - device = config.modules.device; +}: let + inherit (config.networking) domain; cfg = config.modules.services.mailserver; - acceptedTypes = ["server" "hybrid"]; in { imports = [ inputs.simple-nixos-mailserver.nixosModule ]; - config = mkIf (builtins.elem device.type acceptedTypes && cfg.enable) { + config = lib.mkIf cfg.enable { # required for roundcube networking.firewall.allowedTCPPorts = [80 443]; + systemd.services = let + template = {after = ["sops-nix.service"];}; + in { + roundcube = template; + mailserver = template; + }; + services = { roundcube = { enable = true; + + package = pkgs.roundcube.withPlugins ( + plugins: + with plugins; [ + persistent_login + # carddav + ] + ); + database.username = "roundcube"; maxAttachmentSize = 50; + dicts = with pkgs.aspellDicts; [en]; - # this is the url of the vhost, not necessarily the same as the fqdn of - # the mailserver - hostName = "webmail.isabelroses.com"; + + plugins = [ + # "carddav" + "persistent_login" + ]; + + # this is the url of the vhost, not necessarily the same as the fqdn of the mailserver + hostName = "webmail.${domain}"; extraConfig = '' $config['imap_host'] = array( - 'tls://mail.isabelroses.com' => "Isabelroses's Mail Server", + 'ssl://${config.mailserver.fqdn}' => "Isabelroses's Mail Server", 'ssl://imap.gmail.com:993' => 'Google Mail', ); $config['username_domain'] = array( - 'mail.isabelroses.com' => 'isabelroses.com', + '${config.mailserver.fqdn}' => '${domain}', 'mail.gmail.com' => 'gmail.com', ); $config['x_frame_options'] = false; # starttls needed for authentication, so the fqdn required to match # the certificate - $config['smtp_host'] = "tls://${config.mailserver.fqdn}"; + $config['smtp_host'] = "ssl://${config.mailserver.fqdn}"; $config['smtp_user'] = "%u"; $config['smtp_pass'] = "%p"; - $config['plugins'] = [ "carddav" ]; ''; }; @@ -54,17 +73,12 @@ in { "blacklist.woody.ch" ]; dnsBlacklistOverrides = '' - isabelroses.com OK - mail.isabelroses.com OK + ${domain} OK + ${config.mailserver.fqdn} OK 127.0.0.0/8 OK + 10.0.0.0/8 OK 192.168.0.0/16 OK ''; - headerChecks = [ - { - action = "IGNORE"; - pattern = "/^User-Agent.*Roundcube Webmail/"; - } - ]; config = { smtp_helo_name = config.mailserver.fqdn; @@ -79,9 +93,11 @@ in { mailserver = { enable = true; - mailDirectory = "/srv/storage/mail/vmail"; - dkimKeyDirectory = "/srv/storage/mail/dkim"; - sieveDirectory = "/srv/storage/mail/sieve"; + # make sure the perms here is + # /srv/storage/mail/ # 775 + mailDirectory = "/srv/storage/mail/vmail"; # 770 + dkimKeyDirectory = "/srv/storage/mail/dkim"; # 775 + sieveDirectory = "/srv/storage/mail/sieve"; # 770 openFirewall = true; enableImap = true; enableImapSsl = true; @@ -91,24 +107,52 @@ in { enableSubmissionSsl = true; hierarchySeparator = "/"; localDnsResolver = false; - fqdn = "mail.isabelroses.com"; + fqdn = "mail.${domain}"; certificateScheme = "acme-nginx"; - domains = ["isabelroses.com"]; + domains = ["${domain}"]; loginAccounts = { - "isabel@isabelroses.com" = { + "isabel@${domain}" = { hashedPasswordFile = config.sops.secrets.mailserver-isabel.path; - aliases = ["isabel" "me@isabelroses.com" "admin" "admin@isabelroses.com" "root" "root@isabelroses.com" "postmaster" "postmaster@isabelroses.com"]; + aliases = [ + "isabel" + "isabelroses" + "isabelroses@${domain}" + "bell" + "bell@${domain}" + "me@${domain}" + "admin" + "admin@${domain}" + "root" + "root@${domain}" + "postmaster" + "postmaster@${domain}" + ]; }; - "gitea@isabelroses.com" = { - aliases = ["gitea"]; - hashedPasswordFile = config.sops.secrets.mailserver-gitea.path; + "git@${domain}" = { + aliases = ["git" "git@${domain}"]; + hashedPasswordFile = config.sops.secrets.mailserver-git.path; }; - "vaultwarden@isabelroses.com" = { - aliases = ["vaultwarden"]; + "vaultwarden@${domain}" = { + aliases = ["vaultwarden" "bitwarden" "bitwarden@${domain}"]; hashedPasswordFile = config.sops.secrets.mailserver-vaultwarden.path; }; + + "grafana@${domain}" = { + aliases = ["grafana" "monitor" "monitor@${domain}"]; + hashedPasswordFile = config.sops.secrets.mailserver-grafana.path; + }; + + "noreply@${domain}" = { + aliases = ["noreply"]; + hashedPasswordFile = config.sops.secrets.mailserver-noreply.path; + }; + + "spam@${domain}" = { + aliases = ["spam" "shush" "shush@${domain}" "stfu" "stfu@${domain}"]; + hashedPasswordFile = config.sops.secrets.mailserver-spam.path; + }; }; mailboxes = { diff --git a/modules/common/types/server/services/matrix/default.nix b/modules/common/types/server/services/matrix/default.nix new file mode 100644 index 000000000..1d314aec1 --- /dev/null +++ b/modules/common/types/server/services/matrix/default.nix @@ -0,0 +1,156 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib) mkIf; + inherit (config.networking) domain; + + cfg = config.modules.services; + + port = 8008; + bindAddress = "::1"; + serverConfig."m.server" = "${config.services.matrix-synapse.settings.server_name}:443"; + clientConfig = { + "m.homeserver".base_url = "https://${config.networking.hostName}${domain}"; + "m.identity_server" = {}; + }; + + mkWellKnown = data: '' + add_header Content-Type application/json; + add_header Access-Control-Allow-Origin *; + add_header 'Referrer-Policy' 'origin-when-cross-origin'; + add_header X-Frame-Options DENY; + add_header X-Content-Type-Options nosniff; + return 200 '${builtins.toJSON data}'; + ''; +in { + config = mkIf cfg.matrix.enable { + networking.firewall.allowedTCPPorts = [port]; + + services = { + postgresql = { + enable = true; + initialScript = pkgs.writeText "synapse-init.sql" '' + CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse'; + CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse" + TEMPLATE template0 + LC_COLLATE = "C" + LC_CTYPE = "C"; + ''; + }; + + nginx.virtualHosts = { + "${domain}" = { + locations = { + "= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig; + "= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig; + "/_matrix".proxyPass = "http://[${bindAddress}]:${toString port}"; + "/_synapse/client".proxyPass = "http://[${bindAddress}]:${toString port}"; + }; + }; + }; + + matrix-synapse = { + enable = true; + + extraConfigFiles = [config.sops.secrets.matrix.path]; + settings = { + withJemalloc = true; + enable_registration = true; + registration_requires_token = true; + + bcrypt_rounds = 14; + + # Don't report anonymized usage statistics + report_stats = false; + + /* + # db + database = { + name = "psycopg2"; + args = { + user = "matrix-synapse"; + database = "matrix-synapse"; + }; + }; + */ + server_name = domain; + public_baseurl = "https://${domain}"; + + # media + media_retention.remote_media_lifetime = "30d"; + max_upload_size = "100M"; + url_preview_enabled = true; + url_preview_ip_range_blacklist = [ + "127.0.0.0/8" + "10.0.0.0/8" + "172.16.0.0/12" + "192.168.0.0/16" + "100.64.0.0/10" + "192.0.0.0/24" + "169.254.0.0/16" + "192.88.99.0/24" + "198.18.0.0/15" + "192.0.2.0/24" + "198.51.100.0/24" + "203.0.113.0/24" + "224.0.0.0/4" + "::1/128" + "fe80::/10" + "fc00::/7" + "2001:db8::/32" + "ff00::/8" + "fec0::/10" + ]; + + # listener configuration + listeners = [ + { + inherit port; + bind_addresses = ["${bindAddress}"]; + resources = [ + { + names = ["client" "federation"]; + compress = true; + } + ]; + tls = false; + type = "http"; + x_forwarded = true; + } + ]; + + logConfig = '' + version: 1 + + # In systemd's journal, loglevel is implicitly stored, so let's omit it + # from the message text. + formatters: + journal_fmt: + format: '%(name)s: [%(request)s] %(message)s' + + filters: + context: + (): synapse.util.logcontext.LoggingContextFilter + request: "" + + handlers: + journal: + class: systemd.journal.JournalHandler + formatter: journal_fmt + filters: [context] + SYSLOG_IDENTIFIER: synapse + + root: + level: WARNING + handlers: [journal] + + disable_existing_loggers: False + ''; + }; + }; + }; + }; +} diff --git a/modules/common/types/server/services/miniflux/default.nix b/modules/common/types/server/services/miniflux/default.nix new file mode 100644 index 000000000..4085471ac --- /dev/null +++ b/modules/common/types/server/services/miniflux/default.nix @@ -0,0 +1,89 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib) mkIf; + + cfg = config.modules.services; +in { + config = mkIf cfg.miniflux.enable { + # https://github.com/Gerg-L/nixos/blob/master/hosts/gerg-desktop/services/miniflux.nix + + systemd.services = { + miniflux = { + description = "Miniflux service"; + wantedBy = ["multi-user.target"]; + requires = ["miniflux-dbsetup.service"]; + after = ["network.target" "postgresql.service" "miniflux-dbsetup.service"]; + script = lib.getExe' pkgs.miniflux "miniflux"; + + serviceConfig = { + User = "miniflux"; + RuntimeDirectory = "miniflux"; + RuntimeDirectoryMode = "0770"; + EnvironmentFile = config.sops.secrets.miniflux-env.path; + + # Hardening + CapabilityBoundingSet = [""]; + DeviceAllow = [""]; + LockPersonality = true; + MemoryDenyWriteExecute = true; + PrivateDevices = true; + PrivateUsers = true; + ProcSubset = "pid"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + RestrictAddressFamilies = ["AF_INET" "AF_INET6" "AF_UNIX"]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = ["@system-service" "~@privileged"]; + UMask = "0077"; + }; + + environment = { + BASE_URL = "https://flux.isabelroses.com"; + LISTEN_ADDR = "/run/miniflux/miniflux.sock"; + DATABASE_URL = "user=miniflux host=/run/postgresql dbname=miniflux"; + RUN_MIGRATIONS = "1"; + CREATE_ADMIN = "1"; + }; + }; + miniflux-dbsetup = { + description = "Miniflux database setup"; + requires = ["postgresql.service"]; + after = ["network.target" "postgresql.service"]; + script = '' + ${lib.getExe' config.services.postgresql.package "psql"} "miniflux" -c "CREATE EXTENSION IF NOT EXISTS hstore" + ''; + serviceConfig = { + Type = "oneshot"; + User = config.services.postgresql.superUser; + }; + }; + }; + users = { + groups.miniflux = { + gid = 377; + }; + users = { + miniflux = { + group = "miniflux"; + extraGroups = ["postgres"]; + isSystemUser = true; + uid = 377; + }; + ${config.services.nginx.user}.extraGroups = ["miniflux"]; + }; + }; + }; +} diff --git a/modules/common/types/server/services/monitoring/default.nix b/modules/common/types/server/services/monitoring/default.nix new file mode 100644 index 000000000..2d4770acc --- /dev/null +++ b/modules/common/types/server/services/monitoring/default.nix @@ -0,0 +1,6 @@ +_: { + imports = [ + ./grafana + ./prometheus + ]; +} diff --git a/modules/common/types/server/services/monitoring/grafana/default.nix b/modules/common/types/server/services/monitoring/grafana/default.nix new file mode 100644 index 000000000..ad0cbd8d3 --- /dev/null +++ b/modules/common/types/server/services/monitoring/grafana/default.nix @@ -0,0 +1,73 @@ +{ + config, + lib, + ... +}: let + inherit (lib) mkIf; + inherit (config.networking) domain; + + cfg = config.modules.services.monitoring.grafana; + + port = 3100; +in { + config = mkIf cfg.enable { + networking.firewall.allowedTCPPorts = [port]; + + services.grafana = { + enable = true; + settings = { + analytics = { + reporting_enabled = false; + check_for_updates = false; + }; + + server = { + http_port = port; + http_addr = "0.0.0.0"; + domain = "graph.${domain}"; + enforce_domain = true; + }; + + "auth.anonymous".enabled = false; + "auth.basic".enabled = false; + + users = { + allow_signup = false; + }; + + database = { + type = "postgres"; + host = "/run/postgresql"; + name = "grafana"; + user = "grafana"; + ssl_mode = "disable"; + }; + + smtp = let + mailer = "grafana@${domain}"; + in { + enabled = true; + + user = mailer; + password = "$__file{" + config.sops.secrets.mailserver-grafana-nohash.path + "}"; + + host = "mail.${domain}:465"; + from_address = mailer; + startTLS_policy = "MandatoryStartTLS"; + }; + }; + provision = { + datasources.settings = { + datasources = [ + { + name = "Prometheus"; + type = "prometheus"; + url = "http://localhost:9090"; + orgId = 1; + } + ]; + }; + }; + }; + }; +} diff --git a/modules/common/types/server/services/monitoring/prometheus/default.nix b/modules/common/types/server/services/monitoring/prometheus/default.nix new file mode 100644 index 000000000..a91b14978 --- /dev/null +++ b/modules/common/types/server/services/monitoring/prometheus/default.nix @@ -0,0 +1,69 @@ +{ + config, + lib, + ... +}: let + inherit (lib) mkIf; + + cfg = config.modules.services.monitoring.prometheus; +in { + config = mkIf cfg.enable { + services = { + # Prometheus exporter for Grafana + prometheus = { + enable = true; + port = 9100; + # enabled exporters + exporters = { + node = { + enable = true; + port = 9101; + enabledCollectors = [ + "logind" + "systemd" + ]; + disabledCollectors = [ + "textfile" + ]; + openFirewall = true; + }; + + redis = { + enable = true; + openFirewall = true; + port = 9002; + }; + + postgres = { + enable = true; + openFirewall = true; + port = 9003; + }; + }; + + scrapeConfigs = [ + { + job_name = "prometheus"; + scrape_interval = "30s"; + static_configs = [{targets = ["localhost:9090"];}]; + } + { + job_name = "node"; + scrape_interval = "30s"; + static_configs = [{targets = ["localhost:9100"];}]; + } + { + job_name = "redis_exporter"; + scrape_interval = "30s"; + static_configs = [{targets = ["localhost:9002"];}]; + } + { + job_name = "postgres"; + scrape_interval = "30s"; + static_configs = [{targets = ["localhost:9003"];}]; + } + ]; + }; + }; + }; +} diff --git a/modules/common/types/server/services/nextcloud/default.nix b/modules/common/types/server/services/nextcloud/default.nix new file mode 100644 index 000000000..6e601dd9c --- /dev/null +++ b/modules/common/types/server/services/nextcloud/default.nix @@ -0,0 +1,72 @@ +{ + config, + lib, + pkgs, + ... +}: +with lib; let + inherit (config.networking) domain; + nextcloud_domain = "cloud.${domain}"; + + cfg = config.modules.services; +in { + config = mkIf cfg.nextcloud.enable { + modules.services.database = { + redis.enable = true; + postgresql.enable = true; + }; + + services = { + nextcloud = { + enable = true; + package = pkgs.nextcloud27; + caching.redis = true; + extraOptions = { + redis = { + host = "/run/redis-default/redis.sock"; + dbindex = 0; + timeout = 1.5; + }; + }; + + hostName = nextcloud_domain; + home = "/opt/nextcloud"; + maxUploadSize = "4G"; + enableImagemagick = true; + + autoUpdateApps = { + enable = true; + startAt = "02:00"; + }; + + config = { + overwriteProtocol = "https"; + extraTrustedDomains = ["https://${toString nextcloud_domain}"]; + trustedProxies = ["https://${toString nextcloud_domain}"]; + adminuser = "isabel"; + adminpassFile = config.sops.secrets.nextcloud-passwd.path; + defaultPhoneRegion = "UK"; + + # database + dbtype = "pgsql"; + dbhost = "/run/postgresql"; + dbname = "nextcloud"; + }; + nginx.recommendedHttpHeaders = true; + https = true; + }; + }; + + systemd.services = { + phpfpm-nextcloud.aliases = ["nextcloud.service"]; + "nextcloud-setup" = { + requires = ["postgresql.service"]; + after = ["postgresql.service"]; + serviceConfig = { + Restart = "on-failure"; + RestartSec = "10s"; + }; + }; + }; + }; +} diff --git a/modules/common/types/server/services/nginx/default.nix b/modules/common/types/server/services/nginx/default.nix index 0fcf7acc6..0e8654978 100644 --- a/modules/common/types/server/services/nginx/default.nix +++ b/modules/common/types/server/services/nginx/default.nix @@ -2,27 +2,27 @@ lib, config, ... -}: -with lib; let - device = config.modules.device; - acceptedTypes = ["server" "hybrid"]; +}: let + cfg = config.modules.services; + inherit (lib) mkIf; + domain = "isabelroses.com"; in { - config = mkIf (builtins.elem device.type acceptedTypes) { - networking.domain = "isabelroses.com"; + config = { + networking.domain = domain; security = { acme = { acceptTerms = true; - defaults.email = "isabel@isabelroses.com"; + defaults.email = "isabel@${domain}"; }; }; - services.nginx = { + services.nginx = mkIf cfg.nginx.enable { enable = true; commonHttpConfig = '' real_ip_header CF-Connecting-IP; add_header 'Referrer-Policy' 'origin-when-cross-origin'; - add_header X-Frame-Options DENY; + add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options nosniff; ''; @@ -31,57 +31,86 @@ in { recommendedGzipSettings = true; recommendedProxySettings = true; - virtualHosts = let - template = { + virtualHosts = { + # website + other stuff + "${domain}" = mkIf cfg.isabelroses-web.enable { forceSSL = true; enableACME = true; + locations."/".proxyPass = "http://127.0.0.1:3000"; }; - in { - # website + other stuff - "isabelroses.com" = - mkIf (config.modules.services.isabelroses-web.enable) - template - // { - serverAliases = ["isabelroses.com"]; - root = "/home/isabel/dev/isabelroses.com-pub"; - }; + # vaultwawrden - "vault.isabelroses.com" = - mkIf (config.modules.services.vaultwarden.enable) - template - // { - locations."/" = { - proxyPass = "http://127.0.0.1:${toString config.services.vaultwarden.config.ROCKET_PORT}"; - extraConfig = "proxy_pass_header Authorization;"; - }; - }; - # gitea - "git.isabelroses.com" = - mkIf (config.modules.services.gitea.enable) - template - // { - locations."/".proxyPass = "http://127.0.0.1:${toString config.services.gitea.settings.server.HTTP_PORT}"; + "vault.${domain}" = mkIf cfg.vaultwarden.enable { + forceSSL = true; + enableACME = true; + locations."/" = { + proxyPass = "http://127.0.0.1:${toString config.services.vaultwarden.config.ROCKET_PORT}"; + extraConfig = "proxy_pass_header Authorization;"; }; + }; + + # forgejo + "git.${domain}" = mkIf cfg.forgejo.enable { + locations."/".proxyPass = "http://127.0.0.1:${toString config.services.forgejo.settings.server.HTTP_PORT}"; + forceSSL = true; + enableACME = true; + }; + + "cloud.${domain}" = { + forceSSL = true; + enableACME = true; + }; # mailserver - "mail.isabelroses.com" = mkIf (config.modules.services.mailserver.enable) template; + "mail.${domain}" = mkIf cfg.mailserver.enable { + forceSSL = true; + enableACME = true; + }; + "rspamd.${domain}" = mkIf (cfg.mailserver.enable && cfg.mailserver.rspamd-web.enable) { + forceSSL = true; + enableACME = true; + basicAuthFile = config.sops.secrets.rspamd-web.path; + locations."/".proxyPass = "http://unix:/run/rspamd/worker-controller.sock:/"; + }; + "webmail.${domain}" = mkIf cfg.mailserver.enable { + forceSSL = true; + enableACME = true; + }; - # webmail - "webmail.isabelroses.com" = mkIf (config.modules.services.mailserver.enable) template; + # searxng + "search.${domain}" = mkIf cfg.searxng.enable { + forceSSL = true; + enableACME = true; + locations."/".proxyPass = "http://127.0.0.1:8888"; + extraConfig = '' + access_log /dev/null; + error_log /dev/null; + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + ''; + }; - "search.isabelroses.com" = - mkIf (config.modules.services.searxng.enable) - template - // { - locations."/".proxyPass = "http://127.0.0.1:8888"; - extraConfig = '' - access_log /dev/null; - error_log /dev/null; - proxy_connect_timeout 60s; - proxy_send_timeout 60s; - proxy_read_timeout 60s; - ''; + "graph.${domain}" = mkIf cfg.monitoring.grafana.enable { + locations."/" = { + proxyPass = "http://${toString config.services.grafana.settings.server.http_addr}:${toString config.services.grafana.settings.server.http_port}/"; + proxyWebsockets = true; }; + addSSL = true; + enableACME = true; + }; + + "flux.${domain}" = mkIf cfg.miniflux.enable { + locations."/".proxyPass = "http://unix:${config.systemd.services.miniflux.environment.LISTEN_ADDR}"; + forceSSL = true; + enableACME = true; + }; + + "matrix.${domain}" = mkIf cfg.matrix.enable { + locations."/".proxyPass = "http://127.0.0.1:8008"; + forceSSL = true; + enableACME = true; + }; }; }; }; diff --git a/modules/common/types/server/services/photoprism/default.nix b/modules/common/types/server/services/photoprism/default.nix index 159f07fb9..389a587b4 100644 --- a/modules/common/types/server/services/photoprism/default.nix +++ b/modules/common/types/server/services/photoprism/default.nix @@ -3,13 +3,11 @@ config, lib, ... -}: -with lib; let - device = config.modules.device; +}: let + inherit (config.networking) domain; cfg = config.modules.services.photoprism; - acceptedTypes = ["server" "hybrid"]; in { - services = mkIf (builtins.elem device.type acceptedTypes && cfg.enable) { + services = lib.mkIf cfg.enable { photoprism = { enable = true; port = 2342; @@ -23,7 +21,7 @@ in { PHOTOPRISM_DATABASE_NAME = "photoprism"; PHOTOPRISM_DATABASE_SERVER = "/run/mysqld/mysqld.sock"; PHOTOPRISM_DATABASE_USER = "photoprism"; - PHOTOPRISM_SITE_URL = "https://photos.isabelroses.com"; + PHOTOPRISM_SITE_URL = "https://photos.${domain}"; PHOTOPRISM_SITE_TITLE = "My PhotoPrism"; }; }; diff --git a/modules/common/types/server/services/smb/default.nix b/modules/common/types/server/services/smb/default.nix index 6ee09caf8..1e495561f 100644 --- a/modules/common/types/server/services/smb/default.nix +++ b/modules/common/types/server/services/smb/default.nix @@ -4,11 +4,9 @@ ... }: let inherit (lib) mkIf; - device = config.modules.device; cfg = config.modules.services.smb; - acceptedTypes = ["server" "hybrid"]; in { - config = mkIf (builtins.elem device.type acceptedTypes && cfg.enable) { + config = mkIf cfg.enable { services = { # https://nixos.wiki/wiki/Samba # make shares visible for windows 10 clients diff --git a/modules/common/types/server/services/vaultwarden/default.nix b/modules/common/types/server/services/vaultwarden/default.nix index 50a750e56..d69ce9e67 100644 --- a/modules/common/types/server/services/vaultwarden/default.nix +++ b/modules/common/types/server/services/vaultwarden/default.nix @@ -3,17 +3,17 @@ lib, ... }: let - inherit (lib) mkIf; - + inherit (config.networking) domain; cfg = config.modules.services.vaultwarden; - device = config.modules.device; - acceptedTypes = ["server" "hybrid"]; in { - config = mkIf (builtins.elem device.type acceptedTypes && cfg.enable) { + config = lib.mkIf cfg.enable { # this forces the system to create backup folder - systemd.services.backup-vaultwarden.serviceConfig = { - User = "root"; - Group = "root"; + systemd.services = { + vaultwarden.after = ["sops-nix.service"]; + backup-vaultwarden.serviceConfig = { + User = "root"; + Group = "root"; + }; }; services.vaultwarden = { @@ -21,22 +21,22 @@ in { environmentFile = config.sops.secrets.vaultwarden-env.path; backupDir = "/srv/storage/vaultwarden/backup"; config = { - DOMAIN = "https://vault.isabelroses.com"; + DOMAIN = "https://vault.${domain}"; SIGNUPS_ALLOWED = false; ROCKET_ADDRESS = "127.0.0.1"; ROCKET_PORT = 8222; extendedLogging = true; - invitationsAllowed = false; + invitationsAllowed = true; useSyslog = true; logLevel = "warn"; showPasswordHint = false; signupsAllowed = false; - signupsDomainsWhitelist = "isabelroses.com"; + signupsDomainsWhitelist = "${domain}"; signupsVerify = true; smtpAuthMechanism = "Login"; - smtpFrom = "vaultwarden@isabelroses.com"; - smtpFromName = "isabelroses's Vaultwarden Service"; - smtpHost = "mail.isabelroses.com"; + smtpFrom = "vaultwarden@${domain}"; + smtpFromName = "Isabelroses's Vaultwarden Service"; + smtpHost = "mail.${domain}"; smtpPort = 465; smtpSecurity = "force_tls"; dataDir = "/srv/storage/vaultwarden"; diff --git a/modules/common/types/server/services/wakatime/config.nix b/modules/common/types/server/services/wakatime/config.nix new file mode 100644 index 000000000..c39105d8f --- /dev/null +++ b/modules/common/types/server/services/wakatime/config.nix @@ -0,0 +1,26 @@ +{ + config, + pkgs, + lib, + ... +}: let + inherit (config.networking) domain; +in { + services.wakapi = lib.mkIf config.modules.services.wakapi.enable { + enable = true; + package = pkgs.wakapi; + + domain = "wakapi.${domain}"; + port = 15912; + nginx.enable = true; + passwordSaltFile = config.sops.secrets.wakapi.path; + settings = { + app.avatar_url_template = "https://www.gravatar.com/avatar/{email_hash}.png"; + mail.enabled = false; + security = { + allow_signup = false; + disable_frontpage = true; + }; + }; + }; +} diff --git a/modules/common/types/server/services/wakatime/default.nix b/modules/common/types/server/services/wakatime/default.nix new file mode 100644 index 000000000..a88393988 --- /dev/null +++ b/modules/common/types/server/services/wakatime/default.nix @@ -0,0 +1,6 @@ +_: { + imports = [ + ./config.nix + ./module.nix + ]; +} diff --git a/modules/common/types/server/services/wakatime/module.nix b/modules/common/types/server/services/wakatime/module.nix new file mode 100644 index 000000000..af34224df --- /dev/null +++ b/modules/common/types/server/services/wakatime/module.nix @@ -0,0 +1,196 @@ +{ + config, + lib, + pkgs, + ... +}: let + # stolen from https://git.winston.sh/winston/deployment-flake/src/branch/main/modules/wakapi.nix + cfg = config.services.wakapi; + settingsFormat = pkgs.formats.yaml {}; + inherit (lib) types; + + settingsFile = settingsFormat.generate "wakapi-settings" cfg.settings; + + serviceConfig = { + systemd.services.wakapi = { + description = "Wakapi (self-hosted WakaTime-compatible backend)"; + wants = ["network-online.target"]; + after = ["network-online.target"]; + wantedBy = ["multi-user.target"]; + + script = '' + exec ${lib.getExe pkgs.wakapi} -config ${settingsFile} + ''; + + serviceConfig = { + Environment = lib.mkIf (cfg.passwordSalt != null) "WAKAPI_PASSWORD_SALT=${cfg.passwordSalt}"; + EnvironmentFile = lib.mkIf (cfg.passwordSaltFile != null) cfg.passwordSaltFile; + + User = "wakapi"; + Group = "wakapi"; + + DynamicUser = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "strict"; + RestrictAddressFamilies = ["AF_INET" "AF_INET6" "AF_UNIX"]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + }; + }; + + services.wakapi.settings = { + env = lib.mkDefault "production"; + inherit (cfg) db; + server = { + inherit (cfg) port; + }; + }; + + assertions = [ + { + assertion = cfg.passwordSalt != null || cfg.passwordSaltFile != null; + message = "Either `passwordSalt` or `passwordSaltFile` must be set."; + } + ]; + }; + + databaseConfig = { + services.postgresql = { + enable = true; + ensureDatabases = lib.singleton cfg.settings.db.name; + ensureUsers = lib.singleton { + name = cfg.settings.db.user; + ensurePermissions = { + "DATABASE ${cfg.settings.db.name}" = "ALL PRIVILEGES"; + }; + }; + authentication = '' + host ${cfg.settings.db.name} ${cfg.settings.db.user} 127.0.0.1/32 trust + ''; + }; + + services.wakapi.settings.db = { + dialect = "postgres"; + }; + + systemd.services.wakapi = { + requires = ["postgresql.service"]; + after = ["postgresql.service"]; + }; + }; + + nginxConfig = lib.mkIf cfg.nginx.enable { + services.nginx = { + enable = true; + virtualHosts.${cfg.domain} = { + locations."/".proxyPass = "http://127.0.0.1:${toString cfg.port}"; + + enableACME = lib.mkDefault true; + forceSSL = lib.mkDefault true; + }; + }; + + services.wakapi.settings.server = { + public_url = lib.mkDefault cfg.domain; + }; + }; +in { + options.services.wakapi = { + enable = lib.mkEnableOption "Wakapi"; + package = lib.mkPackageOption pkgs "wakapi" {}; + + port = lib.mkOption { + type = types.int; + default = 3000; + description = '' + The port to serve Wakapi on. + This is used to configure nginx. + ''; + }; + domain = lib.mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The FQDN of the domain to serve Wakapi on. + This is used to configure nginx. + ''; + }; + + db = { + host = lib.mkOption { + type = types.str; + default = "127.0.0.1"; + description = '' + The database host to use for Wakapi. + ''; + }; + port = lib.mkOption { + type = types.int; + default = 5432; + description = '' + The port to use for the database. + ''; + }; + name = lib.mkOption { + type = types.str; + default = "wakapi"; + description = '' + The database name to use for Wakapi. + ''; + }; + user = lib.mkOption { + type = types.str; + default = "wakapi"; + description = '' + The database user to use for Wakapi. + ''; + }; + password = lib.mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The database password to use for Wakapi. + ''; + }; + }; + + nginx.enable = lib.mkEnableOption "Wakapi Nginx"; + + passwordSalt = lib.mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The password salt to use for Wakapi. + ''; + }; + passwordSaltFile = lib.mkOption { + type = types.nullOr types.path; + default = null; + description = '' + The path to a file containing the password salt to use for Wakapi. + ''; + }; + + settings = lib.mkOption { + inherit (settingsFormat) type; + default = {}; + description = lib.mkDoc '' + Settings for Wakapi. + + See [config.default.yml](https://github.com/muety/wakapi/blob/master/config.default.yml) for a list of all possible options. + ''; + }; + }; + + config = lib.mkIf cfg.enable (lib.mkMerge [ + databaseConfig + nginxConfig + serviceConfig + ]); +} diff --git a/modules/common/types/server/system/default.nix b/modules/common/types/server/system/default.nix index e46be8f94..44bc7c177 100644 --- a/modules/common/types/server/system/default.nix +++ b/modules/common/types/server/system/default.nix @@ -1,5 +1,8 @@ _: { imports = [ - ./users.nix + ./users + + ./enviroment.nix + ./systemd.nix ]; } diff --git a/modules/common/types/server/system/enviroment.nix b/modules/common/types/server/system/enviroment.nix new file mode 100644 index 000000000..81ee97390 --- /dev/null +++ b/modules/common/types/server/system/enviroment.nix @@ -0,0 +1,10 @@ +_: { + environment = { + # normally we wouldn't need any Xlibs on a headless server but for whatever reason + # this affects whether or not some programs can build - such as pipewire + # noXlibs = true; + + # print the URL instead on servers + variables.BROWSER = "echo"; + }; +} diff --git a/modules/common/types/server/system/systemd.nix b/modules/common/types/server/system/systemd.nix new file mode 100644 index 000000000..e222280a3 --- /dev/null +++ b/modules/common/types/server/system/systemd.nix @@ -0,0 +1,29 @@ +_: { + # https://github.com/numtide/srvos/blob/main/nixos/server/default.nix + systemd = { + # given that our systems are headless, emergency mode is useless. + # we prefer the system to attempt to continue booting so + # that we can hopefully still access it remotely. + enableEmergencyMode = false; + + # For more detail, see: + # https://0pointer.de/blog/projects/watchdog.html + watchdog = { + # systemd will send a signal to the hardware watchdog at half + # the interval defined here, so every 10s. + # If the hardware watchdog does not get a signal for 20s, + # it will forcefully reboot the system. + runtimeTime = "20s"; + # Forcefully reboot if the final stage of the reboot + # hangs without progress for more than 30s. + # For more info, see: + # https://utcc.utoronto.ca/~cks/space/blog/linux/SystemdShutdownWatchdog + rebootTime = "30s"; + }; + + sleep.extraConfig = '' + AllowSuspend=no + AllowHibernation=no + ''; + }; +} diff --git a/modules/common/types/server/system/users.nix b/modules/common/types/server/system/users.nix deleted file mode 100644 index b3d3252b8..000000000 --- a/modules/common/types/server/system/users.nix +++ /dev/null @@ -1,15 +0,0 @@ -{ - lib, - config, - ... -}: let - inherit (lib) mkIf; -in { - users.users.git = mkIf config.modules.services.gitea.enable { - isSystemUser = true; - extraGroups = []; - useDefaultShell = true; - home = "/var/lib/gitea"; - group = "gitea"; - }; -} diff --git a/modules/common/types/server/system/users/default.nix b/modules/common/types/server/system/users/default.nix new file mode 100644 index 000000000..07a11ac68 --- /dev/null +++ b/modules/common/types/server/system/users/default.nix @@ -0,0 +1,6 @@ +_: { + imports = [ + ./git.nix + ./wakapi.nix + ]; +} diff --git a/modules/common/types/server/system/users/git.nix b/modules/common/types/server/system/users/git.nix new file mode 100644 index 000000000..aff8862de --- /dev/null +++ b/modules/common/types/server/system/users/git.nix @@ -0,0 +1,18 @@ +{ + lib, + config, + ... +}: let + inherit (lib) mkIf; + cfg = config.modules.services.forgejo; +in { + users = mkIf cfg.enable { + groups.git = {}; + + users.git = { + isSystemUser = true; + createHome = false; + group = "git"; + }; + }; +} diff --git a/modules/common/types/server/system/users/wakapi.nix b/modules/common/types/server/system/users/wakapi.nix new file mode 100644 index 000000000..73cc3c89a --- /dev/null +++ b/modules/common/types/server/system/users/wakapi.nix @@ -0,0 +1,18 @@ +{ + lib, + config, + ... +}: let + inherit (lib) mkIf; + cfg = config.modules.services.wakapi; +in { + users = mkIf cfg.enable { + groups.wakapi = {}; + + users.wakapi = { + isSystemUser = true; + createHome = false; + group = "wakapi"; + }; + }; +} diff --git a/modules/common/types/workstation/default.nix b/modules/common/types/workstation/default.nix index 96d570a2f..21f2d8c6a 100644 --- a/modules/common/types/workstation/default.nix +++ b/modules/common/types/workstation/default.nix @@ -1,6 +1,5 @@ _: { imports = [ - ./gaming ./programs ./services ./system diff --git a/modules/common/types/workstation/gaming/default.nix b/modules/common/types/workstation/gaming/default.nix deleted file mode 100644 index 53152e1db..000000000 --- a/modules/common/types/workstation/gaming/default.nix +++ /dev/null @@ -1,63 +0,0 @@ -{ - config, - lib, - pkgs, - inputs, - ... -}: -with lib; let - programs = makeBinPath (with pkgs; [ - inputs.hyprland.packages.${pkgs.system}.default - coreutils - power-profiles-daemon - systemd - ]); - - startscript = pkgs.writeShellScript "gamemode-start" '' - export PATH=$PATH:${programs} - export HYPRLAND_INSTANCE_SIGNATURE=$(ls -w1 /tmp/hypr | tail -1) - hyprctl --batch 'keyword decoration:blur 0 ; keyword animations:enabled 0 ; keyword misc:vfr 0' - ${pkgs.libnotify}/bin/notify-send -a 'Gamemode' 'Optimizations activated' - powerprofilesctl set performance - ''; - - endscript = pkgs.writeShellScript "gamemode-end" '' - export PATH=$PATH:${programs} - export HYPRLAND_INSTANCE_SIGNATURE=$(ls -w1 /tmp/hypr | tail -1) - hyprctl --batch 'keyword decoration:blur 1 ; keyword animations:enabled 1 ; keyword misc:vfr 1' - ${pkgs.libnotify}/bin/notify-send -a 'Gamemode' 'Optimizations deactivated' - powerprofilesctl set power-saver - ''; - - cfg = config.modules.programs; -in { - config = mkIf cfg.gaming.enable { - programs = { - gamemode = { - enable = true; - enableRenice = true; - settings = { - general = { - softrealtime = "auto"; - renice = 15; - }; - custom = { - start = startscript.outPath; - end = endscript.outPath; - }; - }; - }; - - steam = { - enable = true; - # Open ports in the firewall for Steam Remote Play - remotePlay.openFirewall = true; - # Open ports in the firewall for Source Dedicated Server - dedicatedServer.openFirewall = true; - # Compatibility tools to install - # this option is provided by modules/shared/nixos/steam - withProtonGE = true; - }; - }; - }; -} diff --git a/modules/common/types/workstation/programs/ccache/default.nix b/modules/common/types/workstation/programs/ccache/default.nix new file mode 100644 index 000000000..90c27ac89 --- /dev/null +++ b/modules/common/types/workstation/programs/ccache/default.nix @@ -0,0 +1,49 @@ +{ + config, + lib, + ... +}: { + programs.ccache = { + enable = true; + cacheDir = "/var/cache/sccache"; + }; + + systemd.tmpfiles.rules = [ + "z ${config.programs.ccache.cacheDir} 770 root nixbld - -" + ]; + + nix.settings.extra-sandbox-paths = [ + config.programs.ccache.cacheDir + "/var/cache/sccache" + ]; + + nixpkgs.overlays = lib.mkIf (config.programs.ccache.enable && config.programs.ccache.packageNames == []) [ + (_: super: { + ccacheWrapper = super.ccacheWrapper.override { + extraConfig = '' + export CCACHE_COMPRESS=1 + export CCACHE_DIR="${config.programs.ccache.cacheDir}" + export CCACHE_UMASK=007 + export CCACHE_SLOPPINESS=include_file_mtime,time_macros + export CCACHE_NODIRECT=1 + if [ ! -d "$CCACHE_DIR" ]; then + echo "=====" + echo "Directory '$CCACHE_DIR' does not exist" + echo "Please create it with:" + echo " sudo mkdir -m0770 '$CCACHE_DIR'" + echo " sudo chown root:nixbld '$CCACHE_DIR'" + echo "=====" + exit 1 + fi + if [ ! -w "$CCACHE_DIR" ]; then + echo "=====" + echo "Directory '$CCACHE_DIR' is not accessible for user $(whoami)" + echo "Please verify its access permissions" + echo "=====" + exit 1 + fi + ''; + }; + }) + ]; +} diff --git a/modules/common/types/workstation/programs/cli.nix b/modules/common/types/workstation/programs/cli.nix index 94b19894b..b078abfd2 100644 --- a/modules/common/types/workstation/programs/cli.nix +++ b/modules/common/types/workstation/programs/cli.nix @@ -21,8 +21,7 @@ in { }; programs = { - # home-manager is quirky as ever, and wants this to be set in system config - # instead of just home-manager + # home-manager is so strange and needs these declared muliple times fish.enable = true; # type "fuck" to fix the last command that made you go "fuck" @@ -30,10 +29,18 @@ in { # help manage android devices via command line adb.enable = true; + + # direnv is cool + direnv = { + enable = true; + silent = true; + + # faster, persistent + nix-direnv.enable = true; + }; }; - # determine which version of wine to be used - # then add it to systemPackages + # determine which version of wine to use environment.systemPackages = with pkgs; let winePackage = if (env.isWayland) diff --git a/modules/common/types/workstation/programs/default.nix b/modules/common/types/workstation/programs/default.nix index f1d088373..b48a0f892 100644 --- a/modules/common/types/workstation/programs/default.nix +++ b/modules/common/types/workstation/programs/default.nix @@ -1,5 +1,6 @@ _: { imports = [ + ./ccache ./flatpak ./xdg-ninja diff --git a/modules/common/types/workstation/programs/flatpak/default.nix b/modules/common/types/workstation/programs/flatpak/default.nix index 9cc573d9b..9d4e25014 100644 --- a/modules/common/types/workstation/programs/flatpak/default.nix +++ b/modules/common/types/workstation/programs/flatpak/default.nix @@ -1,5 +1,5 @@ _: { - # enable flatpak, as well as xdgp to communicate with the host filesystems + # enable flatpak services.flatpak.enable = false; environment.sessionVariables.XDG_DATA_DIRS = ["/var/lib/flatpak/exports/share"]; diff --git a/modules/common/types/workstation/programs/gui.nix b/modules/common/types/workstation/programs/gui.nix index d4bddeb59..025462eae 100644 --- a/modules/common/types/workstation/programs/gui.nix +++ b/modules/common/types/workstation/programs/gui.nix @@ -1,4 +1,8 @@ -{pkgs, ...}: { +{ + pkgs, + config, + ... +}: { environment = { systemPackages = with pkgs; [ # packages necessery for thunar thumbnails @@ -20,13 +24,12 @@ ]; }; - # registry for linux, thanks to gnome dconf.enable = true; # gnome's keyring manager seahorse.enable = true; - # networkmanager tray uility - nm-applet.enable = true; + # networkmanager tray uility, pretty useful actually + nm-applet.enable = config.modules.programs.defaults.bar == "waybar"; }; } diff --git a/modules/common/types/workstation/services/default.nix b/modules/common/types/workstation/services/default.nix index a368e060b..65c768cb7 100644 --- a/modules/common/types/workstation/services/default.nix +++ b/modules/common/types/workstation/services/default.nix @@ -6,5 +6,7 @@ _: { ./misc.nix ./printing.nix ./runners.nix + ./tor.nix + ./xserver.nix ]; } diff --git a/modules/common/types/workstation/services/gnome.nix b/modules/common/types/workstation/services/gnome.nix index 3bf03a7ac..859eb4163 100644 --- a/modules/common/types/workstation/services/gnome.nix +++ b/modules/common/types/workstation/services/gnome.nix @@ -3,12 +3,11 @@ pkgs, lib, ... -}: -with lib; let - device = config.modules.device; +}: let + inherit (config.modules) device; acceptedTypes = ["desktop" "laptop" "hybrid" "lite"]; in { - config = mkIf (builtins.elem device.type acceptedTypes) { + config = lib.mkIf (builtins.elem device.type acceptedTypes) { services = { udev.packages = with pkgs; [ gnome.gnome-settings-daemon @@ -16,13 +15,10 @@ in { gnome = { evolution-data-server.enable = true; - # optional to use google/nextcloud calendar gnome-online-accounts.enable = true; - # optional to use google/nextcloud calendar gnome-keyring.enable = true; - # hard fails rebuilds for whatever reason, PLEASE stay disabled - # spoiler: it didn't - building gnome-control-center still breaks rebuilds - # entirely because of gnome-remote-desktop + + # stupid thing i want disabled gnome-remote-desktop.enable = lib.mkForce false; }; }; diff --git a/modules/common/types/workstation/services/location.nix b/modules/common/types/workstation/services/location.nix index 09c11dc41..4470c8ef9 100644 --- a/modules/common/types/workstation/services/location.nix +++ b/modules/common/types/workstation/services/location.nix @@ -2,12 +2,11 @@ config, lib, ... -}: -with lib; let - device = config.modules.device; +}: let + inherit (config.modules) device; acceptedTypes = ["desktop" "laptop" "lite"]; in { - config = mkIf (builtins.elem device.type acceptedTypes) { + config = lib.mkIf (builtins.elem device.type acceptedTypes) { location.provider = "geoclue2"; services.geoclue2 = { diff --git a/modules/common/types/workstation/services/login.nix b/modules/common/types/workstation/services/login.nix index 73bd6366f..caba0fed3 100644 --- a/modules/common/types/workstation/services/login.nix +++ b/modules/common/types/workstation/services/login.nix @@ -1,43 +1,87 @@ { config, + lib, pkgs, ... -}: { +}: let + inherit (config.modules) system usrEnv programs; + inherit (lib) mkIf; + sessionData = config.services.xserver.displayManager.sessionData.desktops; + sessionPath = lib.concatStringsSep ":" [ + "${sessionData}/share/xsessions" + "${sessionData}/share/wayland-sessions" + ]; +in { config = { # unlock GPG keyring on login - security.pam.services.login = { - enableGnomeKeyring = true; - gnupg = { - enable = true; - noAutostart = true; - storeOnly = true; + security.pam.services = { + login = { + enableGnomeKeyring = true; + gnupg = { + enable = true; + noAutostart = true; + storeOnly = true; + }; }; - }; - systemd.services = { - # login manager - seatd = { - enable = true; - description = "Seat management daemon"; - script = "${pkgs.seatd}/bin/seatd -g wheel"; - serviceConfig = { - Type = "simple"; - Restart = "always"; - RestartSec = "1"; - }; - wantedBy = ["multi-user.target"]; + greetd = mkIf (programs.defaults.loginManager == "greetd") { + gnupg.enable = true; + enableGnomeKeyring = true; }; }; services = { + xserver.displayManager.session = [ + { + manage = "desktop"; + name = "hyprland"; + start = '' + Hyprland + ''; + } + ]; + + greetd = { + enable = programs.defaults.loginManager == "greetd"; + vt = 2; + restart = !system.autoLogin; + settings = { + # pick up desktop variant (i.e Hyprland) and username from usrEnv + # this option is usually defined in host//system.nix + initial_session = mkIf system.autoLogin { + command = "${usrEnv.desktop}"; + user = "${system.mainUser}"; + }; + + default_session = + if (!system.autoLogin) + then { + command = lib.concatStringsSep " " [ + (lib.getExe pkgs.greetd.tuigreet) + "--time" + "--remember" + "--remember-user-session" + "--asterisks" + "--sessions '${sessionPath}'" + ]; + user = "greeter"; + } + else { + command = "${usrEnv.desktop}"; + user = "${system.mainUser}"; + }; + }; + }; + gnome = { + glib-networking.enable = true; gnome-keyring.enable = true; }; logind = { lidSwitch = "ignore"; - lidSwitchDocked = "ignore"; - lidSwitchExternalPower = "ignore"; + lidSwitchDocked = "lock"; + lidSwitchExternalPower = "lock"; powerKey = "suspend-then-hibernate"; }; }; diff --git a/modules/common/types/workstation/services/misc.nix b/modules/common/types/workstation/services/misc.nix index 2824541d6..5a390d5b4 100644 --- a/modules/common/types/workstation/services/misc.nix +++ b/modules/common/types/workstation/services/misc.nix @@ -3,9 +3,9 @@ pkgs, lib, ... -}: -with lib; let - device = config.modules.device; +}: let + inherit (lib) mkIf; + inherit (config.modules) device; acceptedTypes = ["desktop" "laptop" "hybrid" "lite"]; in { config = mkIf (builtins.elem device.type acceptedTypes) { @@ -16,6 +16,9 @@ in { # thumbnail support on thunar tumbler.enable = true; + # storage daemon required for udiskie auto-mount + udisks2.enable = true; + dbus = { packages = with pkgs; [dconf gcr udisks2]; enable = true; @@ -35,7 +38,7 @@ in { in { inherit extraConfig; user = {inherit extraConfig;}; - services."getty@tty1".enable = false; + services."getty@tty1".enable = false; # if you want to use tty1 enable services."autovt@tty1".enable = false; services."getty@tty7".enable = false; services."autovt@tty7".enable = false; diff --git a/modules/common/types/workstation/services/printing.nix b/modules/common/types/workstation/services/printing.nix index 667bef32d..1b06e3430 100644 --- a/modules/common/types/workstation/services/printing.nix +++ b/modules/common/types/workstation/services/printing.nix @@ -3,12 +3,11 @@ lib, pkgs, ... -}: -with lib; let +}: let sys = config.modules.system; in { - config = mkIf (sys.printing.enable) { - # enable cups and add some drivers for common printers + config = lib.mkIf sys.printing.enable { + # enable cups and some drivers for common printers services = { printing = { enable = true; @@ -21,9 +20,7 @@ in { # required for network discovery of printers avahi = { enable = true; - # resolve .local domains for printers nssmdns = true; - # pass avahi port(s) to the firewall openFirewall = true; }; }; diff --git a/modules/common/types/workstation/services/runners.nix b/modules/common/types/workstation/services/runners.nix index 6b2cc1c2f..77f51554f 100644 --- a/modules/common/types/workstation/services/runners.nix +++ b/modules/common/types/workstation/services/runners.nix @@ -6,7 +6,7 @@ ... }: let inherit (lib) mkIf; - device = config.modules.device; + inherit (config.modules) device; in { imports = [inputs.nix-ld.nixosModules.nix-ld]; @@ -22,16 +22,27 @@ in { # run unpatched linux binaries with nix-ld programs.nix-ld.dev = { - enable = false; + enable = true; libraries = with pkgs; [ + stdenv.cc.cc openssl curl glib - gjs util-linux glibc + icu + libunwind + libuuid + zlib + libsecret + # graphical + freetype + libglvnd libnotify + SDL2 + vulkan-loader gdk-pixbuf + xorg.libX11 ]; }; }; diff --git a/modules/common/types/workstation/services/tor.nix b/modules/common/types/workstation/services/tor.nix new file mode 100644 index 000000000..3489baf88 --- /dev/null +++ b/modules/common/types/workstation/services/tor.nix @@ -0,0 +1,12 @@ +{ + lib, + config, + ... +}: { + services.tor = lib.mkIf config.modules.system.security.tor.enable { + enable = true; + client.enable = true; + client.dns.enable = true; + torsocks.enable = true; + }; +} diff --git a/modules/common/types/workstation/services/xserver.nix b/modules/common/types/workstation/services/xserver.nix new file mode 100644 index 000000000..53bdbee64 --- /dev/null +++ b/modules/common/types/workstation/services/xserver.nix @@ -0,0 +1,26 @@ +{ + pkgs, + config, + lib, + ... +}: let + inherit (lib) mkIf; + inherit (config.modules) device programs system; + acceptedTypes = ["desktop" "laptop" "hybrid" "lite"]; +in { + config = mkIf (system.video.enable && builtins.elem device.type acceptedTypes) { + services.xserver = { + enable = true; + displayManager.gdm.enable = programs.defaults.loginManager == "gdm"; + displayManager.lightdm.enable = programs.defaults.loginManager == "lightdm"; + displayManager.sddm = { + enable = programs.defaults.loginManager == "sddm"; + wayland.enable = true; + theme = "${import ../../../../../parts/pkgs/sddm.nix {inherit pkgs lib;}}"; + settings = { + General = {InputMethod = "";}; + }; + }; + }; + }; +} diff --git a/modules/common/types/workstation/system/default.nix b/modules/common/types/workstation/system/default.nix index 8175026ef..9b36398d8 100644 --- a/modules/common/types/workstation/system/default.nix +++ b/modules/common/types/workstation/system/default.nix @@ -1,7 +1,6 @@ _: { imports = [ ./fonts.nix - ./environment.nix ./misc.nix ]; } diff --git a/modules/common/types/workstation/system/environment.nix b/modules/common/types/workstation/system/environment.nix deleted file mode 100644 index e63a20111..000000000 --- a/modules/common/types/workstation/system/environment.nix +++ /dev/null @@ -1,17 +0,0 @@ -{ - config, - lib, - ... -}: -with lib; let - device = config.modules.device; - progs = config.modules.programs.default; - acceptedTypes = ["desktop" "laptop" "hybrid" "lite"]; -in { - config = mkIf (builtins.elem device.type acceptedTypes) { - environment.variables = { - # open links with the default browser - BROWSER = progs.browser; - }; - }; -} diff --git a/modules/common/types/workstation/system/misc.nix b/modules/common/types/workstation/system/misc.nix index d383e7b47..d24d6d0be 100644 --- a/modules/common/types/workstation/system/misc.nix +++ b/modules/common/types/workstation/system/misc.nix @@ -2,17 +2,11 @@ config, lib, ... -}: -with lib; let - device = config.modules.device; +}: let + inherit (config.modules) device; acceptedTypes = ["desktop" "laptop" "hybrid" "lite"]; in { - config = mkIf (builtins.elem device.type acceptedTypes) { - qt = { - enable = true; - platformTheme = "qt5ct"; - }; - + config = lib.mkIf (builtins.elem device.type acceptedTypes) { # enable polkit for privilege escalation security.polkit.enable = true; diff --git a/modules/extra/shared/home-manager/gtklock/default.nix b/modules/extra/shared/home-manager/gtklock/default.nix index f95a15509..40635d296 100644 --- a/modules/extra/shared/home-manager/gtklock/default.nix +++ b/modules/extra/shared/home-manager/gtklock/default.nix @@ -1,3 +1,4 @@ +# stolen from https://github.com/NotAShelf/nyx/blob/refactor/modules/extra/shared/home-manager/gtklock/default.nix { config, lib, diff --git a/modules/extra/shared/nixos/default.nix b/modules/extra/shared/nixos/default.nix index 00e7ed19c..87a13d7f8 100644 --- a/modules/extra/shared/nixos/default.nix +++ b/modules/extra/shared/nixos/default.nix @@ -1,5 +1,2 @@ _: { - imports = [ - ./steam - ]; } diff --git a/modules/extra/shared/nixos/steam/default.nix b/modules/extra/shared/nixos/steam/default.nix deleted file mode 100644 index 5ec5c4214..000000000 --- a/modules/extra/shared/nixos/steam/default.nix +++ /dev/null @@ -1,55 +0,0 @@ -{ - config, - lib, - inputs', - ... -}: -with lib; let - cfg = config.programs.steam; -in { - options.programs.steam = { - withProtonGE = mkOption { - type = types.bool; - default = false; - description = mdDoc '' - Whether or not proton-ge from nix-gaming should be appended to `extraCompatPackages`. - ''; - }; - - extraCompatPackages = mkOption { - type = with types; listOf package; - default = []; - defaultText = literalExpression "[]"; - example = literalExpression '' - with pkgs; [ - luxtorpeda - proton-ge - ] - ''; - description = mdDoc '' - Extra packages to be used as compatibility tools for Steam on Linux. Packages will be included - in the `STEAM_EXTRA_COMPAT_TOOLS_PATHS` environmental variable. For more information see - . - ''; - }; - }; - - config = let - CompatPackages = - if cfg.withProtonGE == true - then cfg.extraCompatPackages ++ [inputs'.nix-gaming.packages.proton-ge] - else cfg.extraCompatPackages; - in - mkIf cfg.enable { - # Steam hardware (just in case) - hardware.steam-hardware.enable = true; - - # Append the extra compatibility packages to whatever else the env variable was populated with. - # For more information see https://github.com/ValveSoftware/steam-for-linux/issues/6310. - environment.sessionVariables = mkIf (CompatPackages != []) { - STEAM_EXTRA_COMPAT_TOOLS_PATHS = [ - (makeBinPath CompatPackages) - ]; - }; - }; -} diff --git a/modules/common/options/default.nix b/modules/options/default.nix similarity index 86% rename from modules/common/options/default.nix rename to modules/options/default.nix index ea8cb5541..0502025eb 100644 --- a/modules/common/options/default.nix +++ b/modules/options/default.nix @@ -2,6 +2,7 @@ _: { imports = [ ./device ./programs + ./services ./system ./themes ./usrEnv diff --git a/modules/options/device/capabilities.nix b/modules/options/device/capabilities.nix new file mode 100644 index 000000000..5ad686be1 --- /dev/null +++ b/modules/options/device/capabilities.nix @@ -0,0 +1,22 @@ +{lib, ...}: +with lib; { + options.modules.device = { + hasBluetooth = mkOption { + type = types.bool; + default = true; + description = "Whether or not the system has bluetooth support"; + }; + + hasSound = mkOption { + type = types.bool; + default = true; + description = "Whether the system has sound support (usually true except for servers)"; + }; + + hasTPM = mkOption { + type = types.bool; + default = false; + description = "Whether the system has tpm support"; + }; + }; +} diff --git a/modules/options/device/default.nix b/modules/options/device/default.nix new file mode 100644 index 000000000..5a9dd8b75 --- /dev/null +++ b/modules/options/device/default.nix @@ -0,0 +1,6 @@ +_: { + imports = [ + ./capabilities.nix + ./hardware.nix + ]; +} diff --git a/modules/options/device/hardware.nix b/modules/options/device/hardware.nix new file mode 100644 index 000000000..6466a7f40 --- /dev/null +++ b/modules/options/device/hardware.nix @@ -0,0 +1,36 @@ +{lib, ...}: let + inherit (lib) mdDoc mkOption types; +in { + options.modules.device = { + type = mkOption { + type = types.enum ["laptop" "desktop" "server" "hybrid" "lite" "vm"]; + default = ""; + }; + + cpu = mkOption { + type = types.enum ["pi" "intel" "vm-intel" "amd" "vm-amd" null]; + default = null; + }; + + gpu = mkOption { + type = types.enum ["amd" "intel" "nvidia" null]; + default = null; + description = "The manifacturer/type of the primary system gpu"; + }; + + monitors = mkOption { + type = with types; listOf str; + default = []; + description = mdDoc '' + this does not affect any drivers and such, it is only necessary for + declaring things like monitors in window manager configurations + you can avoid declaring this, but I'd rather if you did declare + ''; + }; + + keyboard = mkOption { + type = types.enum ["us" "gb"]; + default = "gb"; + }; + }; +} diff --git a/modules/options/programs/default.nix b/modules/options/programs/default.nix new file mode 100644 index 000000000..dd07e2bde --- /dev/null +++ b/modules/options/programs/default.nix @@ -0,0 +1,27 @@ +{lib, ...}: let + inherit (lib) mkEnableOption mkOption types; +in { + imports = [ + ./defaults + ./gaming.nix + ]; + + options.modules.programs = { + cli = { + enable = mkEnableOption "Enable CLI programs"; + modernShell.enable = mkEnableOption "Enable modern shell programs"; + }; + tui.enable = mkEnableOption "Enable TUI programs"; + gui.enable = mkEnableOption "Enable GUI programs"; + + zathura.enable = mkEnableOption "Enable zathura PDF reader"; + + git = { + signingKey = mkOption { + type = types.str; + default = ""; + description = "The default gpg key used for signing commits"; + }; + }; + }; +} diff --git a/modules/options/programs/defaults/default.nix b/modules/options/programs/defaults/default.nix new file mode 100644 index 000000000..b58bacb22 --- /dev/null +++ b/modules/options/programs/defaults/default.nix @@ -0,0 +1,59 @@ +{lib, ...}: let + inherit (lib) mkOption types mdDoc; +in { + options.modules.programs.defaults = { + terminal = mkOption { + type = types.enum ["alacritty" "kitty" "wezterm" "foot"]; + default = "kitty"; + }; + + fileManager = mkOption { + type = types.enum ["thunar" "dolphin" "nemo"]; + default = "thunar"; + }; + + browser = mkOption { + type = types.enum ["schizofox" "chromium"]; + default = "schizofox"; + }; + + editor = mkOption { + type = types.enum ["nvim" "codium"]; + default = "nvim"; + }; + + launcher = mkOption { + type = types.enum ["rofi" "wofi"]; + default = "rofi"; + }; + + bar = mkOption { + type = types.enum ["eww" "waybar" "ags"]; + default = "eww"; + }; + + screenLocker = mkOption { + type = with types; nullOr (enum ["swaylock" "gtklock"]); + default = "gtklock"; + description = mdDoc '' + The lockscreen module to be loaded by home-manager. + ''; + }; + + loginManager = mkOption { + type = with types; nullOr (enum ["greetd" "gdm" "lightdm" "sddm"]); + default = "greetd"; + description = mdDoc '' + The login manager to be used by the system. + ''; + }; + + noiseSupressor = mkOption { + type = with types; nullOr (enum ["rnnoise" "noisetorch"]); + default = "rnnoise"; + description = lib.mdDoc '' + The noise supressor to be used for desktop systems with sound enabled. + ''; + }; + }; +} diff --git a/modules/options/programs/gaming.nix b/modules/options/programs/gaming.nix new file mode 100644 index 000000000..0f6dc0de3 --- /dev/null +++ b/modules/options/programs/gaming.nix @@ -0,0 +1,19 @@ +{ + config, + lib, + ... +}: let + inherit (lib) mkEnableOption; +in { + options.modules.programs.gaming = let + cfg = config.modules.programs.gaming; + in { + enable = mkEnableOption "Enable packages required for the device to be gaming-ready"; + emulation.enable = mkEnableOption "Enable programs required to emulate other platforms"; + minecraft.enable = mkEnableOption "Enable minecraft"; + + gamescope.enable = mkEnableOption "Gamescope compositing manager" // {default = cfg.enable;}; + steam.enable = mkEnableOption "Enable Steam" // {default = cfg.enable;}; + mangohud.enable = mkEnableOption "Enable MangoHud" // {default = cfg.enable;}; + }; +} diff --git a/modules/options/services/default.nix b/modules/options/services/default.nix new file mode 100644 index 000000000..679292278 --- /dev/null +++ b/modules/options/services/default.nix @@ -0,0 +1,60 @@ +{ + config, + lib, + ... +}: let + inherit (lib) mkEnableOption; + cfg = config.modules.services; + + # mkEnableOption is the same as mkEnableOption but with the default value being equal to cfg.monitoring.enable + mkEnableOption' = desc: mkEnableOption "${desc}" // {default = cfg.monitoring.enable;}; +in { + options.modules.services = { + nextcloud.enable = mkEnableOption "Nextcloud service"; + matrix.enable = mkEnableOption "Enable matrix server"; + miniflux.enable = mkEnableOption "Enable miniflux rss news aggreator service"; + forgejo.enable = mkEnableOption "Enable the forgejo service"; + cyberchef.enable = mkEnableOption "Enable the cyberchef website"; + vaultwarden.enable = mkEnableOption "Enable the vaultwarden service"; + photoprism.enable = mkEnableOption "Enable the photoprism service"; + vscode-server.enable = mkEnableOption "Enables remote ssh vscode server"; + isabelroses-web.enable = mkEnableOption "Enables my website"; + searxng.enable = mkEnableOption "Enables searxng search engine service"; + nginx.enable = mkEnableOption "Enables nginx webserver"; + cloudflared.enable = mkEnableOption "Enables cloudflared tunnels"; + wakapi.enable = mkEnableOption "Enables wakapi"; + jellyfin.enable = mkEnableOption "Enables the jellyfin service"; + + mailserver = { + enable = mkEnableOption "Enable the mailserver service"; + rspamd-web.enable = mkEnableOption "Enable rspamd web ui"; + }; + + # monitoring tools + monitoring = { + enable = mkEnableOption "system monitoring services"; # // {default = ifOneEnabled cfg "grafana" "prometheus" "loki";}; + prometheus.enable = mkEnableOption' "Prometheus monitoring service"; + grafana.enable = mkEnableOption' "Grafana monitoring service"; + loki.enable = mkEnableOption' "Loki monitoring service"; + }; + + # database backends + database = { + mysql.enable = mkEnableOption "MySQL database service"; + mongodb.enable = mkEnableOption "MongoDB service"; + postgresql.enable = mkEnableOption "Postgresql service"; + redis.enable = mkEnableOption "Redis service"; + }; + + smb = { + enable = mkEnableOption "Enables smb shares"; + host.enable = mkEnableOption "Enables hosting of smb shares"; + + # should smb shares be enabled as a recpient machine + recive = { + general = mkEnableOption "genral share"; + media = mkEnableOption "media share"; + }; + }; + }; +} diff --git a/modules/options/system/activation.nix b/modules/options/system/activation.nix new file mode 100644 index 000000000..87a3731ce --- /dev/null +++ b/modules/options/system/activation.nix @@ -0,0 +1,7 @@ +{lib, ...}: let + inherit (lib) mkEnableOption mdDoc; +in { + options.modules.system.activation = { + diffGenerations = mkEnableOption (mdDoc "diff view between rebuilds"); + }; +} diff --git a/modules/options/system/boot.nix b/modules/options/system/boot.nix new file mode 100644 index 000000000..29cc4d501 --- /dev/null +++ b/modules/options/system/boot.nix @@ -0,0 +1,116 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib) mkOption mkEnableOption types; +in { + options.modules.system.boot = { + enableKernelTweaks = mkEnableOption "security and performance related kernel parameters"; + enableInitrdTweaks = mkEnableOption "quality of life tweaks for the initrd stage"; + recommendedLoaderConfig = mkEnableOption "tweaks for common bootloader configs per my liking"; + loadRecommendedModules = mkEnableOption "kernel modules that accommodate for most use cases"; + tmpOnTmpfs = mkEnableOption "`/tmp` living on tmpfs. false means it will be cleared manually on each reboot"; + + kernel = mkOption { + type = types.raw; + default = pkgs.linuxPackages_latest; + description = "The kernel to use for the system."; + }; + + # https://nixos.wiki/wiki/Secure_Boot + secureBoot = mkEnableOption '' + secure-boot and load necessary packages, say good bye to systemd-boot + ''; + + extraModprobeConfig = mkOption { + type = types.str; + default = ''options hid_apple fnmode=1''; + description = "Extra modprobe config that will be passed to system modprobe config."; + }; + + silentBoot = + mkEnableOption (lib.mdDoc '' + almost entirely silent boot process through `quiet` kernel parameter + '') + // {default = config.modules.system.boot.plymouth.enable;}; + + extraKernelParams = mkOption { + type = with types; listOf str; + default = []; + }; + + extraModulePackages = mkOption { + type = with types; listOf package; + default = with config.boot.kernelPackages; [acpi_call]; + description = "Extra kernel modules to be loaded."; + }; + + loader = mkOption { + type = types.enum ["none" "grub" "systemd-boot"]; + default = "none"; + description = "The bootloader that should be used for the device."; + }; + + device = mkOption { + type = with types; nullOr str; + default = "nodev"; + description = "The device to install the bootloader to."; + }; + + memtest = { + enable = mkEnableOption "memtest86+"; + package = mkOption { + type = types.package; + default = pkgs.memtest86plus; + description = "The memtest package to use."; + }; + }; + + encryption = { + enable = mkEnableOption "LUKS encryption"; + + device = mkOption { + type = types.str; + default = "enc"; + description = '' + The LUKS label for the device that will be decrypted on boot. + Currently does not support multiple devices at once. + ''; + }; + + keyFile = mkOption { + type = with types; nullOr str; + default = null; + description = '' + The path to the keyfile that will be used to decrypt the device. + Needs to be an absolute path, and the file must exist. Set to `null` + to disable. + ''; + }; + + keySize = mkOption { + type = types.int; + default = 4096; + description = '' + The size of the keyfile in bytes. + ''; + }; + + fallbackToPassword = mkOption { + type = types.bool; + default = !config.boot.initrd.systemd.enable; + description = '' + Whether or not to fallback to password authentication if the keyfile + is not present. + ''; + }; + }; + + plymouth = { + enable = mkEnableOption "plymouth boot splash"; + withThemes = mkEnableOption "plymouth theme"; + }; + }; +} diff --git a/modules/options/system/default.nix b/modules/options/system/default.nix new file mode 100644 index 000000000..1110f0e1e --- /dev/null +++ b/modules/options/system/default.nix @@ -0,0 +1,88 @@ +{ + lib, + config, + ... +}: let + inherit (lib) mkOption mkEnableOption optionals types mdDoc; +in { + imports = [ + ./activation.nix + ./boot.nix + ./emulation.nix + ./encryption.nix + ./networking.nix + ./printing.nix + ./security.nix + ./virtualization.nix + ]; + + options.modules.system = { + warnings = optionals (config.modules.system.users == []) [ + '' + You have not added any users to be supported by your system. You may end up with an unbootable system! + Consider setting `config.modules.system.users` in your configuration + '' + ]; + + mainUser = mkOption { + type = types.enum config.modules.system.users; + description = "The username of the main user for your system"; + default = builtins.elemAt config.modules.system.users 0; + }; + + users = mkOption { + type = with types; listOf str; + default = ["isabel"]; + description = mdDoc '' + A list of users that you wish to declare as your non-system users. The first username + in the list will be treated as your main user unless `modules.system.mainUser` is set. + ''; + }; + + hostname = mkOption { + type = types.str; + description = "The name of the device for the system"; + }; + + autoLogin = mkOption { + type = types.bool; + default = false; + description = mdDoc '' + Whether to enable passwordless login. This is generally useful on systems with + FDE (Full Disk Encryption) enabled. It is a security risk for systems without FDE. + ''; + }; + + fs = mkOption { + type = with types; listOf str; + default = ["vfat" "ext4"]; + description = mdDoc '' + A list of filesystems available supported by the system + it will enable services based on what strings are found in the list. + + It would be a good idea to keep vfat and ext4 so you can mount USBs. + ''; + }; + + flakePath = mkOption { + type = types.str; + default = "/home/isabel/.config/flake"; + description = "The path to the configuration"; + }; + + sound = { + enable = mkEnableOption "sound"; + description = "Does the device have sound and its related programs be enabled"; + }; + + video = { + enable = mkEnableOption "video drivers"; + description = "Does the device allow for graphical programs"; + }; + + bluetooth = { + enable = mkEnableOption "bluetooth"; + description = "should the device load bluetooth drivers and enable blueman"; + }; + }; +} diff --git a/modules/options/system/emulation.nix b/modules/options/system/emulation.nix new file mode 100644 index 000000000..01250d3c0 --- /dev/null +++ b/modules/options/system/emulation.nix @@ -0,0 +1,25 @@ +{ + lib, + pkgs, + ... +}: let + inherit (lib) mkEnableOption mkOption types; +in { + options.modules.system.emulation = { + # should we enable emulation for additional architechtures? + # enabling this option will make it so that you can build for, e.g. + # aarch64 on x86_&4 and vice verse - not recommended on weaker machines + enable = mkEnableOption '' + emulation of additional arcitechtures via binfmt. enabling this option will make it so that the system can build for + addiitonal systems such as aarc64 on x86_64 and vice versa. + ''; + + systems = mkOption { + type = with types; listOf str; + default = builtins.filter (system: system != pkgs.system) ["aarch64-linux" "i686-linux"]; + description = '' + the systems to enable emulation for + ''; + }; + }; +} diff --git a/modules/options/system/encryption.nix b/modules/options/system/encryption.nix new file mode 100644 index 000000000..0ddd4ce8c --- /dev/null +++ b/modules/options/system/encryption.nix @@ -0,0 +1,57 @@ +{ + config, + lib, + ... +}: let + inherit (lib) mkEnableOption mkOption types mkIf; +in { + config = mkIf config.modules.system.encryption.enable { + warnings = + if config.modules.system.encryption.device == "" + then [ + '' + You have enabled LUKS encryption, but have not selected a device, you may not be able to decrypt your disk on boot. + '' + ] + else []; + }; + options.modules.system.encryption = { + enable = mkEnableOption "LUKS encryption"; + + device = mkOption { + type = types.str; # this should actually be a list + default = ""; + description = '' + The LUKS label for the device that will be decrypted on boot. + Currently does not support multiple devices at once. + ''; + }; + + keyFile = mkOption { + type = with types; nullOr str; + default = null; + description = '' + The path to the keyfile that will be used to decrypt the device. + Needs to be an absolute path, and the file must exist. Set to `null` + to disable. + ''; + }; + + keySize = mkOption { + type = types.int; + default = 4096; + description = '' + The size of the keyfile in bytes. + ''; + }; + + fallbackToPassword = mkOption { + type = types.bool; + default = !config.boot.initrd.systemd.enable; + description = '' + Whether or not to fallback to password authentication if the keyfile + is not present. + ''; + }; + }; +} diff --git a/modules/common/options/system/networking.nix b/modules/options/system/networking.nix similarity index 77% rename from modules/common/options/system/networking.nix rename to modules/options/system/networking.nix index 7ae69aef5..f45b9568f 100644 --- a/modules/common/options/system/networking.nix +++ b/modules/options/system/networking.nix @@ -1,6 +1,5 @@ {lib, ...}: with lib; { - # should we optimize tcp networking options.modules.system.networking = { optimizeTcp = mkEnableOption "Enable tcp optimizations"; }; diff --git a/modules/options/system/printing.nix b/modules/options/system/printing.nix new file mode 100644 index 000000000..a3fc4eec6 --- /dev/null +++ b/modules/options/system/printing.nix @@ -0,0 +1,13 @@ +{lib, ...}: let + inherit (lib) mkEnableOption mkOption types; +in { + options.modules.system.printing = { + enable = mkEnableOption "printing"; + + drivers = mkOption { + type = with types; listOf str; + default = []; + description = "A list of additional drivers to install for printing"; + }; + }; +} diff --git a/modules/options/system/security.nix b/modules/options/system/security.nix new file mode 100644 index 000000000..21a63104b --- /dev/null +++ b/modules/options/system/security.nix @@ -0,0 +1,88 @@ +{ + pkgs, + lib, + ... +}: let + inherit (lib) mkOption mkEnableOption mdDoc types; +in { + options.modules.system.security = { + fixWebcam = mkEnableOption (mdDoc "Fix the purposefully broken webcam by un-blacklisting the related kernel module."); + tor.enable = mkEnableOption (mdDoc "Tor daemon"); + lockModules = mkEnableOption (mdDoc "Lock kernel modules to the ones specified in the configuration. Highly breaking."); + + auditd = { + enable = mkEnableOption (mdDoc "Enable the audit daemon."); + autoPrune = { + enable = mkEnableOption (mdDoc "Enable auto-pruning of audit logs."); + + size = mkOption { + type = types.int; + default = 524288000; # roughly 500 megabytes + description = "The maximum size of the audit log in bytes."; + }; + + dates = mkOption { + type = types.str; + default = "daily"; + example = "weekly"; + description = "How often cleaning is triggered. Passed to systemd.time"; + }; + }; + }; + + clamav = { + enable = mkEnableOption (mdDoc "Enable ClamAV daemon."); + + daemon = { + settings = mkOption { + type = with types; attrsOf (oneOf [bool int str (listOf str)]); + default = { + LogFile = "/var/log/clamd.log"; + LogTime = true; + VirusEvent = lib.escapeShellArgs [ + "${pkgs.libnotify}/bin/notify-send" + "--" + "ClamAV Virus Scan" + "Found virus: %v" + ]; + DetectPUA = true; + }; + description = lib.mdDoc '' + ClamAV configuration. Refer to , + for details on supported values. + ''; + }; + }; + + updater = { + enable = mkEnableOption (lib.mdDoc "ClamAV freshclam updater"); + + frequency = mkOption { + type = types.int; + default = 12; + description = lib.mdDoc '' + Number of database checks per day. + ''; + }; + + interval = mkOption { + type = types.str; + default = "hourly"; + description = lib.mdDoc '' + How often freshclam is invoked. See systemd.time(7) for more + information about the format. + ''; + }; + + settings = mkOption { + type = with types; attrsOf (oneOf [bool int str (listOf str)]); + default = {}; + description = lib.mdDoc '' + freshclam configuration. Refer to , + for details on supported values. + ''; + }; + }; + }; + }; +} diff --git a/modules/common/options/system/virtualization.nix b/modules/options/system/virtualization.nix similarity index 77% rename from modules/common/options/system/virtualization.nix rename to modules/options/system/virtualization.nix index f5d18b593..c9d57a8e7 100644 --- a/modules/common/options/system/virtualization.nix +++ b/modules/options/system/virtualization.nix @@ -2,9 +2,8 @@ inherit (lib) mkEnableOption; in { options.modules.system = { - # should virtualization (docker, qemu, podman etc.) be enabled virtualization = { - enable = mkEnableOption "virtualization"; + enable = mkEnableOption "Should the device be allowed to virtualizle processes"; docker = {enable = mkEnableOption "docker";}; podman = {enable = mkEnableOption "podman";}; qemu = {enable = mkEnableOption "qemu";}; diff --git a/modules/options/themes/default.nix b/modules/options/themes/default.nix new file mode 100644 index 000000000..1fac1c3a8 --- /dev/null +++ b/modules/options/themes/default.nix @@ -0,0 +1,59 @@ +{ + lib, + pkgs, + config, + ... +}: let + inherit (lib) mkOption mkEnableOption types mdDoc; + cfg = config.modules.style; +in { + imports = [./gtk.nix ./qt.nix]; + options = { + modules = { + style = { + forceGtk = mkEnableOption "Force GTK applications to use the GTK theme"; + useKvantum = mkEnableOption "Use Kvantum to theme QT applications"; + + # choose a colorscheme + colorScheme = { + # "Name Of The Scheme" + name = mkOption { + type = with types; nullOr (enum ["Catppuccin Mocha" "Tokyo Night"]); + description = "The colorscheme that should be used globally to theme your system."; + default = "Catppuccin Mocha"; + }; + + # "name-of-the-scheme" + slug = mkOption { + type = types.str; + default = lib.serializeTheme "${cfg.colorScheme.name}"; + description = mdDoc '' + The serialized slug for the colorScheme you are using. Defaults to a lowercased version of the theme name with spaces + replaced with hyphens. Only change if the slug is expected to be different." + ''; + }; + }; + + pointerCursor = { + package = mkOption { + type = types.package; + description = "The package providing the cursors"; + default = pkgs.catppuccin-cursors.mochaDark; + }; + + name = mkOption { + type = types.str; + description = "The name of the cursor inside the package"; + default = "Catppuccin-Mocha-Dark-Cursors"; + }; + + size = mkOption { + type = types.int; + description = "The size of the cursor"; + default = 24; + }; + }; + }; + }; + }; +} diff --git a/modules/options/themes/gtk.nix b/modules/options/themes/gtk.nix new file mode 100644 index 000000000..0501f5d15 --- /dev/null +++ b/modules/options/themes/gtk.nix @@ -0,0 +1,68 @@ +{ + lib, + pkgs, + ... +}: let + inherit (lib) mkOption mkEnableOption types; +in { + options = { + modules = { + style = { + gtk = { + enable = mkEnableOption "GTK theming optionss"; + usePortal = mkEnableOption "native desktop portal use for filepickers"; + + theme = { + name = mkOption { + type = types.str; + default = "Catppuccin-Mocha-Standard-Sapphire-Dark"; + description = "The name for the GTK theme package"; + }; + + package = mkOption { + type = types.package; + description = "The theme package to be used for GTK programs"; + default = pkgs.catppuccin-gtk.override { + size = "standard"; + accents = ["sapphire"]; + variant = "mocha"; + tweaks = ["normal"]; + }; + }; + }; + + iconTheme = { + name = mkOption { + type = types.str; + description = "The name for the icon theme that will be used for GTK programs"; + default = "Papirus-Dark"; + }; + + package = mkOption { + type = types.package; + description = "The GTK icon theme to be used"; + default = pkgs.catppuccin-papirus-folders.override { + accent = "sapphire"; + flavor = "mocha"; + }; + }; + }; + + font = { + name = mkOption { + type = types.str; + description = "The name of the font that will be used for GTK applications"; + default = "RobotoMono Nerd Font Regular"; + }; + + size = mkOption { + type = types.int; + description = "The size of the font"; + default = 14; + }; + }; + }; + }; + }; + }; +} diff --git a/modules/options/themes/qt.nix b/modules/options/themes/qt.nix new file mode 100644 index 000000000..f75e5c368 --- /dev/null +++ b/modules/options/themes/qt.nix @@ -0,0 +1,43 @@ +{ + lib, + pkgs, + config, + ... +}: let + inherit (lib) mkEnableOption mkOption types; + cfg = config.modules.style; +in { + options = { + modules = { + style = { + qt = { + enable = mkEnableOption "QT Style Module"; + + theme = { + package = mkOption { + type = types.package; + default = pkgs.catppuccin-kde.override { + flavour = ["mocha"]; + accents = ["sapphire"]; + winDecStyles = ["modern"]; + }; + description = "The theme package to be used for QT programs"; + }; + + name = mkOption { + type = types.str; + default = "Catppuccin-Mocha-Dark"; + description = "The name for the QT theme package"; + }; + }; + + kdeglobals.source = mkOption { + type = types.path; + default = "${cfg.qt.theme.package}/share/color-schemes/CatppuccinMochaSapphire.colors"; + description = "The source file for the kdeglobals file. Usually provided by the qt theme package"; + }; + }; + }; + }; + }; +} diff --git a/modules/common/options/usrEnv/default.nix b/modules/options/usrEnv/default.nix similarity index 66% rename from modules/common/options/usrEnv/default.nix rename to modules/options/usrEnv/default.nix index dbc09cfac..384d488ed 100644 --- a/modules/common/options/usrEnv/default.nix +++ b/modules/options/usrEnv/default.nix @@ -1,10 +1,19 @@ -{lib, ...}: -with lib; { +{lib, ...}: let + inherit (lib) mkOption types mdDoc; +in { options.modules.usrEnv = { + useHomeManager = mkOption { + type = types.bool; + default = true; + description = mdDoc '' + Whether to use home-manager or not. Username MUST be set if this option is enabled. + ''; + }; + desktop = mkOption { type = types.enum ["Hyprland"]; default = "Hyprland"; - description = lib.mdDoc '' + description = mdDoc '' The desktop environment to be used. ''; }; @@ -12,7 +21,7 @@ with lib; { isWayland = mkOption { type = types.bool; default = true; - description = lib.mdDoc '' + description = mdDoc '' Whether to enable Wayland compatibility module. This generally includes: - Wayland nixpkgs overlay - Wayland only services @@ -21,21 +30,5 @@ with lib; { - Wayland compatible versions of packages ''; }; - - useHomeManager = mkOption { - type = types.bool; - default = true; - description = lib.mdDoc '' - Whether to use home-manager or not. Username MUST be set if this option is enabled. - ''; - }; - - noiseSupressor = mkOption { - type = with types; nullOr (enum ["rnnoise" "noisetorch"]); - default = "rnnoise"; - description = lib.mdDoc '' - The noise supressor to be used for desktop systems with sound enabled. - ''; - }; }; }