Compare commits

..

67 Commits

Author SHA1 Message Date
237a62ea8a feat: init quickshell 2025-07-13 22:17:13 +08:00
a63be876f7 chore: fmt 2025-07-13 13:11:23 +08:00
2b5a96bc20 chore: update secrets 2025-07-12 21:54:26 +08:00
02216bfa0c fix: imxyy-nix-x16 2025-07-12 21:54:05 +08:00
793dbac197 feat(imxyy-nix-x16): update secrets 2025-07-12 20:32:29 +08:00
c584091e60 feat: init imxyy-nix-x16 2025-07-12 19:52:42 +08:00
68b1765582 fix(tealdeer): auto update 2025-07-12 16:00:35 +08:00
8a169dbfa1 fix(open-webui): use stable 2025-07-11 20:43:58 +08:00
2c035ac47a fix: immich 2025-07-11 20:43:58 +08:00
5648ae6b31 feat: tealdeer (tldr) 2025-07-11 20:34:30 +08:00
c504274eca chore: drop cht.sh 2025-07-11 20:34:21 +08:00
bd192f0443 feat(imxyy-nix-server): immich 2025-07-11 18:30:02 +08:00
99e5362345 feat(jj): signing 2025-07-11 16:58:50 +08:00
35693c9782 feat(starship): use "jj root" to determine whether to show jj module 2025-07-11 15:40:59 +08:00
aba70d46a9 feat(starship): only show git status if not in a jj repo 2025-07-11 15:27:24 +08:00
be4de25d84 feat(zsh): starship prompt 2025-07-11 14:52:46 +08:00
2177549100 chore: update flake.lock 2025-07-11 14:52:35 +08:00
abdc2f5c6c feat(coding/langs): QML 2025-07-06 14:29:49 +08:00
99121f72c9 feat(style): use papirus icon 2025-07-06 14:29:34 +08:00
b460cb58ef refactor(pkgs): use haumea for automatic callPackage 2025-07-06 14:29:10 +08:00
32232d08db fix: add self back to wheel group 2025-07-05 11:25:38 +08:00
2d9c505ad7 feat(sing-box): use qjebbs/sing-box 2025-07-04 21:57:03 +08:00
667af5a5a6 refactor: overlay 2025-07-04 21:33:46 +08:00
e79ed0f643 feat(doas): add sudo wrapper 2025-07-04 21:32:35 +08:00
d0fcde133d feat: move to doas 2025-07-04 20:06:59 +08:00
b953e5b7ce chore: update flake.lock 2025-07-04 20:06:39 +08:00
c8f098f1a2 feat(sing-box): use PuerNya/sing-box/building for outbound_provider 2025-06-29 16:40:08 +08:00
e454e12d2f feat(kitty): do not use "-1" option 2025-06-29 15:16:30 +08:00
44a72b39e4 feat: use both sjtu mirrors 2025-06-29 15:16:30 +08:00
4af7226777 chore: update imxyy-nix password 2025-06-29 15:16:30 +08:00
28c59be2a7 feat(nvim): add leap.nvim 2025-06-29 15:16:30 +08:00
51b882f2c5 feat: add ~/.npm-global/bin to PATH 2025-06-29 15:16:30 +08:00
13b69ccc95 refactor: persist 2025-06-29 15:16:30 +08:00
be5fd3b9ff fix(wine): add to all.nix 2025-06-29 15:16:30 +08:00
20ddfb5ddd chore: drop trash and dooit 2025-06-29 15:16:30 +08:00
4d2949ab93 chore: drop cinny 2025-06-29 15:16:30 +08:00
e0faac096b feat: wechat 2025-06-29 15:16:30 +08:00
1c6708bad5 feat(wine): use bottles 2025-06-29 15:16:30 +08:00
a07742a206 feat(qq): use unstable 2025-06-29 15:16:30 +08:00
7bacc8ae06 feat: remote build for EFLKumo 2025-06-28 23:27:26 +08:00
f400aaf570 feat(tmux): manage by home-manager 2025-06-28 18:38:51 +08:00
dbd3195430 feat(imxyy-nix-server/virt): ignore unhandled MSR 2025-06-27 23:40:57 +08:00
d041f61c46 feat: update README.md 2025-06-27 23:22:24 +08:00
705f702535 feat: use nh (yet another nix helper) 2025-06-27 23:22:16 +08:00
8fe373eeb5 chore: drop useless github-cli-comp 2025-06-27 23:21:52 +08:00
64dd1077b6 feat: add jujutsu VCS 2025-06-27 23:21:29 +08:00
8fe95f071a chore: update flake.lock 2025-06-27 22:03:38 +08:00
bd21506f0d fix: do not mkForce substituters 2025-06-27 22:03:30 +08:00
c8c6a09684 feat(desktop): use NIXOS_OZONE_WL 2025-06-22 09:51:17 +08:00
0c679290c5 feat: zed-editor 2025-06-21 22:55:37 +08:00
4685f31aa1 feat(xwayland-satellite): use builtin fractional scaling 2025-06-21 22:55:20 +08:00
77b8578379 fix(niri): avoid double spawning xsettingsd 2025-06-21 13:03:46 +08:00
5bf4a22e8f feat(siyuan): v3.1.24 -> v.3.1.30 2025-06-21 11:38:35 +08:00
91257fbcf8 chore(matrix-synapse): use stable deu to the build failure of unstable 2025-06-21 11:36:42 +08:00
13cc8234e1 feat: move to umport for automatic module import 2025-06-21 11:30:35 +08:00
89aa6186f2 chore: remove unused nerd-fonts.jetbrains-mono 2025-06-21 10:42:11 +08:00
794593222c fix(niri): buggy clipboard in kitty (maybe?) 2025-06-21 10:37:24 +08:00
8c64e8e7b9 fix: emoji display 2025-06-21 10:36:55 +08:00
8348cd9a54 chore: update flake.lock 2025-06-20 21:55:51 +08:00
83772d34dd feat(niri): place-within-backdrop 2025-06-20 21:55:31 +08:00
5e5f2ed1bb chore(mpd): use stable due to the build failure of unstable 2025-06-20 21:55:03 +08:00
d7a3fc7a07 chore: drop waydroid 2025-06-20 21:53:34 +08:00
3c4bc5043e feat(imxyy-nix): use linux-cachyos 2025-06-20 21:53:20 +08:00
a2261cacd1 feat(imxyy-nix-server): use linux-cachyos 2025-06-17 08:16:52 +08:00
558faa058d chore: update flake.lock 2025-06-15 15:45:42 +08:00
9c547b6207 fix: persist zoxide database 2025-06-15 15:45:17 +08:00
2a4694b633 feat(zsh): move to official omz 2025-06-15 13:54:03 +08:00
209 changed files with 17047 additions and 1725 deletions

View File

@@ -1,6 +1,7 @@
keys: keys:
- &imxyy-nix age1jf5pg2x6ta8amj40xdy0stvcvrdlkwc2nrwtmkpymu0qclk0eg5qmm9kns - &imxyy-nix age1jf5pg2x6ta8amj40xdy0stvcvrdlkwc2nrwtmkpymu0qclk0eg5qmm9kns
- &imxyy-nix-server age1hpgg6psejh4y6jcdd34wxuml75fnweqpe0kh8376yqsctsfn9qxs037kk6 - &imxyy-nix-server age1hpgg6psejh4y6jcdd34wxuml75fnweqpe0kh8376yqsctsfn9qxs037kk6
- &imxyy-nix-x16 age1r0fv0tagxupfacv0aaxk5ss7sqvswv6kq8tk3x46ndqrj6f5afvqegahxq
- &imxyy-cloudwin age1tp7th3rrv3x0l6jl76n0hjqjp223w2y586pkgr0hcjwdm254jd5shkj6a8 - &imxyy-cloudwin age1tp7th3rrv3x0l6jl76n0hjqjp223w2y586pkgr0hcjwdm254jd5shkj6a8
creation_rules: creation_rules:
- path_regex: secrets/.*\.(yaml|toml|json|env|dae|txt|conf)$ - path_regex: secrets/.*\.(yaml|toml|json|env|dae|txt|conf)$
@@ -8,4 +9,5 @@ creation_rules:
- age: - age:
- *imxyy-nix - *imxyy-nix
- *imxyy-nix-server - *imxyy-nix-server
- *imxyy-nix-x16
- *imxyy-cloudwin - *imxyy-cloudwin

View File

@@ -2,15 +2,19 @@ all: fmt switch
switch: switch:
@echo "Rebuilding NixOS..." @echo "Rebuilding NixOS..."
@nixos-rebuild switch --flake . --sudo --json |& nom @nh os switch .
boot: boot:
@echo "Rebuilding NixOS..." @echo "Rebuilding NixOS..."
@nixos-rebuild boot --flake . --sudo --json |& nom @nh os boot .
test:
@echo "Rebuilding NixOS..."
@nh os test .
vm: vm:
@echo "Building NixOS VM..." @echo "Building NixOS VM..."
@nixos-rebuild build-vm --flake . --json |& nom @nh os build-vm .
update: update:
@echo "Updating flakes..." @echo "Updating flakes..."
@@ -23,17 +27,17 @@ replpkgs:
@nix repl -f flake:nixpkgs @nix repl -f flake:nixpkgs
repl: repl:
@nixos-rebuild repl --flake . @nh os repl .
cleandry: cleandry:
@echo "Listing all generations older than 15 days..." @echo "Listing all generations older than 15 days..."
@sudo nix profile wipe-history --profile /nix/var/nix/profiles/system --dry-run --older-than 15d @sudo nix profile wipe-history --profile /nix/var/nix/profiles/system --dry-run --older-than 15d
@nix run home-manager#home-manager -- expire-generations -15days --dry-run @nix profile wipe-history --profile ~/.local/state/nix/profiles/home-manager --dry-run --older-than 15d
clean: clean:
@echo "Removing all generations older than 15 days..." @echo "Removing all generations older than 15 days..."
@sudo nix profile wipe-history --profile /nix/var/nix/profiles/system --older-than 15d @sudo nix profile wipe-history --profile /nix/var/nix/profiles/system --older-than 15d
@nix run home-manager#home-manager -- expire-generations -15days @nix profile wipe-history --profile ~/.local/state/nix/profiles/home-manager --older-than 15d
gc: gc:
@nix store gc --debug @nix store gc --debug

View File

@@ -32,7 +32,7 @@ As for Flakes, refer to
| **Application Launcher** | wofi | | **Application Launcher** | wofi |
| **Notification Daemon** | SwayNotificationCenter | | **Notification Daemon** | SwayNotificationCenter |
| **Input method framework** | Fcitx5 | | **Input method framework** | Fcitx5 |
| **Shell** | zsh & custom oh-my-zsh | | **Shell** | Zsh |
| **Netease Cloudmusic Player** | go-musicfox | | **Netease Cloudmusic Player** | go-musicfox |
| **Media Player** | mpv | | **Media Player** | mpv |
| **Text Editor** | Neovim | | **Text Editor** | Neovim |
@@ -52,28 +52,3 @@ And more...
- `vars.nix` - my variables - `vars.nix` - my variables
- `secrets/` - secrets managed by sops-nix. see [./secrets](./secrets) for details - `secrets/` - secrets managed by sops-nix. see [./secrets](./secrets) for details
- `flake.nix` - flake entry - `flake.nix` - flake entry
<!--
## Deployment Guide
Since this repository is **heavily** based on my **own** daily use,
it includes, but not limit to, the tweaks listed below:
- auto login some specific TTYs (see [./modules/getty-autologin.nix](./modules/getty-autologin.nix) for details)
- `config.my` alias for custom modules and `config.my.home` alias for single user home-manger configuartion
- `lib.my` utilities to define custom modules conveniently
Therefore, if you want to deploy this setup locally, make sure that
you have **carefully** read **every single line** of code in this repository.
Then, you can follow the guide to deploy:
0. make sure that you have a very **reliable** networking environment (you know what I'm talking about)
1. boot into LiveCD
2. repartition your disk, it should be like this:
- `/dev/sda`
- `/dev/sda1`: boot partition (remember to set its type to `EFI System` in `cfdisk`, don't ask me why)
3. clone the repository (if you don't have `git` installed, `nix-shell -p git` will do the trick)
4. rename one of the folders in the `config/hosts` folder
5.
-->

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -22,10 +22,17 @@
nixosDirs = [ nixosDirs = [
"/root" "/root"
"/var" "/var"
"/etc/ssh"
]; ];
nixosFiles = [ nixosFiles = [
"/etc/machine-id" "/etc/machine-id"
]; ];
homeDirs = [
{
directory = ".ssh";
mode = "0700";
}
];
}; };
}; };
} }

View File

@@ -1,8 +1,10 @@
{ pkgs, ... }:
{ {
services.open-webui = { services.open-webui = {
enable = true; enable = true;
host = "127.0.0.1"; host = "127.0.0.1";
port = 8089; port = 8089;
package = pkgs.stable.open-webui;
}; };
services.caddy.virtualHosts."ai.imxyy.top" = { services.caddy.virtualHosts."ai.imxyy.top" = {
extraConfig = '' extraConfig = ''

View File

@@ -0,0 +1,47 @@
{
config,
lib,
pkgs,
sopsRoot,
...
}:
{
sops.secrets.et-imxyy-nix-server-nixremote = {
sopsFile = sopsRoot + /et-imxyy-nix-server-nixremote.toml;
format = "binary";
};
environment.systemPackages = [ pkgs.easytier ];
systemd.services."easytier-nixremote" = {
enable = true;
script = "${pkgs.easytier}/bin/easytier-core -c ${config.sops.secrets.et-imxyy-nix-server-nixremote.path}";
serviceConfig = {
Restart = lib.mkOverride 500 "always";
RestartMaxDelaySec = lib.mkOverride 500 "1m";
RestartSec = lib.mkOverride 500 "100ms";
RestartSteps = lib.mkOverride 500 9;
User = "root";
};
wantedBy = [ "multi-user.target" ];
after = [
"network.target"
"sops-nix.service"
];
};
users.groups.nixremote = { };
users.users.nixremote = {
isSystemUser = true;
description = "nix remote build user";
group = "nixremote";
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOEFLUkyeaK8ZPPZdVNEmtx8zvoxi7xqS2Z6oxRBuUPO imxyy@imxyy-nix"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBWOy0QmAyxENg/O5m3cus8U3c9jCLioivwcWsh5/a82 imxyy-hisense-pad"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK8pivvE8PMtsOxmccfNhH/4KehDKhBfUfJbQZxo/SZT imxyy-ace5"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKALTBn/QSGcSPgMg0ViSazFcaA0+nEF05EJpjbsI6dE imxyy_soope_@imxyy-cloudwin"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIENauvvhVMLsUwH9cPYsvnOg7VCL3a4yEiKm8I524TE efl@efl-nix"
];
};
nix.settings.trusted-users = [
"nixremote"
];
}

View File

@@ -21,5 +21,7 @@
./note.nix ./note.nix
./matrix.nix ./matrix.nix
./minio.nix ./minio.nix
./build.nix
./immich.nix
]; ];
} }

View File

@@ -18,13 +18,15 @@ in
]; ];
boot.initrd.kernelModules = [ "amdgpu" ]; boot.initrd.kernelModules = [ "amdgpu" ];
boot.kernelModules = [ "kvm-amd" ]; boot.kernelModules = [ "kvm-amd" ];
boot.kernelPackages = lib.mkForce pkgs.linuxKernel.packages.linux_zen; boot.kernelPackages = lib.mkForce pkgs.linuxPackages_cachyos;
services.scx.enable = true;
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
boot.tmp.useTmpfs = true; boot.tmp.useTmpfs = true;
boot.supportedFilesystems = [ "zfs" ]; boot.supportedFilesystems = [ "zfs" ];
boot.zfs = { boot.zfs = {
extraPools = [ "data" ]; extraPools = [ "data" ];
forceImportRoot = false; forceImportRoot = false;
package = pkgs.zfs_cachyos;
}; };
services.zfs.autoScrub.enable = true; services.zfs.autoScrub.enable = true;
services.btrfs.autoScrub.enable = true; services.btrfs.autoScrub.enable = true;

View File

@@ -12,20 +12,11 @@
"workspace" "workspace"
"Virt" "Virt"
{
directory = ".ssh";
mode = "0700";
}
".local/state" ".local/state"
".local/share"
".local/share/nvim"
".cache" ".cache"
".ollama" ".ollama"
]; ];
nixosDirs = [
"/etc/ssh"
];
}; };
}; };
} }

View File

@@ -0,0 +1,17 @@
{ ... }:
{
services.immich = {
enable = true;
host = "127.0.0.1";
port = 8096;
mediaLocation = "/mnt/nas/immich";
group = "nextcloud";
};
services.caddy.virtualHosts."immich.imxyy.top" = {
extraConfig = ''
reverse_proxy :8096 {
header_up X-Real-IP {remote_host}
}
'';
};
}

View File

@@ -392,6 +392,21 @@
customDomains = [ "matrix.imxyy.top" ]; customDomains = [ "matrix.imxyy.top" ];
} }
{
name = "immich-http";
type = "http";
localIP = "127.0.0.1";
localPort = 80;
customDomains = [ "immich.imxyy.top" ];
}
{
name = "immich-https";
type = "https";
localIP = "127.0.0.1";
localPort = 443;
customDomains = [ "immich.imxyy.top" ];
}
{ {
name = "minecraft"; name = "minecraft";
type = "tcp"; type = "tcp";
@@ -455,7 +470,7 @@
environment.systemPackages = [ pkgs.easytier ]; environment.systemPackages = [ pkgs.easytier ];
systemd.services."easytier" = { systemd.services."easytier" = {
enable = true; enable = true;
script = "easytier-core -c ${config.sops.secrets.et-imxyy-nix-server.path}"; script = "${pkgs.easytier}/bin/easytier-core -c ${config.sops.secrets.et-imxyy-nix-server.path}";
serviceConfig = { serviceConfig = {
Restart = lib.mkOverride 500 "always"; Restart = lib.mkOverride 500 "always";
RestartMaxDelaySec = lib.mkOverride 500 "1m"; RestartMaxDelaySec = lib.mkOverride 500 "1m";
@@ -468,11 +483,6 @@
"network.target" "network.target"
"sops-nix.service" "sops-nix.service"
]; ];
path = with pkgs; [
easytier
iproute2
bash
];
}; };
virtualisation.oci-containers = { virtualisation.oci-containers = {

View File

@@ -27,7 +27,7 @@
ports = [ "8093:8080" ]; ports = [ "8093:8080" ];
}; };
siyuan = { siyuan = {
image = "apkdv/siyuan-unlock:v3.1.24"; image = "apkdv/siyuan-unlock:v3.1.30";
volumes = [ volumes = [
"/mnt/nas/siyuan/workspace:/workspace" "/mnt/nas/siyuan/workspace:/workspace"
"/mnt/nas/siyuan:/home/siyuan" "/mnt/nas/siyuan:/home/siyuan"

View File

@@ -26,9 +26,8 @@
]; ];
users = { users = {
users.nas = { users.nas = {
isNormalUser = true; isSystemUser = true;
home = "/var/empty"; description = "NAS user";
description = "nas user";
group = "nextcloud"; group = "nextcloud";
}; };
}; };

View File

@@ -23,6 +23,10 @@ in
"amd_iommu=on" "amd_iommu=on"
"vfio-pci.ids=${lib.concatStringsSep "," gpuIDs}" "vfio-pci.ids=${lib.concatStringsSep "," gpuIDs}"
]; ];
extraModprobeConfig = ''
options kvm ignore_msrs=Y
options kvm report_ignored_msrs=N
'';
}; };
virtualisation.spiceUSBRedirection.enable = true; virtualisation.spiceUSBRedirection.enable = true;
my.virt.enable = true; my.virt.enable = true;

View File

@@ -0,0 +1,8 @@
{
imports = [
./nixos.nix
./hardware.nix
./home.nix
./net.nix
];
}

View File

@@ -0,0 +1,106 @@
{
config,
lib,
pkgs,
username,
...
}:
let
btrfs = "/dev/disk/by-uuid/69ab72d4-6ced-4f70-8b5e-aa2daa8c0b6b";
in
{
boot = {
initrd = {
kernelModules = [ "amdgpu" ];
availableKernelModules = [
"nvme"
"xhci_pci"
"thunderbolt"
"uas"
"sd_mod"
];
verbose = false;
};
kernelPackages = lib.mkForce pkgs.linuxPackages_cachyos;
kernelModules = [ "kvm-amd" ];
tmp.useTmpfs = true;
kernel.sysctl = {
"fs.file-max" = 9223372036854775807;
};
};
services.scx.enable = true;
fileSystems."/" = {
device = btrfs;
fsType = "btrfs";
options = [
"compress=zstd"
"subvol=root"
];
};
fileSystems."/nix" = {
device = btrfs;
fsType = "btrfs";
options = [
"compress=zstd"
"subvol=nix"
];
};
my.persist.location = "/nix/persist";
fileSystems."/nix/persist" = {
device = btrfs;
fsType = "btrfs";
options = [
"compress=zstd"
"subvol=persist"
];
neededForBoot = true;
};
boot.initrd.postDeviceCommands = lib.mkAfter ''
mkdir /btrfs_tmp
mount ${btrfs} /btrfs_tmp
mkdir -p /btrfs_tmp/old_roots
if [[ -e /btrfs_tmp/root ]]; then
timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/root)" "+%Y-%m-%-d_%H:%M:%S")
mv /btrfs_tmp/root "/btrfs_tmp/old_roots/$timestamp"
fi
delete_subvolume_recursively() {
IFS=$'\n'
for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
delete_subvolume_recursively "/btrfs_tmp/$i"
done
btrfs subvolume delete "$1"
}
for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +14); do
delete_subvolume_recursively "$i"
done
btrfs subvolume create /btrfs_tmp/root
umount /btrfs_tmp
'';
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/96D3-93B0";
fsType = "vfat";
options = [
"uid=0"
"gid=0"
"fmask=0077"
"dmask=0077"
];
};
networking.useDHCP = lib.mkDefault false;
hardware.enableRedistributableFirmware = lib.mkDefault true;
hardware.cpu.amd.updateMicrocode = config.hardware.enableRedistributableFirmware;
nixpkgs.hostPlatform = lib.mkForce "x86_64-linux";
}

View File

@@ -0,0 +1,141 @@
{
config,
lib,
pkgs,
username,
...
}:
{
my.home = {
home.packages = with pkgs; [
localsend
rclone
wpsoffice-cn
wps-office-fonts
ttf-wps-fonts
evince
anki
ayugram-desktop
telegram-desktop
signal-desktop
discord
qq
wechat
gnome-clocks
wineWowPackages.waylandFull
pavucontrol
pamixer
];
programs.zsh = {
sessionVariables = {
PATH = "/home/${username}/bin:$PATH";
};
};
};
my = {
gpg.enable = true;
cli.all.enable = true;
coding.all.enable = true;
desktop.all.enable = true;
desktop.browser.librewolf.enable = lib.mkForce false;
i18n.fcitx5.enable = true;
xdg = {
enable = true;
defaultApplications =
let
browser = [ "zen-beta.desktop" ];
editor = [ "codium.desktop" ];
imageviewer = [ "org.gnome.Shotwell-Viewer.desktop" ];
in
{
"inode/directory" = [ "nemo.desktop" ];
"application/pdf" = [ "org.gnome.Evince.desktop" ];
"text/*" = editor;
"application/json" = editor;
"text/html" = editor;
"text/xml" = editor;
"application/xml" = editor;
"application/xhtml+xml" = editor;
"application/xhtml_xml" = editor;
"application/rdf+xml" = editor;
"application/rss+xml" = editor;
"application/x-extension-htm" = editor;
"application/x-extension-html" = editor;
"application/x-extension-shtml" = editor;
"application/x-extension-xht" = editor;
"application/x-extension-xhtml" = editor;
"x-scheme-handler/about" = browser;
"x-scheme-handler/ftp" = browser;
"x-scheme-handler/http" = browser;
"x-scheme-handler/https" = browser;
"x-scheme-handler/unknown" = browser;
"audio/*" = imageviewer;
"video/*" = imageviewer;
"image/*" = imageviewer;
"image/gif" = imageviewer;
"image/jpeg" = imageviewer;
"image/png" = imageviewer;
"image/webp" = imageviewer;
};
extraBookmarks =
let
homedir = config.my.home.home.homeDirectory;
in
[
"file://${homedir}/NAS NAS"
"file://${homedir}/NAS/imxyy_soope_ NAS imxyy_soope_"
"file://${homedir}/NAS/imxyy_soope_/OS NAS OS"
];
};
persist = {
enable = true;
homeDirs = [
"Documents"
"Downloads"
"Videos"
"Music"
"Pictures"
"bin"
"workspace"
".cache"
".local/state"
".local/share/Anki2"
".local/share/shotwell"
".local/share/cheat.sh"
".local/share/Kingsoft"
".local/share/AyuGramDesktop"
".local/share/TelegramDesktop"
".config/Signal"
".config/discord"
".config/QQ"
".xwechat"
".config/Kingsoft"
".config/dconf"
".config/gh"
".config/pulse"
".config/pip"
".config/libreoffice"
".config/sunshine"
];
};
};
}

View File

@@ -0,0 +1,59 @@
{
config,
lib,
pkgs,
sopsRoot,
...
}:
{
boot.kernelParams = [
"biosdevname=0"
"net.ifnames=0"
];
networking.networkmanager.enable = true;
sops.secrets.dae-imxyy-nix-x16 = {
sopsFile = sopsRoot + /dae-imxyy-nix-x16.dae;
format = "binary";
};
services.dae = {
enable = true;
configFile = config.sops.secrets.dae-imxyy-nix-x16.path;
};
systemd.services.dae.after = [ "sops-nix.service" ];
sops.secrets.mihomo = {
sopsFile = sopsRoot + /mihomo.yaml;
format = "yaml";
key = "";
};
systemd.services.mihomo.after = [ "sops-nix.service" ];
services.mihomo = {
enable = true;
configFile = config.sops.secrets.mihomo.path;
webui = pkgs.metacubexd;
};
sops.secrets.et-imxyy-nix-x16 = {
sopsFile = sopsRoot + /et-imxyy-nix-x16.toml;
format = "binary";
};
environment.systemPackages = with pkgs; [
easytier
];
systemd.services."easytier" = {
enable = true;
script = "${pkgs.easytier}/bin/easytier-core -c ${config.sops.secrets.et-imxyy-nix-x16.path}";
serviceConfig = {
Restart = lib.mkOverride 500 "always";
RestartMaxDelaySec = lib.mkOverride 500 "1m";
RestartSec = lib.mkOverride 500 "100ms";
RestartSteps = lib.mkOverride 500 9;
User = "root";
};
wantedBy = [ "multi-user.target" ];
after = [
"network.target"
"sops-nix.service"
];
};
}

View File

@@ -0,0 +1,175 @@
{
lib,
pkgs,
config,
username,
sopsRoot,
...
}:
{
security.pam.loginLimits = [
{
domain = "*";
type = "soft";
item = "nofile";
value = "524288";
}
];
boot.kernelParams = [
"usbcore.autosuspend=-1" # Avoid usb autosuspend (for usb bluetooth adapter)
];
boot.loader = {
efi.canTouchEfiVariables = true;
systemd-boot.enable = true;
grub.enable = false;
timeout = 0;
};
hardware.graphics.enable = true;
hardware.graphics.enable32Bit = true;
systemd.services.nix-daemon = {
environment.TMPDIR = "/var/cache/nix";
serviceConfig.CacheDirectory = "nix";
};
environment.variables.NIX_REMOTE = "daemon";
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = false;
alsa.support32Bit = false;
pulse.enable = false;
audio.enable = false;
};
services.pulseaudio = {
enable = true;
support32Bit = true;
package = pkgs.pulseaudioFull;
extraConfig = ''
load-module module-switch-on-connect
unload-module module-suspend-on-idle
'';
};
hardware.bluetooth = {
enable = true;
powerOnBoot = true;
settings = {
General = {
Enable = "Source,Sink,Media,Socket";
Disable = "HeadSet";
MultiProfile = "multiple";
};
};
};
users.extraUsers.${username}.extraGroups = [ "audio" ];
fonts = {
enableDefaultPackages = false;
fontDir.enable = true;
packages = with pkgs; [
noto-fonts
noto-fonts-cjk-sans
noto-fonts-emoji
jetbrains-mono
nerd-fonts.symbols-only
];
fontconfig.defaultFonts = {
serif = [
"Noto Serif CJK SC"
"Noto Serif"
"Symbols Nerd Font"
];
sansSerif = [
"Noto Sans CJK SC"
"Noto Sans"
"Symbols Nerd Font"
];
monospace = [
"JetBrains Mono"
"Noto Sans Mono CJK SC"
"Symbols Nerd Font Mono"
];
emoji = [ "Noto Color Emoji" ];
};
};
services.printing.enable = true;
services.keyd = {
enable = true;
keyboards.default.settings = {
main = {
capslock = "overload(control, esc)";
home = "end";
};
shift = {
home = "home";
};
control = {
delete = "print";
};
};
};
services.gvfs.enable = true;
services.openssh = {
enable = true;
settings = {
# Forbid root login through SSH.
PermitRootLogin = null;
PasswordAuthentication = true;
};
};
environment.systemPackages = [
pkgs.rclone
];
sops.secrets.imxyy-nix-rclone = {
sopsFile = sopsRoot + /imxyy-nix-rclone.conf;
format = "binary";
};
fileSystems = {
"/home/${username}/Nextcloud" = {
device = "Nextcloud:";
fsType = "rclone";
options = [
"nodev"
"nofail"
"allow_other"
"args2env"
"config=${config.sops.secrets.imxyy-nix-rclone.path}"
"uid=1000"
"gid=100"
"rw"
"no-check-certificate"
"vfs-cache-mode=full"
];
};
"/home/${username}/NAS" = {
device = "//10.0.0.1/share";
fsType = "cifs";
options = [
"username=nas"
"password=nasshare"
"x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s"
"nodev"
"nofail"
"uid=1000"
"gid=100"
"vers=3"
"rw"
];
};
};
my.persist.nixosDirs = [ "/etc/NetworkManager/system-connections" ];
}

View File

@@ -23,7 +23,7 @@ in
verbose = false; verbose = false;
}; };
kernelPackages = lib.mkForce pkgs.linuxKernel.packages.linux_zen; kernelPackages = lib.mkForce pkgs.linuxPackages_cachyos;
kernelModules = [ "kvm-amd" ]; kernelModules = [ "kvm-amd" ];
tmp.useTmpfs = true; tmp.useTmpfs = true;
@@ -36,6 +36,7 @@ in
"resume_offset=6444127" "resume_offset=6444127"
]; ];
}; };
services.scx.enable = true;
fileSystems."/" = { fileSystems."/" = {
device = btrfs; device = btrfs;

View File

@@ -22,9 +22,9 @@
ayugram-desktop ayugram-desktop
telegram-desktop telegram-desktop
signal-desktop signal-desktop
cinny-desktop
discord discord
qq qq
wechat
gnome-clocks gnome-clocks
@@ -76,27 +76,6 @@
scale = 1.25; scale = 1.25;
}; };
}; };
spawn-at-startup = [
{
command = [
"sh"
"-c"
"sleep 3; echo 'Xft.dpi: 120' | ${lib.getExe pkgs.xorg.xrdb} -merge"
];
}
{
command = [
(toString (
pkgs.writeShellScript "xsettingsd" ''
while :
do
${lib.getExe pkgs.xsettingsd} -c ${pkgs.writeText "xsettingsd.conf" "Xft/DPI 122880\n"}
done
''
))
];
}
];
}; };
}; };
@@ -127,7 +106,7 @@
{ {
"inode/directory" = [ "nemo.desktop" ]; "inode/directory" = [ "nemo.desktop" ];
"application/pdf" = [ "evince.desktop" ]; "application/pdf" = [ "org.gnome.Evince.desktop" ];
"text/*" = editor; "text/*" = editor;
"application/json" = editor; "application/json" = editor;
@@ -175,53 +154,32 @@
".android" ".android"
"Android" "Android"
".ssh"
"bin" "bin"
"workspace" "workspace"
"WineApps"
"Virt" "Virt"
".cache" ".cache"
".local/state" ".local/state"
".local/share/Anki2" ".local/share/Anki2"
".local/share/dooit"
".local/share/nvim"
".local/share/shotwell" ".local/share/shotwell"
".local/share/Steam"
".local/share/SteamOS"
".local/share/Trash"
".local/share/cheat.sh" ".local/share/cheat.sh"
".local/share/Kingsoft" ".local/share/Kingsoft"
".local/share/oss.krtirtho.spotube"
".local/share/AyuGramDesktop" ".local/share/AyuGramDesktop"
".local/share/TelegramDesktop" ".local/share/TelegramDesktop"
".local/share/cinny"
".config/Signal" ".config/Signal"
".config/discord" ".config/discord"
".config/QQ" ".config/QQ"
".xwechat"
".config/Kingsoft" ".config/Kingsoft"
".config/dconf" ".config/dconf"
".config/gh" ".config/gh"
".config/pulse" ".config/pulse"
".config/go-musicfox/db"
".config/tmux/plugins"
".config/pip" ".config/pip"
".config/obs-studio"
".config/libreoffice" ".config/libreoffice"
".config/Moonlight Game Streaming Project"
".config/sunshine" ".config/sunshine"
]; ];
nixosDirs = [
"/etc/ssh"
];
homeFiles = [
".config/mpd/mpd.db" # requires bindfs
".config/go-musicfox/cookie"
".hmcl.json"
];
}; };
}; };
} }

View File

@@ -113,7 +113,7 @@
environment.systemPackages = [ pkgs.easytier ]; environment.systemPackages = [ pkgs.easytier ];
systemd.services."easytier" = { systemd.services."easytier" = {
enable = true; enable = true;
script = "easytier-core -c ${config.sops.secrets.et-imxyy-nix.path}"; script = "${pkgs.easytier}/bin/easytier-core -c ${config.sops.secrets.et-imxyy-nix.path}";
serviceConfig = { serviceConfig = {
Restart = lib.mkOverride 500 "always"; Restart = lib.mkOverride 500 "always";
RestartMaxDelaySec = lib.mkOverride 500 "1m"; RestartMaxDelaySec = lib.mkOverride 500 "1m";
@@ -126,10 +126,5 @@
"network.target" "network.target"
"sops-nix.service" "sops-nix.service"
]; ];
path = with pkgs; [
easytier
iproute2
bash
];
}; };
} }

View File

@@ -160,19 +160,16 @@ in
"Noto Serif CJK SC" "Noto Serif CJK SC"
"Noto Serif" "Noto Serif"
"Symbols Nerd Font" "Symbols Nerd Font"
"Noto Color Emoji"
]; ];
sansSerif = [ sansSerif = [
"Noto Sans CJK SC" "Noto Sans CJK SC"
"Noto Sans" "Noto Sans"
"Symbols Nerd Font" "Symbols Nerd Font"
"Noto Color Emoji"
]; ];
monospace = [ monospace = [
"JetBrains Mono" "JetBrains Mono"
"Noto Sans Mono CJK SC" "Noto Sans Mono CJK SC"
"Symbols Nerd Font Mono" "Symbols Nerd Font Mono"
"Noto Color Emoji"
]; ];
emoji = [ "Noto Color Emoji" ]; emoji = [ "Noto Color Emoji" ];
}; };
@@ -198,8 +195,6 @@ in
services.gvfs.enable = true; services.gvfs.enable = true;
virtualisation.waydroid.enable = true;
programs.wireshark.enable = true; programs.wireshark.enable = true;
programs.wireshark.package = pkgs.wireshark; programs.wireshark.package = pkgs.wireshark;
users.users.${username}.extraGroups = [ "wireshark" ]; users.users.${username}.extraGroups = [ "wireshark" ];

513
flake.lock generated
View File

@@ -81,7 +81,7 @@
"go-musicfox", "go-musicfox",
"devenv" "devenv"
], ],
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs_2"
}, },
"locked": { "locked": {
"lastModified": 1728672398, "lastModified": 1728672398,
@@ -98,6 +98,29 @@
"type": "github" "type": "github"
} }
}, },
"chaotic": {
"inputs": {
"flake-schemas": "flake-schemas",
"home-manager": "home-manager",
"jovian": "jovian",
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1752141190,
"narHash": "sha256-RHNq77Z84BtLTwyRtrBffm5V9006Dqw4vh3vrvULlxM=",
"owner": "chaotic-cx",
"repo": "nyx",
"rev": "ef0794b8e94eea166407141f7e92da75f6df925a",
"type": "github"
},
"original": {
"owner": "chaotic-cx",
"ref": "nyxpkgs-unstable",
"repo": "nyx",
"type": "github"
}
},
"darkly": { "darkly": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -105,11 +128,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1749134809, "lastModified": 1750940343,
"narHash": "sha256-1WErpDYTlMW/889Efe3OUM3uwt5w+EttjOGoBolBZvE=", "narHash": "sha256-qmc/jreM09MOwQ8dOa/+yyh99rU7TowSqo8L33VHfto=",
"owner": "Bali10050", "owner": "Bali10050",
"repo": "Darkly", "repo": "Darkly",
"rev": "c26d5e6a00c053850befd6c6af550797a5758dac", "rev": "77770c8d3c35f7ad39da2c57122c360096df0aac",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -124,7 +147,7 @@
"flake-compat": "flake-compat", "flake-compat": "flake-compat",
"git-hooks": "git-hooks", "git-hooks": "git-hooks",
"nix": "nix", "nix": "nix",
"nixpkgs": "nixpkgs_3" "nixpkgs": "nixpkgs_4"
}, },
"locked": { "locked": {
"lastModified": 1738772960, "lastModified": 1738772960,
@@ -148,11 +171,11 @@
"rust-analyzer-src": "rust-analyzer-src" "rust-analyzer-src": "rust-analyzer-src"
}, },
"locked": { "locked": {
"lastModified": 1749710537, "lastModified": 1752129689,
"narHash": "sha256-Jte1NonRzaKF6UpPL5FujKHVTVvc8CAIj8fK+X/0qVM=", "narHash": "sha256-0Xq5tZbvgZvxbbxv6kRHFuZE4Tq2za016NXh32nX0+Q=",
"owner": "nix-community", "owner": "nix-community",
"repo": "fenix", "repo": "fenix",
"rev": "b8fda10da7629d856086bbc1e21164c2d55691e3", "rev": "70bb04a7de606a75ba0a2ee9d47b99802780b35d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -209,21 +232,6 @@
"type": "github" "type": "github"
} }
}, },
"flake-compat_3": {
"locked": {
"lastModified": 1747046372,
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": { "flake-parts": {
"inputs": { "inputs": {
"nixpkgs-lib": [ "nixpkgs-lib": [
@@ -293,11 +301,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1743550720, "lastModified": 1751413152,
"narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", "narHash": "sha256-Tyw1RjYEsp5scoigs1384gIg6e0GoBVjms4aXFfRssQ=",
"owner": "hercules-ci", "owner": "hercules-ci",
"repo": "flake-parts", "repo": "flake-parts",
"rev": "c621e8422220273271f52058f618c94e405bb0f5", "rev": "77826244401ea9de6e3bac47c2db46005e1f30b5",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -321,6 +329,20 @@
"type": "github" "type": "github"
} }
}, },
"flake-schemas": {
"locked": {
"lastModified": 1721999734,
"narHash": "sha256-G5CxYeJVm4lcEtaO87LKzOsVnWeTcHGKbKxNamNWgOw=",
"rev": "0a5c42297d870156d9c57d8f99e476b738dcd982",
"revCount": 75,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/DeterminateSystems/flake-schemas/0.1.5/0190ef2f-61e0-794b-ba14-e82f225e55e6/source.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://flakehub.com/f/DeterminateSystems/flake-schemas/%3D0.1.5.tar.gz"
}
},
"flake-utils": { "flake-utils": {
"inputs": { "inputs": {
"systems": "systems" "systems": "systems"
@@ -339,24 +361,6 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"fromYaml": { "fromYaml": {
"flake": false, "flake": false,
"locked": { "locked": {
@@ -400,32 +404,6 @@
"type": "github" "type": "github"
} }
}, },
"git-hooks_2": {
"inputs": {
"flake-compat": [
"stylix",
"flake-compat"
],
"gitignore": "gitignore_2",
"nixpkgs": [
"stylix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1747372754,
"narHash": "sha256-2Y53NGIX2vxfie1rOW0Qb86vjRZ7ngizoo+bnXU9D9k=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": { "gitignore": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -449,41 +427,19 @@
"type": "github" "type": "github"
} }
}, },
"gitignore_2": {
"inputs": {
"nixpkgs": [
"stylix",
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"gnome-shell": { "gnome-shell": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1744584021, "lastModified": 1748186689,
"narHash": "sha256-0RJ4mJzf+klKF4Fuoc8VN8dpQQtZnKksFmR2jhWE1Ew=", "narHash": "sha256-UaD7Y9f8iuLBMGHXeJlRu6U1Ggw5B9JnkFs3enZlap0=",
"owner": "GNOME", "owner": "GNOME",
"repo": "gnome-shell", "repo": "gnome-shell",
"rev": "52c517c8f6c199a1d6f5118fae500ef69ea845ae", "rev": "8c88f917db0f1f0d80fa55206c863d3746fa18d0",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "GNOME", "owner": "GNOME",
"ref": "48.1", "ref": "48.2",
"repo": "gnome-shell", "repo": "gnome-shell",
"type": "github" "type": "github"
} }
@@ -515,23 +471,44 @@
"type": "github" "type": "github"
} }
}, },
"home-manager": { "haumea": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1749821119, "lastModified": 1685133229,
"narHash": "sha256-X3WAS322EsebI4ohJcXhKpiyG1v+7wE4VOiXy1pxM/c=", "narHash": "sha256-FePm/Gi9PBSNwiDFq3N+DWdfxFq0UKsVVTJS3cQPn94=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "haumea",
"rev": "79dfd9aa295e53773aad45480b44c131da29f35b", "rev": "34dd58385092a23018748b50f9b23de6266dffc2",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "v0.2.2",
"repo": "haumea",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"chaotic",
"nixpkgs"
]
},
"locked": {
"lastModified": 1751824240,
"narHash": "sha256-aDDC0CHTlL7QDKWWhdbEgVPK6KwWt+ca0QkmHYZxMzI=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "fd9e55f5fac45a26f6169310afca64d56b681935",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nix-community", "owner": "nix-community",
"ref": "master",
"repo": "home-manager", "repo": "home-manager",
"type": "github" "type": "github"
} }
@@ -539,20 +516,20 @@
"home-manager_2": { "home-manager_2": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
"stylix",
"nixpkgs" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1748737919, "lastModified": 1752202894,
"narHash": "sha256-5kvBbLYdp+n7Ftanjcs6Nv+UO6sBhelp6MIGJ9nWmjQ=", "narHash": "sha256-knafgng4gCjZIUMyAEWjxxdols6n/swkYnbWr+oF+1w=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "5675a9686851d9626560052a032c4e14e533c1fa", "rev": "fab659b346c0d4252208434c3c4b3983a4b38fec",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nix-community", "owner": "nix-community",
"ref": "master",
"repo": "home-manager", "repo": "home-manager",
"type": "github" "type": "github"
} }
@@ -609,6 +586,28 @@
"url": "https://codeberg.org/amjoseph/infuse.nix" "url": "https://codeberg.org/amjoseph/infuse.nix"
} }
}, },
"jovian": {
"inputs": {
"nix-github-actions": "nix-github-actions",
"nixpkgs": [
"chaotic",
"nixpkgs"
]
},
"locked": {
"lastModified": 1751529406,
"narHash": "sha256-jwKDHyUycp678zDYa5Hyfq3msO73YMXdZPxp96dU7po=",
"owner": "Jovian-Experiments",
"repo": "Jovian-NixOS",
"rev": "b2e5ce654e4f5bf8905c2e07a96dcf4966e6277d",
"type": "github"
},
"original": {
"owner": "Jovian-Experiments",
"repo": "Jovian-NixOS",
"type": "github"
}
},
"libgit2": { "libgit2": {
"flake": false, "flake": false,
"locked": { "locked": {
@@ -669,11 +668,11 @@
"xwayland-satellite-unstable": "xwayland-satellite-unstable" "xwayland-satellite-unstable": "xwayland-satellite-unstable"
}, },
"locked": { "locked": {
"lastModified": 1749801447, "lastModified": 1752078530,
"narHash": "sha256-cfrRFN9j340Wlgwe3k2oWB/0LI63JyUZab7apN72xd8=", "narHash": "sha256-TrRmlYdhWcadWvBpDjB9Xlry4uT4ZUIO46d+o5tjtCQ=",
"owner": "sodiboo", "owner": "sodiboo",
"repo": "niri-flake", "repo": "niri-flake",
"rev": "fba861e81d6fe8c0a8ba9fb2ed8d5e6df4a6ad78", "rev": "d231d92313192d4d0c78d6ef04167fed9dee87cf",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -685,16 +684,16 @@
"niri-stable": { "niri-stable": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1740117926, "lastModified": 1748151941,
"narHash": "sha256-mTTHA0RAaQcdYe+9A3Jx77cmmyLFHmRoZdd8RpWa+m8=", "narHash": "sha256-z4viQZLgC2bIJ3VrzQnR+q2F3gAOEQpU1H5xHtX/2fs=",
"owner": "YaLTeR", "owner": "YaLTeR",
"repo": "niri", "repo": "niri",
"rev": "b94a5db8790339cf9134873d8b490be69e02ac71", "rev": "8ba57fcf25d2fc9565131684a839d58703f1dae7",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "YaLTeR", "owner": "YaLTeR",
"ref": "v25.02", "ref": "v25.05.1",
"repo": "niri", "repo": "niri",
"type": "github" "type": "github"
} }
@@ -702,11 +701,11 @@
"niri-unstable": { "niri-unstable": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1749797708, "lastModified": 1750791124,
"narHash": "sha256-P5x0U6AW5Zn20bARv4D83d8XlNaWK1st9QwBfSe+Vfg=", "narHash": "sha256-F5iVU/hjoSHSSe0gllxm0PcAaseEtGNanYK5Ha3k2Tg=",
"owner": "YaLTeR", "owner": "YaLTeR",
"repo": "niri", "repo": "niri",
"rev": "f3f6e79eeca8924ff9cfea4b30006e5b782bc93e", "rev": "37458d94b288945f6cfbd3c5c233f634d59f246c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -723,7 +722,7 @@
], ],
"flake-parts": "flake-parts", "flake-parts": "flake-parts",
"libgit2": "libgit2", "libgit2": "libgit2",
"nixpkgs": "nixpkgs_2", "nixpkgs": "nixpkgs_3",
"nixpkgs-23-11": [ "nixpkgs-23-11": [
"go-musicfox", "go-musicfox",
"devenv" "devenv"
@@ -752,6 +751,29 @@
"type": "github" "type": "github"
} }
}, },
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"chaotic",
"jovian",
"nixpkgs"
]
},
"locked": {
"lastModified": 1729697500,
"narHash": "sha256-VFTWrbzDlZyFHHb1AlKRiD/qqCJIripXKiCSFS8fAOY=",
"owner": "zhaofengli",
"repo": "nix-github-actions",
"rev": "e418aeb728b6aa5ca8c5c71974e7159c2df1d8cf",
"type": "github"
},
"original": {
"owner": "zhaofengli",
"ref": "matrix-name",
"repo": "nix-github-actions",
"type": "github"
}
},
"nix2container": { "nix2container": {
"inputs": { "inputs": {
"flake-utils": "flake-utils", "flake-utils": "flake-utils",
@@ -782,11 +804,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1749574455, "lastModified": 1752199438,
"narHash": "sha256-fm2/8KPOYvvIAnNVtjDlTt/My00lIbZQ+LMrfQIWVzs=", "narHash": "sha256-xSBMmGtq8K4Qv80TMqREmESCAsRLJRHAbFH2T/2Bf1Y=",
"owner": "nix-community", "owner": "nix-community",
"repo": "NixOS-WSL", "repo": "NixOS-WSL",
"rev": "917af390377c573932d84b5e31dd9f2c1b5c0f09", "rev": "d34d9412556d3a896e294534ccd25f53b6822e80",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -797,11 +819,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1730531603, "lastModified": 1751984180,
"narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=", "narHash": "sha256-LwWRsENAZJKUdD3SpLluwDmdXY9F45ZEgCb0X+xgOL0=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "7ffd9ae656aec493492b44d0ddfb28e79a1ea25d", "rev": "9807714d6944a957c2e036f84b0ff8caf9930bc0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -825,11 +847,11 @@
}, },
"nixpkgs-master": { "nixpkgs-master": {
"locked": { "locked": {
"lastModified": 1749879625, "lastModified": 1752206449,
"narHash": "sha256-MtqGUE9dPX64saUYudgYxeH2yPSSnNlvPmyiKHISJ3M=", "narHash": "sha256-NVAbC/s4CupABWGXF8M9mDiVw/n0YCftxwc1KatVjDk=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "f117875f61620e81e0412d3f1d2ab7971d88912d", "rev": "1bd4d0d4a678d48b63eb18f457d74df2fcee6c69",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -841,27 +863,27 @@
}, },
"nixpkgs-stable": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1749866762, "lastModified": 1752203688,
"narHash": "sha256-WWUjx/6D+xmE6boM31L31nM/8csI79BuLgGytZHByz4=", "narHash": "sha256-uJ054F5PVGPu5SvLPMevhdY/EfK0X5DUyRtXhQYNUyo=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "6a06b272523a606c55f7bac29477a091c775d89b", "rev": "a70a12c75e13aa546c20ce0fe515de634d52c39e",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "nixos",
"ref": "release-24.11", "ref": "release-25.05",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
}, },
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1749809936, "lastModified": 1752124863,
"narHash": "sha256-WPGRaj7CKfZukjcpxiacp29uYfMl3S9zFiEsVFv/HWM=", "narHash": "sha256-5rWuf6RAlMDp/CAEuyYEz7ryxzgjxOCgUDhWEef864c=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "ec4c48ddcd5718cc1312f432b800fbbfe63ee2fe", "rev": "40de82b434526744da778ed53c742c1282d9e75e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -872,6 +894,22 @@
} }
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": {
"lastModified": 1730531603,
"narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7ffd9ae656aec493492b44d0ddfb28e79a1ea25d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1717432640, "lastModified": 1717432640,
"narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=",
@@ -887,7 +925,7 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_3": { "nixpkgs_4": {
"locked": { "locked": {
"lastModified": 1716977621, "lastModified": 1716977621,
"narHash": "sha256-Q1UQzYcMJH4RscmpTkjlgqQDX5yi1tZL0O345Ri6vXQ=", "narHash": "sha256-Q1UQzYcMJH4RscmpTkjlgqQDX5yi1tZL0O345Ri6vXQ=",
@@ -903,13 +941,13 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_4": { "nixpkgs_5": {
"locked": { "locked": {
"lastModified": 1749285348, "lastModified": 1751984180,
"narHash": "sha256-frdhQvPbmDYaScPFiCnfdh3B/Vh81Uuoo0w5TkWmmjU=", "narHash": "sha256-LwWRsENAZJKUdD3SpLluwDmdXY9F45ZEgCb0X+xgOL0=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "3e3afe5174c561dee0df6f2c2b2236990146329f", "rev": "9807714d6944a957c2e036f84b0ff8caf9930bc0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -922,15 +960,14 @@
"nur": { "nur": {
"inputs": { "inputs": {
"flake-parts": "flake-parts_3", "flake-parts": "flake-parts_3",
"nixpkgs": "nixpkgs_4", "nixpkgs": "nixpkgs_5"
"treefmt-nix": "treefmt-nix"
}, },
"locked": { "locked": {
"lastModified": 1749874339, "lastModified": 1752207112,
"narHash": "sha256-QKj0+WJm9LiZulDdQI8duXAckKVmj6952C9gww/flB0=", "narHash": "sha256-dnVoQSGQqEGJQzS6iHAG95c0oFrezzBinwu1bDLj9J4=",
"owner": "nix-community", "owner": "nix-community",
"repo": "NUR", "repo": "NUR",
"rev": "c70ec5f29a4642d6f412186a9f4d68f536089814", "rev": "f166dc14862dfec043f9545e8291cc4402f8b866",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -948,42 +985,19 @@
"nixpkgs": [ "nixpkgs": [
"stylix", "stylix",
"nixpkgs" "nixpkgs"
],
"treefmt-nix": "treefmt-nix_2"
},
"locked": {
"lastModified": 1748730660,
"narHash": "sha256-5LKmRYKdPuhm8j5GFe3AfrJL8dd8o57BQ34AGjJl1R0=",
"owner": "nix-community",
"repo": "NUR",
"rev": "2c0bc52fe14681e9ef60e3553888c4f086e46ecb",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "NUR",
"type": "github"
}
},
"omz": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": [
"nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1704103295, "lastModified": 1751906969,
"narHash": "sha256-BAwAKajpAUC78z0IMJt6LXGV8dLdUMYXe6CxbGA0JP0=", "narHash": "sha256-BSQAOdPnzdpOuCdAGSJmefSDlqmStFNScEnrWzSqKPw=",
"owner": "imxyy1soope1", "owner": "nix-community",
"repo": "omz", "repo": "NUR",
"rev": "e581a6d0d47291a3ddd7da5046bea59b29631a3f", "rev": "ddb679f4131e819efe3bbc6457ba19d7ad116f25",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "imxyy1soope1", "owner": "nix-community",
"ref": "master", "repo": "NUR",
"repo": "omz",
"type": "github" "type": "github"
} }
}, },
@@ -994,11 +1008,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1749772873, "lastModified": 1752146885,
"narHash": "sha256-ZsFQIs3ZpUud1QmR1TyhAW0LGbjHzCkA79YCLBbJ12A=", "narHash": "sha256-ZJK989GL+bTCQSxbG8v8/7tHMCEl/FPovkeDBNyClQE=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "517143adf97fb0df7e9a7584061deecdffb19faf", "rev": "d7079b75241c6e2b67f2429996fa7679ffc052e2",
"revCount": 576, "revCount": 616,
"type": "git", "type": "git",
"url": "https://git.outfoxxed.me/outfoxxed/quickshell" "url": "https://git.outfoxxed.me/outfoxxed/quickshell"
}, },
@@ -1009,10 +1023,12 @@
}, },
"root": { "root": {
"inputs": { "inputs": {
"chaotic": "chaotic",
"darkly": "darkly", "darkly": "darkly",
"fenix": "fenix", "fenix": "fenix",
"go-musicfox": "go-musicfox", "go-musicfox": "go-musicfox",
"home-manager": "home-manager", "haumea": "haumea",
"home-manager": "home-manager_2",
"impermanence": "impermanence", "impermanence": "impermanence",
"infuse": "infuse", "infuse": "infuse",
"niri": "niri", "niri": "niri",
@@ -1024,7 +1040,6 @@
"nixpkgs-stable": "nixpkgs-stable", "nixpkgs-stable": "nixpkgs-stable",
"nixpkgs-unstable": "nixpkgs-unstable", "nixpkgs-unstable": "nixpkgs-unstable",
"nur": "nur", "nur": "nur",
"omz": "omz",
"quickshell": "quickshell", "quickshell": "quickshell",
"sops-nix": "sops-nix", "sops-nix": "sops-nix",
"stylix": "stylix", "stylix": "stylix",
@@ -1034,11 +1049,11 @@
"rust-analyzer-src": { "rust-analyzer-src": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1749671345, "lastModified": 1752086493,
"narHash": "sha256-ewwoJOGE6sMnfXQkydmmjT6ixo1JetBZO0tDEENjOb8=", "narHash": "sha256-USpVUdiWXDfPoh+agbvoBQaBhg3ZdKZgHXo/HikMfVo=",
"owner": "rust-lang", "owner": "rust-lang",
"repo": "rust-analyzer", "repo": "rust-analyzer",
"rev": "5b2c8bc9ae90b4ad92dbeb7e52a7f5cbf5ba4d53", "rev": "6e3abe164b9036048dce1a3aa65a7e7e5200c0d3",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1048,6 +1063,27 @@
"type": "github" "type": "github"
} }
}, },
"rust-overlay": {
"inputs": {
"nixpkgs": [
"chaotic",
"nixpkgs"
]
},
"locked": {
"lastModified": 1751856221,
"narHash": "sha256-/QE1eV0ckFvgRMcKjZqgdJDoXFNwSMepwRoBjaw2MCk=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "34cae4b56929c5b340e1c5b10d9a98a425b2a51e",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"sops-nix": { "sops-nix": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -1055,11 +1091,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1749592509, "lastModified": 1751606940,
"narHash": "sha256-VunQzfZFA+Y6x3wYi2UE4DEQ8qKoAZZCnZPUlSoqC+A=", "narHash": "sha256-KrDPXobG7DFKTOteqdSVeL1bMVitDcy7otpVZWDE6MA=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "50754dfaa0e24e313c626900d44ef431f3210138", "rev": "3633fc4acf03f43b260244d94c71e9e14a2f6e0d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1075,16 +1111,13 @@
"base16-helix": "base16-helix", "base16-helix": "base16-helix",
"base16-vim": "base16-vim", "base16-vim": "base16-vim",
"firefox-gnome-theme": "firefox-gnome-theme", "firefox-gnome-theme": "firefox-gnome-theme",
"flake-compat": "flake-compat_3",
"flake-parts": "flake-parts_4", "flake-parts": "flake-parts_4",
"git-hooks": "git-hooks_2",
"gnome-shell": "gnome-shell", "gnome-shell": "gnome-shell",
"home-manager": "home-manager_2",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
"nur": "nur_2", "nur": "nur_2",
"systems": "systems_3", "systems": "systems_2",
"tinted-foot": "tinted-foot", "tinted-foot": "tinted-foot",
"tinted-kitty": "tinted-kitty", "tinted-kitty": "tinted-kitty",
"tinted-schemes": "tinted-schemes", "tinted-schemes": "tinted-schemes",
@@ -1092,11 +1125,11 @@
"tinted-zed": "tinted-zed" "tinted-zed": "tinted-zed"
}, },
"locked": { "locked": {
"lastModified": 1749824792, "lastModified": 1752201883,
"narHash": "sha256-fhEA3GngWkfktSI/7dLdlirgUS9nmXmJGisOs5ozTMw=", "narHash": "sha256-SZVbQ4YThvYU50cJ4W4GNMy7/rVOJI8qmXqbEcRNsug=",
"owner": "danth", "owner": "danth",
"repo": "stylix", "repo": "stylix",
"rev": "c79ad485612a0277c1e25a0bcc562eea11b563d8", "rev": "d395780b9c5c36f191b990b2021c71af180a1982",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1135,21 +1168,6 @@
"type": "github" "type": "github"
} }
}, },
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"tinted-foot": { "tinted-foot": {
"flake": false, "flake": false,
"locked": { "locked": {
@@ -1186,11 +1204,11 @@
"tinted-schemes": { "tinted-schemes": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1748180480, "lastModified": 1750770351,
"narHash": "sha256-7n0XiZiEHl2zRhDwZd/g+p38xwEoWtT0/aESwTMXWG4=", "narHash": "sha256-LI+BnRoFNRa2ffbe3dcuIRYAUcGklBx0+EcFxlHj0SY=",
"owner": "tinted-theming", "owner": "tinted-theming",
"repo": "schemes", "repo": "schemes",
"rev": "87d652edd26f5c0c99deda5ae13dfb8ece2ffe31", "rev": "5a775c6ffd6e6125947b393872cde95867d85a2a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1202,11 +1220,11 @@
"tinted-tmux": { "tinted-tmux": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1748740859, "lastModified": 1751159871,
"narHash": "sha256-OEM12bg7F4N5WjZOcV7FHJbqRI6jtCqL6u8FtPrlZz4=", "narHash": "sha256-UOHBN1fgHIEzvPmdNMHaDvdRMgLmEJh2hNmDrp3d3LE=",
"owner": "tinted-theming", "owner": "tinted-theming",
"repo": "tinted-tmux", "repo": "tinted-tmux",
"rev": "57d5f9683ff9a3b590643beeaf0364da819aedda", "rev": "bded5e24407cec9d01bd47a317d15b9223a1546c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1218,11 +1236,11 @@
"tinted-zed": { "tinted-zed": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1725758778, "lastModified": 1751158968,
"narHash": "sha256-8P1b6mJWyYcu36WRlSVbuj575QWIFZALZMTg5ID/sM4=", "narHash": "sha256-ksOyv7D3SRRtebpXxgpG4TK8gZSKFc4TIZpR+C98jX8=",
"owner": "tinted-theming", "owner": "tinted-theming",
"repo": "base16-zed", "repo": "base16-zed",
"rev": "122c9e5c0e6f27211361a04fae92df97940eccf9", "rev": "86a470d94204f7652b906ab0d378e4231a5b3384",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1231,62 +1249,19 @@
"type": "github" "type": "github"
} }
}, },
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"nur",
"nixpkgs"
]
},
"locked": {
"lastModified": 1733222881,
"narHash": "sha256-JIPcz1PrpXUCbaccEnrcUS8jjEb/1vJbZz5KkobyFdM=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "49717b5af6f80172275d47a418c9719a31a78b53",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
},
"treefmt-nix_2": {
"inputs": {
"nixpkgs": [
"stylix",
"nur",
"nixpkgs"
]
},
"locked": {
"lastModified": 1733222881,
"narHash": "sha256-JIPcz1PrpXUCbaccEnrcUS8jjEb/1vJbZz5KkobyFdM=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "49717b5af6f80172275d47a418c9719a31a78b53",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
},
"xwayland-satellite-stable": { "xwayland-satellite-stable": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1739246919, "lastModified": 1748488455,
"narHash": "sha256-/hBM43/Gd0/tW+egrhlWgOIISeJxEs2uAOIYVpfDKeU=", "narHash": "sha256-IiLr1alzKFIy5tGGpDlabQbe6LV1c9ABvkH6T5WmyRI=",
"owner": "Supreeeme", "owner": "Supreeeme",
"repo": "xwayland-satellite", "repo": "xwayland-satellite",
"rev": "44590a416d4a3e8220e19e29e0b6efe64a80315d", "rev": "3ba30b149f9eb2bbf42cf4758d2158ca8cceef73",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "Supreeeme", "owner": "Supreeeme",
"ref": "v0.5.1", "ref": "v0.6",
"repo": "xwayland-satellite", "repo": "xwayland-satellite",
"type": "github" "type": "github"
} }
@@ -1294,11 +1269,11 @@
"xwayland-satellite-unstable": { "xwayland-satellite-unstable": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1749315541, "lastModified": 1751228685,
"narHash": "sha256-bEik1BfVOFnWvtOrcOHluos/edJ8f+G2y1QySbt/0Ak=", "narHash": "sha256-MENtauGBhJ+kDeFaawvWGXaFG3Il6qQzjaP0RmtfM0k=",
"owner": "Supreeeme", "owner": "Supreeeme",
"repo": "xwayland-satellite", "repo": "xwayland-satellite",
"rev": "da2ecb5be816de35e2efe23a408a1c49fe8b11ba", "rev": "557ebeb616e03d5e4a8049862bbbd1f02c6f020b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1315,11 +1290,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1749875058, "lastModified": 1752164817,
"narHash": "sha256-LGeVwJLNJ+QPsuQMGsm5atAkFZgrRG3t62bB0+loOi4=", "narHash": "sha256-LJFIx27IOUowLsJn5wci9mHZ4CesJsiAivQWDjnZPCc=",
"owner": "0xc000022070", "owner": "0xc000022070",
"repo": "zen-browser-flake", "repo": "zen-browser-flake",
"rev": "12fbcbb395776b50a848f87434bb786ef4f09b9d", "rev": "9193992c4c2c4349b4280ec2b49648cae208fe63",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -4,10 +4,14 @@
inputs = { inputs = {
# Nixpkgs # Nixpkgs
nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable-small"; nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable-small";
nixpkgs-stable.url = "github:nixos/nixpkgs/release-24.11"; nixpkgs-stable.url = "github:nixos/nixpkgs/release-25.05";
nixpkgs-master.url = "github:nixos/nixpkgs/master"; nixpkgs-master.url = "github:nixos/nixpkgs/master";
# nixpkgs.follows = "nixpkgs-stable"; # nixpkgs.follows = "nixpkgs-stable";
nixpkgs.follows = "nixpkgs-unstable"; nixpkgs.follows = "nixpkgs-unstable";
# nixpkgs.follows = "nixpkgs-master";
# Nyxpkgs
chaotic.url = "github:chaotic-cx/nyx/nyxpkgs-unstable";
# SOPS # SOPS
sops-nix.url = "github:Mic92/sops-nix"; sops-nix.url = "github:Mic92/sops-nix";
@@ -23,10 +27,6 @@
# NUR # NUR
nur.url = "github:nix-community/NUR"; nur.url = "github:nix-community/NUR";
# OMZ
omz.url = "github:imxyy1soope1/omz/master";
omz.inputs.nixpkgs.follows = "nixpkgs";
# Niri # Niri
niri.url = "github:sodiboo/niri-flake"; niri.url = "github:sodiboo/niri-flake";
niri.inputs.nixpkgs.follows = "nixpkgs"; niri.inputs.nixpkgs.follows = "nixpkgs";
@@ -57,6 +57,9 @@
infuse.url = "git+https://codeberg.org/amjoseph/infuse.nix"; infuse.url = "git+https://codeberg.org/amjoseph/infuse.nix";
infuse.flake = false; infuse.flake = false;
haumea.url = "github:nix-community/haumea/v0.2.2";
haumea.inputs.nixpkgs.follows = "nixpkgs";
}; };
outputs = outputs =
@@ -77,17 +80,29 @@
}) (builtins.attrNames (builtins.readDir ./config/hosts)) }) (builtins.attrNames (builtins.readDir ./config/hosts))
); );
lib = nixpkgs.lib.extend ( lib = (import ./lib/stdlib-extended.nix nixpkgs.lib).extend (
final: prev: { final: prev: {
inherit (inputs.home-manager.lib) hm; inherit (inputs.home-manager.lib) hm;
inherit infuse; inherit infuse;
my = import ./lib { lib = final; }; haumea = inputs.haumea.lib;
} }
); );
infuse = (import inputs.infuse { inherit (nixpkgs) lib; }).v1.infuse; infuse = (import inputs.infuse { inherit (nixpkgs) lib; }).v1.infuse;
in in
{ {
packages = forAllSystems (system: import ./pkgs nixpkgs.legacyPackages.${system}); packages = forAllSystems (
system:
lib.haumea.load {
src = ./pkgs;
loader = [
{
matches = str: builtins.match ".*\\.nix" str != null;
loader = _: path: nixpkgs.legacyPackages.${system}.callPackage path { };
}
];
transformer = lib.haumea.transformers.liftDefault;
}
);
# workaround for "treefmt warning" # workaround for "treefmt warning"
formatter = forAllSystems ( formatter = forAllSystems (
@@ -109,14 +124,15 @@
} }
); );
overlays = import ./overlays { inherit inputs infuse; }; overlays = import ./overlays {
inherit inputs lib;
};
nixosConfigurations = forAllHosts ( nixosConfigurations = forAllHosts (
hostname: hostname:
let let
overlays = builtins.attrValues self.overlays ++ [ overlays = builtins.attrValues self.overlays ++ [
inputs.go-musicfox.overlays.default inputs.go-musicfox.overlays.default
inputs.omz.overlays.default
inputs.niri.overlays.niri inputs.niri.overlays.niri
inputs.fenix.overlays.default inputs.fenix.overlays.default
(final: prev: { (final: prev: {
@@ -128,7 +144,7 @@
withJemalloc = true; withJemalloc = true;
withQtSvg = true; withQtSvg = true;
withWayland = true; withWayland = true;
withPipewire = false; withPipewire = true;
withPam = false; withPam = false;
withX11 = false; withX11 = false;
withHyprland = false; withHyprland = false;
@@ -157,7 +173,7 @@
}; };
}; };
pkgsConf.nixpkgs = { pkgsConf.nixpkgs = {
overlays = lib.mkForce overlays; inherit overlays;
config.allowUnfree = true; config.allowUnfree = true;
flake.setNixPath = false; flake.setNixPath = false;
}; };
@@ -169,13 +185,23 @@
outputs outputs
hostname hostname
; ;
sopsRoot = ./secrets; sopsRoot = ./secrets;
flake = ./.;
} // vars; } // vars;
modules = [ modules =
./modules (lib.umport {
paths = [ ./modules ];
exclude = [
./modules/virt/types
./modules/desktop/wm/niri/waybar
];
recursive = true;
})
++ [
(lib.mkAliasOptionModule [ "my" "home" ] [ "home-manager" "users" vars.username ])
./config/base.nix ./config/base.nix
./config/hosts/${hostname} ./config/hosts/${hostname}
inputs.chaotic.nixosModules.default
inputs.sops-nix.nixosModules.sops inputs.sops-nix.nixosModules.sops
inputs.impermanence.nixosModules.impermanence inputs.impermanence.nixosModules.impermanence
inputs.home-manager.nixosModules.default inputs.home-manager.nixosModules.default

View File

@@ -9,5 +9,6 @@ in
stdlib.extend ( stdlib.extend (
self: super: { self: super: {
my = mkMyLib { lib = self; }; my = mkMyLib { lib = self; };
umport = import ./umport.nix { lib = self; };
} }
) )

48
lib/umport.nix Normal file
View File

@@ -0,0 +1,48 @@
# This function is modified from:
# https://github.com/yunfachi/nypkgs/blob/master/lib/umport.nix
#
# !!! REMOVING THIS NOTICE VIOLATES THE MIT LICENSE OF THE UMPORT PROJECT !!!
# This notice must be retained in all copies of this function, including modified versions!
# The MIT License can be found here:
# https://github.com/yunfachi/nypkgs/blob/master/LICENSE
{ lib, ... }:
let
umport =
{
path ? null,
paths ? [ ],
include ? [ ],
exclude ? [ ],
recursive ? true,
}:
with lib;
with fileset;
let
excludedFiles = filter (path: pathIsRegularFile path) exclude;
excludedDirs = filter (path: pathIsDirectory path) exclude;
isExcluded =
path:
if elem path excludedFiles then
true
else
(filter (excludedDir: lib.path.hasPrefix excludedDir path) excludedDirs) != [ ];
in
unique (
(filter
(file: pathIsRegularFile file && hasSuffix ".nix" (builtins.toString file) && !isExcluded file)
(
concatMap (
_path:
if recursive then
toList _path
else
mapAttrsToList (
name: type: _path + (if type == "directory" then "/${name}/default.nix" else "/${name}")
) (builtins.readDir _path)
) (unique (if path == null then paths else [ path ] ++ paths))
)
)
++ (if recursive then concatMap (path: toList path) (unique include) else unique include)
);
in
umport

View File

@@ -12,6 +12,7 @@ lib.my.makeSwitch {
misc.enable = true; misc.enable = true;
monitor.all.enable = true; monitor.all.enable = true;
shell.all.enable = true; shell.all.enable = true;
vcs.all.enable = true;
}; };
}; };
} }

View File

@@ -1,9 +0,0 @@
{
imports = [
./all.nix
./media
./misc
./monitor
./shell
];
}

View File

@@ -1,9 +0,0 @@
{
imports = [
./all.nix
./ffmpeg.nix
./mpd
./cava
./go-musicfox
];
}

View File

@@ -23,6 +23,13 @@ lib.my.makeSwitch {
}; };
cli.media.mpd.enable = true; cli.media.mpd.enable = true;
persist.homeDirs = [
".config/go-musicfox/db"
];
persist.homeFiles = [
".config/go-musicfox/cookie"
];
}; };
}; };
} }

View File

@@ -14,12 +14,15 @@ lib.my.makeSwitch {
]; ];
config' = { config' = {
my.home = { my.home = {
home.packages = with pkgs; [ home.packages = with pkgs.stable; [
mpd mpd
mpc-cli mpc-cli
]; ];
services.mpris-proxy.enable = true; services.mpris-proxy.enable = true;
xdg.configFile."mpd/mpd.conf".source = ./mpd.conf; xdg.configFile."mpd/mpd.conf".source = ./mpd.conf;
}; };
my.persist.homeFiles = [
".config/mpd/mpd.db"
];
}; };
} }

85
modules/cli/misc.nix Normal file
View File

@@ -0,0 +1,85 @@
{
config,
lib,
pkgs,
username,
userfullname,
useremail,
...
}:
lib.my.makeSwitch {
inherit config;
default = true;
optionName = "misc command line tools";
optionPath = [
"cli"
"misc"
];
config' = {
environment.systemPackages = with pkgs; [
vim
wget
git
file
gnused
gnutar
zip
unzip
xz
p7zip
unrar-free
pciutils
usbutils
lsof
nmap
traceroute
tcping-go
dnsutils
killall
];
programs.dconf.enable = true;
my.home = {
home.packages = with pkgs; [
lsd
fd
neofetch
fzf
bat
ripgrep
aria2
socat
];
programs.tmux = {
enable = true;
extraConfig = "set-option -g mouse on";
plugins = [
(pkgs.tmuxPlugins.mkTmuxPlugin {
pluginName = "tokyo-night-tmux";
rtpFilePath = "tokyo-night.tmux";
version = "legacy";
src = pkgs.fetchFromGitHub {
owner = "janoamaral";
repo = "tokyo-night-tmux";
rev = "16469dfad86846138f594ceec780db27039c06cd";
hash = "sha256-EKCgYan0WayXnkSb2fDJxookdBLW0XBKi2hf/YISwJE=";
};
})
];
};
programs.tealdeer = {
enable = true;
enableAutoUpdates = true;
settings.updates.auto_update = true;
};
};
};
}

View File

@@ -1,9 +0,0 @@
set-option -g mouse on
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin "janoamaral/tokyo-night-tmux#legacy"
# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
run '~/.config/tmux/plugins/tpm/tpm'

View File

@@ -1,6 +0,0 @@
{
imports = [
./all.nix
./btop
];
}

View File

@@ -1,6 +0,0 @@
{
imports = [
./all.nix
./zsh.nix
];
}

View File

@@ -0,0 +1,190 @@
[aws]
symbol = " "
[buf]
symbol = " "
[bun]
symbol = " "
[c]
symbol = " "
[cpp]
symbol = " "
[cmake]
symbol = " "
[conda]
symbol = " "
[crystal]
symbol = " "
[dart]
symbol = " "
[deno]
symbol = " "
[directory]
read_only = " 󰌾"
[docker_context]
symbol = " "
[elixir]
symbol = " "
[elm]
symbol = " "
[fennel]
symbol = " "
[fossil_branch]
symbol = " "
[gcloud]
symbol = " "
[git_branch]
symbol = " "
[git_commit]
tag_symbol = '  '
[golang]
symbol = " "
[guix_shell]
symbol = " "
[haskell]
symbol = " "
[haxe]
symbol = " "
[hg_branch]
symbol = " "
[hostname]
ssh_symbol = " "
[java]
symbol = " "
[julia]
symbol = " "
[kotlin]
symbol = " "
[lua]
symbol = " "
[memory_usage]
symbol = "󰍛 "
[meson]
symbol = "󰔷 "
[nim]
symbol = "󰆥 "
[nix_shell]
symbol = " "
[nodejs]
symbol = " "
[ocaml]
symbol = " "
[os.symbols]
Alpaquita = " "
Alpine = " "
AlmaLinux = " "
Amazon = " "
Android = " "
Arch = " "
Artix = " "
CachyOS = " "
CentOS = " "
Debian = " "
DragonFly = " "
Emscripten = " "
EndeavourOS = " "
Fedora = " "
FreeBSD = " "
Garuda = "󰛓 "
Gentoo = " "
HardenedBSD = "󰞌 "
Illumos = "󰈸 "
Kali = " "
Linux = " "
Mabox = " "
Macos = " "
Manjaro = " "
Mariner = " "
MidnightBSD = " "
Mint = " "
NetBSD = " "
NixOS = " "
Nobara = " "
OpenBSD = "󰈺 "
openSUSE = " "
OracleLinux = "󰌷 "
Pop = " "
Raspbian = " "
Redhat = " "
RedHatEnterprise = " "
RockyLinux = " "
Redox = "󰀘 "
Solus = "󰠳 "
SUSE = " "
Ubuntu = " "
Unknown = " "
Void = " "
Windows = "󰍲 "
[package]
symbol = "󰏗 "
[perl]
symbol = " "
[php]
symbol = " "
[pijul_channel]
symbol = " "
[pixi]
symbol = "󰏗 "
[python]
symbol = " "
[rlang]
symbol = "󰟔 "
[ruby]
symbol = " "
[rust]
symbol = "󱘗 "
[scala]
symbol = " "
[swift]
symbol = " "
[zig]
symbol = " "
[gradle]
symbol = " "

View File

@@ -14,12 +14,78 @@ lib.my.makeSwitch {
"zsh" "zsh"
]; ];
config' = { config' = {
my.persist.homeDirs = [ ".local/share/zoxide" ];
my.home = my.home =
let let
stateHome = config.my.home.xdg.stateHome; stateHome = config.my.home.xdg.stateHome;
zsh-syntax-highlighting = pkgs.fetchFromGitHub {
owner = "zsh-users";
repo = "zsh-syntax-highlighting";
rev = "0.8.0";
hash = "sha256-iJdWopZwHpSyYl5/FQXEW7gl/SrKaYDEtTH9cGP7iPo=";
};
fzf-tab = pkgs.fetchFromGitHub {
owner = "Aloxaf";
repo = "fzf-tab";
rev = "v1.2.0";
hash = "sha256-q26XVS/LcyZPRqDNwKKA9exgBByE0muyuNb0Bbar2lY=";
};
in in
{ {
home.packages = [ pkgs.omz ]; home.packages = with pkgs; [
fzf
zoxide
];
programs.starship = {
enable = true;
settings = lib.recursiveUpdate (with builtins; fromTOML (readFile ./starship-preset.toml)) {
add_newline = false;
custom = {
jj = {
ignore_timeout = true;
description = "The current jj status";
when = "jj root";
symbol = " ";
command = ''
jj log --revisions @ --no-graph --ignore-working-copy --color always --limit 1 --template '
separate(" ",
change_id.shortest(4),
bookmarks,
"|",
concat(
if(conflict, "💥"),
if(divergent, "🚧"),
if(hidden, "👻"),
if(immutable, "🔒"),
),
raw_escape_sequence("\x1b[1;32m") ++ if(empty, "(empty)"),
raw_escape_sequence("\x1b[1;32m") ++ coalesce(
truncate_end(29, description.first_line(), ""),
"(no description set)",
) ++ raw_escape_sequence("\x1b[0m"),
)
'
'';
};
git_branch = {
when = true;
command = "jj root >/dev/null 2>&1 || starship module git_branch";
description = "Only show git_branch if we're not in a jj repo";
};
git_status = {
when = true;
command = "jj root >/dev/null 2>&1 || starship module git_status";
description = "Only show git_status if we're not in a jj repo";
};
};
git_state.disabled = true;
git_commit.disabled = true;
git_metrics.disabled = true;
git_branch.disabled = true;
git_status.disabled = true;
nix_shell.disabled = true;
};
};
programs.zsh = { programs.zsh = {
enable = true; enable = true;
dotDir = ".config/zsh"; dotDir = ".config/zsh";
@@ -29,14 +95,26 @@ lib.my.makeSwitch {
"la" "la"
]; ];
}; };
initContent = '' initContent = lib.mkAfter ''
source ${pkgs.omz}/share/omz/omz.zsh source ${fzf-tab}/fzf-tab.plugin.zsh
eval "$(zoxide init zsh)"
source ${zsh-syntax-highlighting}/zsh-syntax-highlighting.plugin.zsh
source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh
''; '';
sessionVariables = { oh-my-zsh = {
_ZL_DATA = "${stateHome}/zlua"; enable = true;
_FZF_HISTORY = "${stateHome}/fzf_history"; theme = "gentoo";
plugins = [
"git"
"git-extras"
"extract"
"sudo"
"dotenv"
];
}; };
shellAliases = { shellAliases = {
x = "extract";
ls = "lsd"; ls = "lsd";
svim = "sudoedit"; svim = "sudoedit";
nf = "neofetch"; nf = "neofetch";

16
modules/cli/vcs/all.nix Normal file
View File

@@ -0,0 +1,16 @@
{ config, lib, ... }:
lib.my.makeSwitch {
inherit config;
optionName = "all command line tools";
optionPath = [
"cli"
"vcs"
"all"
];
config' = {
my.cli.vcs = {
git.enable = true;
jj.enable = true;
};
};
}

View File

@@ -7,50 +7,17 @@
useremail, useremail,
... ...
}: }:
lib.my.makeSwitch { lib.my.makeHomeProgramConfig {
inherit config; inherit config;
default = true; programName = "git";
optionName = "misc command line tools";
optionPath = [ optionPath = [
"cli" "cli"
"misc" "vcs"
"git"
]; ];
config' = { extraConfig = {
environment.systemPackages = with pkgs; [
vim
wget
git
file
gnused
gnutar
zip
unzip
xz
p7zip
unrar-free
pciutils
usbutils
lsof
nmap
traceroute
tcping-go
dnsutils
killall
];
programs.zsh.enable = true;
programs.dconf.enable = true;
my.home = { my.home = {
programs.home-manager.enable = true;
programs.git = { programs.git = {
enable = true;
userName = "${userfullname}"; userName = "${userfullname}";
userEmail = "${useremail}"; userEmail = "${useremail}";
signing = { signing = {
@@ -70,31 +37,6 @@ lib.my.makeSwitch {
programs.lazygit = { programs.lazygit = {
enable = true; enable = true;
}; };
home.packages = with pkgs; [
lsd
fd
neofetch
fzf
bat
ripgrep
aria2
socat
nix-output-monitor
tmux
trash-cli
cht-sh
dooit
# translate-shell
];
xdg.configFile."tmux/tmux.conf".source = ./tmux.conf;
}; };
}; };
} }

45
modules/cli/vcs/jj.nix Normal file
View File

@@ -0,0 +1,45 @@
{
config,
lib,
pkgs,
username,
userfullname,
useremail,
...
}:
lib.my.makeHomeProgramConfig {
inherit config;
programName = "jujutsu";
optionPath = [
"cli"
"vcs"
"jj"
];
extraConfig = {
my.home = {
programs.jujutsu = {
settings = {
user = {
name = "${userfullname}";
email = "${useremail}";
};
ui = {
graph.style = "square";
default-command = "status";
};
signing = {
backend = "ssh";
behavior = "own";
key = "/home/${username}/.ssh/id_ed25519";
backends.backends.ssh.allowed-signers =
(pkgs.writeText "allowed_signers" ''
imxyy1soope1@gmail.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOEFLUkyeaK8ZPPZdVNEmtx8zvoxi7xqS2Z6oxRBuUPO imxyy@imxyy-nix
imxyy@imxyy.top ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOEFLUkyeaK8ZPPZdVNEmtx8zvoxi7xqS2Z6oxRBuUPO imxyy@imxyy-nix
'').outPath;
};
};
};
home.packages = [ pkgs.lazyjj ];
};
};
}

View File

@@ -1,8 +0,0 @@
{
imports = [
./all.nix
./misc.nix
./langs
./editor
];
}

View File

@@ -11,6 +11,7 @@ lib.my.makeSwitch {
my.coding.editor = { my.coding.editor = {
neovim.enable = true; neovim.enable = true;
vscode.enable = true; vscode.enable = true;
zed.enable = true;
}; };
}; };
} }

View File

@@ -1,7 +0,0 @@
{
imports = [
./all.nix
./neovim
./vscode
];
}

View File

@@ -54,5 +54,8 @@ lib.my.makeHomeProgramConfig {
]; ];
}; };
}; };
my.persist.homeDirs = [
".local/share/nvim"
];
}; };
} }

View File

@@ -62,6 +62,9 @@ local extra_config = {
}, },
}, },
}, },
qmlls = {
cmd = {"qmlls", "-E"}
}
} }
local capabilities = require("cmp_nvim_lsp").default_capabilities() local capabilities = require("cmp_nvim_lsp").default_capabilities()

View File

@@ -179,6 +179,23 @@ local plugins = {
require("telescope").setup(require("plugins.telescope")) require("telescope").setup(require("plugins.telescope"))
end, end,
}, },
{
"ggandor/leap.nvim",
dependencies = { "tpope/vim-repeat" },
config = function()
require("leap").set_default_mappings()
-- Exclude whitespace and the middle of alphabetic words from preview:
-- foobar[baaz] = quux
-- ^----^^^--^^-^-^--^
require('leap').opts.preview_filter = function(ch0, ch1, ch2)
return not (
ch1:match('%s') or
ch0:match('%a') and ch1:match('%a') and ch2:match('%a')
)
end
require('leap.user').set_repeat_keys('<enter>', '<backspace>')
end
},
{ {
"alexghergh/nvim-tmux-navigation", "alexghergh/nvim-tmux-navigation",
event = "VeryLazy", event = "VeryLazy",
@@ -189,6 +206,7 @@ local plugins = {
{ {
"MeanderingProgrammer/render-markdown.nvim", "MeanderingProgrammer/render-markdown.nvim",
dependencies = { "nvim-treesitter/nvim-treesitter", "nvim-tree/nvim-web-devicons" }, dependencies = { "nvim-treesitter/nvim-treesitter", "nvim-tree/nvim-web-devicons" },
event = "BufEnter *.md",
opts = {}, opts = {},
}, },
{ {

View File

@@ -0,0 +1,20 @@
{
config,
lib,
...
}:
lib.my.makeHomeProgramConfig {
inherit config;
programName = "zed-editor";
optionPath = [
"coding"
"editor"
"zed"
];
extraConfig = {
my.persist.homeDirs = [
".config/zed"
".local/share/zed"
];
};
}

View File

@@ -1,205 +0,0 @@
#compdef gh
# zsh completion for gh -*- shell-script -*-
__gh_debug()
{
local file="$BASH_COMP_DEBUG_FILE"
if [[ -n ${file} ]]; then
echo "$*" >> "${file}"
fi
}
_gh()
{
local shellCompDirectiveError=1
local shellCompDirectiveNoSpace=2
local shellCompDirectiveNoFileComp=4
local shellCompDirectiveFilterFileExt=8
local shellCompDirectiveFilterDirs=16
local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace
local -a completions
__gh_debug "\n========= starting completion logic =========="
__gh_debug "CURRENT: ${CURRENT}, words[*]: ${words[*]}"
# The user could have moved the cursor backwards on the command-line.
# We need to trigger completion from the $CURRENT location, so we need
# to truncate the command-line ($words) up to the $CURRENT location.
# (We cannot use $CURSOR as its value does not work when a command is an alias.)
words=("${=words[1,CURRENT]}")
__gh_debug "Truncated words[*]: ${words[*]},"
lastParam=${words[-1]}
lastChar=${lastParam[-1]}
__gh_debug "lastParam: ${lastParam}, lastChar: ${lastChar}"
# For zsh, when completing a flag with an = (e.g., gh -n=<TAB>)
# completions must be prefixed with the flag
setopt local_options BASH_REMATCH
if [[ "${lastParam}" =~ '-.*=' ]]; then
# We are dealing with a flag with an =
flagPrefix="-P ${BASH_REMATCH}"
fi
# Prepare the command to obtain completions
requestComp="${words[1]} __complete ${words[2,-1]}"
if [ "${lastChar}" = "" ]; then
# If the last parameter is complete (there is a space following it)
# We add an extra empty parameter so we can indicate this to the go completion code.
__gh_debug "Adding extra empty parameter"
requestComp="${requestComp} \"\""
fi
__gh_debug "About to call: eval ${requestComp}"
# Use eval to handle any environment variables and such
out=$(eval ${requestComp} 2>/dev/null)
__gh_debug "completion output: ${out}"
# Extract the directive integer following a : from the last line
local lastLine
while IFS='\n' read -r line; do
lastLine=${line}
done < <(printf "%s\n" "${out[@]}")
__gh_debug "last line: ${lastLine}"
if [ "${lastLine[1]}" = : ]; then
directive=${lastLine[2,-1]}
# Remove the directive including the : and the newline
local suffix
(( suffix=${#lastLine}+2))
out=${out[1,-$suffix]}
else
# There is no directive specified. Leave $out as is.
__gh_debug "No directive found. Setting do default"
directive=0
fi
__gh_debug "directive: ${directive}"
__gh_debug "completions: ${out}"
__gh_debug "flagPrefix: ${flagPrefix}"
if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
__gh_debug "Completion received error. Ignoring completions."
return
fi
local activeHelpMarker="_activeHelp_ "
local endIndex=${#activeHelpMarker}
local startIndex=$((${#activeHelpMarker}+1))
local hasActiveHelp=0
while IFS='\n' read -r comp; do
# Check if this is an activeHelp statement (i.e., prefixed with $activeHelpMarker)
if [ "${comp[1,$endIndex]}" = "$activeHelpMarker" ];then
__gh_debug "ActiveHelp found: $comp"
comp="${comp[$startIndex,-1]}"
if [ -n "$comp" ]; then
compadd -x "${comp}"
__gh_debug "ActiveHelp will need delimiter"
hasActiveHelp=1
fi
continue
fi
if [ -n "$comp" ]; then
# If requested, completions are returned with a description.
# The description is preceded by a TAB character.
# For zsh's _describe, we need to use a : instead of a TAB.
# We first need to escape any : as part of the completion itself.
comp=${comp//:/\\:}
local tab="$(printf '\t')"
comp=${comp//$tab/:}
__gh_debug "Adding completion: ${comp}"
completions+=${comp}
lastComp=$comp
fi
done < <(printf "%s\n" "${out[@]}")
# Add a delimiter after the activeHelp statements, but only if:
# - there are completions following the activeHelp statements, or
# - file completion will be performed (so there will be choices after the activeHelp)
if [ $hasActiveHelp -eq 1 ]; then
if [ ${#completions} -ne 0 ] || [ $((directive & shellCompDirectiveNoFileComp)) -eq 0 ]; then
__gh_debug "Adding activeHelp delimiter"
compadd -x "--"
hasActiveHelp=0
fi
fi
if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
__gh_debug "Activating nospace."
noSpace="-S ''"
fi
if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
# File extension filtering
local filteringCmd
filteringCmd='_files'
for filter in ${completions[@]}; do
if [ ${filter[1]} != '*' ]; then
# zsh requires a glob pattern to do file filtering
filter="\*.$filter"
fi
filteringCmd+=" -g $filter"
done
filteringCmd+=" ${flagPrefix}"
__gh_debug "File filtering command: $filteringCmd"
_arguments '*:filename:'"$filteringCmd"
elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
# File completion for directories only
local subdir
subdir="${completions[1]}"
if [ -n "$subdir" ]; then
__gh_debug "Listing directories in $subdir"
pushd "${subdir}" >/dev/null 2>&1
else
__gh_debug "Listing directories in ."
fi
local result
_arguments '*:dirname:_files -/'" ${flagPrefix}"
result=$?
if [ -n "$subdir" ]; then
popd >/dev/null 2>&1
fi
return $result
else
__gh_debug "Calling _describe"
if eval _describe "completions" completions $flagPrefix $noSpace; then
__gh_debug "_describe found some completions"
# Return the success of having called _describe
return 0
else
__gh_debug "_describe did not find completions."
__gh_debug "Checking if we should do file completion."
if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
__gh_debug "deactivating file completion"
# We must return an error code here to let zsh know that there were no
# completions found by _describe; this is what will trigger other
# matching algorithms to attempt to find completions.
# For example zsh can match letters in the middle of words.
return 1
else
# Perform file completion
__gh_debug "Activating file completion"
# We must return the result of this command, so it must be the
# last command, or else we must store its result to return it.
_arguments '*:filename:_files'" ${flagPrefix}"
fi
fi
fi
}
# don't run the completion function when being source-ed or eval-ed
if [ "$funcstack[1]" = "_gh" ]; then
_gh
fi

View File

@@ -15,6 +15,7 @@ lib.my.makeSwitch {
python.enable = true; python.enable = true;
rust.enable = true; rust.enable = true;
lua.enable = true; lua.enable = true;
qml.enable = true;
}; };
}; };
} }

View File

@@ -1,11 +0,0 @@
{
imports = [
./all.nix
./c.nix
./go.nix
./js.nix
./rust.nix
./python.nix
./lua.nix
];
}

View File

@@ -24,6 +24,9 @@ lib.my.makeSwitch {
prefix = ''${HOME}/.npm-global prefix = ''${HOME}/.npm-global
registry = https://registry.npmmirror.com registry = https://registry.npmmirror.com
''; '';
programs.zsh.initContent = lib.mkAfter ''
export PATH=$PATH:$HOME/.npm-global/bin
'';
}; };
my.persist.homeDirs = [ my.persist.homeDirs = [
".npm" ".npm"

View File

@@ -0,0 +1,20 @@
{
config,
lib,
pkgs,
...
}:
lib.my.makeSwitch {
inherit config;
optionName = "QML";
optionPath = [
"coding"
"langs"
"qml"
];
config' = {
my.home.home.packages = with pkgs; [
kdePackages.qtdeclarative
];
};
}

View File

@@ -17,9 +17,6 @@ lib.my.makeSwitch {
gnumake gnumake
github-cli # gh github-cli # gh
]; ];
programs.zsh.initContent = ''
source ${./github-cli-comp}
'';
programs.direnv.enable = true; programs.direnv.enable = true;
}; };
my.persist.homeDirs = [ my.persist.homeDirs = [

View File

@@ -1,24 +0,0 @@
{
lib,
username,
...
}:
{
imports = [
./cli
./coding
./virt
./desktop
./i18n
./nix.nix
./sops.nix
./gpg.nix
./time.nix
./user.nix
./xdg.nix
./persist.nix
./getty-autologin.nix
(lib.mkAliasOptionModule [ "my" "home" ] [ "home-manager" "users" username ])
];
}

View File

@@ -17,6 +17,7 @@ lib.my.makeSwitch {
wm.all.enable = true; wm.all.enable = true;
style.enable = true; style.enable = true;
quickshell.enable = true; quickshell.enable = true;
wine.enable = true;
}; };
}; };
} }

View File

@@ -1,9 +0,0 @@
{
imports = [
./all.nix
./firefox.nix
./librewolf.nix
./chromium.nix
./zen.nix
];
}

View File

@@ -1,14 +0,0 @@
{
imports = [
./all.nix
./browser
./gaming
./media
./notify
./screencast
./terminal
./wm
./style
./quickshell
];
}

View File

@@ -1,7 +0,0 @@
{
imports = [
./all.nix
./minecraft.nix
./steam.nix
];
}

View File

@@ -23,5 +23,8 @@ lib.my.makeSwitch {
".minecraft" ".minecraft"
".local/share/hmcl" ".local/share/hmcl"
]; ];
my.persist.homeFiles = [
".hmcl.json"
];
}; };
} }

View File

@@ -20,5 +20,8 @@ lib.my.makeSwitch {
gamescope gamescope
]; ];
}; };
my.persist.homeDirs = [
".local/share/Steam"
];
}; };
} }

View File

@@ -1,11 +0,0 @@
{
imports = [
./all.nix
./mpv.nix
./shotwell.nix
./thunderbird.nix
./vlc.nix
./spotify.nix
./spotube.nix
];
}

View File

@@ -13,4 +13,9 @@ lib.my.makeHomePackageConfig {
"media" "media"
"spotube" "spotube"
]; ];
extraConfig = {
my.persist.homeDirs = [
".local/share/oss.krtirtho.spotube"
];
};
} }

View File

@@ -1,7 +0,0 @@
{
imports = [
./all.nix
./dunst
./swaync
];
}

View File

@@ -1,48 +0,0 @@
import Quickshell
import Quickshell.Services.UPower
import QtQuick
import QtQuick.Layouts
import org.kde.kirigami
Rectangle {
id: bat
Layout.preferredWidth: batIcon.width
Layout.fillHeight: true
color: 'transparent'
readonly property var battery: UPower.displayDevice
readonly property int percentage: Math.round(battery.percentage * 100)
property var size: height * 0.4
visible: battery.isLaptopBattery
Icon {
id: batIcon
anchors.centerIn: parent
implicitHeight: bat.size
implicitWidth: bat.size
// This recolors the entire svg, instead of only classless components.
// Hopefully in the future classes can be selected for recoloring.
isMask: true
color: 'white'
source: {
const nearestTen = Math.round(bat.percentage / 10) * 10;
const number = nearestTen.toString().padStart(2, "0");
let charging;
if (bat.battery.state == UPowerDeviceState.Charging) {
charging = "-charging";
} else if (bat.battery.state.toString() == UPowerDeviceState.FullyCharged) {
charging = "-charged";
} else {
charging = "";
}
return Quickshell.iconPath(`battery-level-${number}${charging}-symbolic`);
}
}
}

View File

@@ -1,16 +0,0 @@
import QtQuick
import QtQuick.Layouts
import "../../utils"
Rectangle {
Layout.fillHeight: true
color: "transparent"
implicitWidth: clockText.width
Text {
id: clockText
text: Time.time
color: Colors.fg
anchors.centerIn: parent
}
}

View File

@@ -1,14 +0,0 @@
import QtQuick
import QtQuick.Layouts
Rectangle {
Layout.fillHeight: true
color: "salmon"
implicitWidth: mprisText.width
Text {
id: mprisText
text: "Mpris"
anchors.centerIn: parent
}
}

View File

@@ -1,54 +0,0 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../../utils"
Rectangle {
id: resources
Layout.fillHeight: true
color: "transparent"
implicitWidth: rowLayout.width
property int valueSize: 8
property int textSize: 6
property string valueColor: "white"
property string textColor: "lightgray"
RowLayout {
id: rowLayout
anchors.centerIn: parent
ColumnLayout {
id: cpuColumn
Label {
color: textColor
font.pointSize: textSize
text: "CPU"
Layout.alignment: Qt.AlignCenter
}
Label {
color: valueColor
font.pointSize: valueSize
text: Resources.cpu_percent + "%"
Layout.alignment: Qt.AlignCenter
}
}
ColumnLayout {
Label {
color: textColor
font.pointSize: textSize
text: "MEM"
Layout.alignment: Qt.AlignCenter
}
Label {
color: valueColor
font.pointSize: valueSize
text: Resources.mem_percent + "%"
Layout.alignment: Qt.AlignCenter
}
}
}
}

View File

@@ -1,5 +0,0 @@
import QtQuick
Text {
renderType: Text.NativeRendering
}

View File

@@ -1,14 +0,0 @@
import QtQuick
import QtQuick.Layouts
Rectangle {
Layout.fillHeight: true
color: "lightblue"
implicitWidth: trayText.width
Text {
id: trayText
text: "Tray"
anchors.centerIn: parent
}
}

View File

@@ -1,26 +0,0 @@
import QtQuick
import QtQuick.Layouts
Rectangle {
id: ws
property bool hovered: false
Layout.preferredWidth: parent.height * 0.4
Layout.preferredHeight: parent.height * 0.4
Layout.alignment: Qt.AlignHCenter
radius: height / 2
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: () => {
ws.hovered = true;
}
onExited: () => {
ws.hovered = false;
}
onClicked: () => console.log(`workspace ?`)
}
}

View File

@@ -1,55 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import "../../../utils"
import Quickshell.Hyprland
Rectangle {
id: workspaces
color: 'transparent'
width: workspacesRow.implicitWidth
Layout.fillHeight: true
RowLayout {
id: workspacesRow
height: parent.height
implicitWidth: (parent.height * 0.5 + spacing) * 2 - spacing
anchors.centerIn: parent
spacing: height / 7
Repeater {
id: repeater
model: HyprlandUtils.maxWorkspace
Workspace {
id: ws
required property int index
property HyprlandWorkspace currWorkspace: Hyprland.workspaces.values.find(e => e.id == index + 1) || null
property bool nonexistent: currWorkspace === null
property bool focused: index + 1 === Hyprland.focusedMonitor.activeWorkspace.id
Layout.preferredWidth: {
if (focused) {
return parent.height * 0.8;
} else {
return parent.height * 0.4;
}
}
color: {
if (nonexistent) {
return Colors.bgBlur;
} else {
return Colors.monitorColors[Hyprland.monitors.values.indexOf(Hyprland.workspaces.values.find(e => e.id === index + 1).monitor)];
}
}
}
}
}
}

View File

@@ -1,6 +0,0 @@
import "./windows"
import Quickshell // for ShellRoot and PanelWindow
ShellRoot {
Bar {}
}

View File

@@ -1,9 +0,0 @@
import Quickshell
pragma Singleton
Singleton {
property var bgBar: Qt.rgba(0, 0, 0, 0.21)
property var bgBlur: Qt.rgba(0, 0, 0, 0.3)
property var fg: "white"
property list<var> monitorColors: ["#e06c75", "#e5c07b", "#98c379", "#61afef"]
}

View File

@@ -1,67 +0,0 @@
pragma Singleton
import Quickshell
import Quickshell.Hyprland
import QtQuick
Singleton {
id: hyprland
property list<HyprlandWorkspace> workspaces: sortWorkspaces(Hyprland.workspaces.values)
property HyprlandWorkspace focusedWorkspace: Hyprland.focusedMonitor?.activeWorkspace
property int maxWorkspace: findMaxId()
function sortWorkspaces(ws) {
return [...ws].sort((a, b) => a?.id - b?.id);
}
function switchWorkspace(w: int): void {
console.log(`workspace: focus ${focusedWorkspace.id} -> ${w}`);
Hyprland.dispatch(`workspace ${w}`);
}
function findMaxId(): int {
let num = hyprland.workspaces.length;
return hyprland.workspaces[num - 1]?.id;
}
Connections {
target: Hyprland
function onRawEvent(event) {
// console.log("EVENT NAME", event.name);
// consow.wg("EVENT DATA", event.data);
let eventName = event.name;
switch (eventName) {
// Both of these are required in order to detect workspace changes
// even when switching monitors.
// case "workspacev2":
// {
// // hyprland.focusedWorkspace = Hyprland.focusedMonitor?.activeWorkspace;
// console.log(`workspace: ${hyprland.focusedWorkspace.id}`);
// console.log(`num workspaces ${hyprland.workspaces.length}`)
// console.log(`num workspaces (real) ${Hyprland.workspaces.values.length}`)
// break;
// }
// case "focusedmonv2":
// {
// // hyprland.focusedWorkspace = Hyprland.focusedMonitor?.activeWorkspace;
// console.log(`workspace: ${hyprland.focusedWorkspace.id}`);
// console.log(`num workspaces ${hyprland.workspaces.length}`)
// console.log(`num workspaces (real) ${Hyprland.workspaces.values.length}`)
// break;
// }
case "createworkspacev2":
{
hyprland.workspaces = hyprland.sortWorkspaces(Hyprland.workspaces.values);
hyprland.maxWorkspace = findMaxId();
}
case "destroyworkspacev2":
{
hyprland.workspaces = hyprland.sortWorkspaces(Hyprland.workspaces.values);
hyprland.maxWorkspace = findMaxId();
}
}
}
}
}

View File

@@ -1,67 +0,0 @@
pragma Singleton
import Quickshell
import Quickshell.Io
import QtQuick
Singleton {
property int cpu_percent
property string cpu_freq
property int mem_percent
property string mem_used
Process {
id: process_cpu_percent
running: true
command: ["sh", "-c", "top -bn1 | rg '%Cpu' | awk '{print 100-$8}'"]
stdout: SplitParser {
onRead: data => cpu_percent = Math.round(data)
}
}
Process {
id: process_cpu_freq
running: true
command: ["sh", "-c", "lscpu --parse=MHZ"]
stdout: SplitParser {
onRead: data => {
// delete the first 4 lines (comments)
const mhz = data.split("\n").slice(4);
// compute mean frequency
const freq = mhz.reduce((acc, e) => acc + Number(e), 0) / mhz.length;
cpu_freq = Math.round(freq) + " MHz";
}
}
}
Process {
id: process_mem_percent
running: true
command: ["sh", "-c", "free | awk 'NR==2{print $3/$2*100}'"]
stdout: SplitParser {
onRead: data => mem_percent = Math.round(data)
}
}
Process {
id: process_mem_used
running: true
command: ["sh", "-c", "free --si -h | awk 'NR==2{print $3}'"]
stdout: SplitParser {
onRead: data => mem_used = data
}
}
Timer {
interval: 2000
running: true
repeat: true
onTriggered: () => {
process_cpu_percent.running = true
process_cpu_freq.running = true
process_mem_percent.running = true
process_mem_used.running = true
}
}
}

View File

@@ -1,29 +0,0 @@
pragma Singleton
import Quickshell
import Quickshell.Io
import QtQuick
Singleton {
property var locale: Qt.locale()
function createDate(): string {
let date = new Date();
let hh = date.getHours().toString().padStart(2, 0);
let mm = date.getMinutes().toString().padStart(2, 0)
let weekday = locale.dayName(date.getDay(), Locale.ShortFormat)
let month = locale.monthName(date.getMonth(), Locale.ShortFormat)
let day = date.getDate()
return `${weekday} ${month} ${day} ${hh}:${mm}`
}
property var time: createDate()
Timer {
interval: 1000
running: true
repeat: true
onTriggered: time = createDate()
}
}

View File

@@ -1,79 +0,0 @@
//@ pragma NativeTextRendering
import Quickshell
import QtQuick
import QtQuick.Layouts
import "../utils"
import "../components/bar"
import "../components/bar/workspaces"
Scope {
PanelWindow {
id: barWindow
screen: Quickshell.screens[0]
anchors {
top: true
left: true
right: true
}
height: 32
color: "transparent"
Rectangle {
id: bar
anchors.fill: parent
color: Colors.bgBlur
// left
// RowLayout {
// id: barLeft
//
// anchors.bottom: parent.bottom
// anchors.left: parent.left
// anchors.top: parent.top
//
// anchors.leftMargin: height / 4
// anchors.rightMargin: height / 4
// spacing: height / 4
//
// Workspaces {}
// }
// middle
RowLayout {
id: barMiddle
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.leftMargin: height / 4
anchors.rightMargin: height / 4
spacing: height / 4
Mpris {}
}
// right
RowLayout {
id: barRight
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.top: parent.top
anchors.leftMargin: height / 4
anchors.rightMargin: height / 4
spacing: height / 4
Tray {}
Resources {}
Battery {}
Clock {}
}
}
}
}

View File

@@ -4,6 +4,12 @@
pkgs, pkgs,
... ...
}: }:
let
# FIXME: symlink
homeDir = config.my.home.home.homeDirectory;
quickshellDir = "${homeDir}/workspace/nixos-dotfiles/modules/desktop/quickshell/qml";
quickshellTarget = "${homeDir}/.config/quickshell";
in
lib.my.makeSwitch { lib.my.makeSwitch {
inherit config; inherit config;
default = false; default = false;
@@ -13,17 +19,25 @@ lib.my.makeSwitch {
"quickshell" "quickshell"
]; ];
config' = { config' = {
my.home = { my.home.home = {
home.packages = [ pkgs.quickshell ]; packages = with pkgs; [
home.sessionVariables.QML2_IMPORT_PATH = lib.concatStringsSep ":" [ quickshell
qt6Packages.qt5compat
libsForQt5.qt5.qtgraphicaleffects
kdePackages.qtbase
kdePackages.qtdeclarative
material-symbols
material-icons
];
sessionVariables.QML2_IMPORT_PATH = lib.concatStringsSep ":" [
"${pkgs.quickshell}/lib/qt-6/qml" "${pkgs.quickshell}/lib/qt-6/qml"
"${pkgs.kdePackages.qtdeclarative}/lib/qt-6/qml" "${pkgs.kdePackages.qtdeclarative}/lib/qt-6/qml"
"${pkgs.kdePackages.kirigami.unwrapped}/lib/qt-6/qml" "${pkgs.kdePackages.kirigami.unwrapped}/lib/qt-6/qml"
]; ];
xdg.configFile."quickshell" = { activation.symlinkQuickshellAndFaceIcon = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
source = ./config; ln -sfn "${quickshellDir}" "${quickshellTarget}"
recursive = true; '';
};
}; };
}; };
} }

View File

@@ -0,0 +1,2 @@
/debug.log
/quickshell.log

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -0,0 +1,84 @@
import QtQuick
import QtQuick.Shapes
import "root:/Data" as Settings
// Concave corner shape component for rounded panel edges
Shape {
id: root
property string position: "topleft" // Corner position: topleft/topright/bottomleft/bottomright
property real size: 1.0 // Scale multiplier for entire corner
property int concaveWidth: 100 * size
property int concaveHeight: 60 * size
property int offsetX: -20
property int offsetY: -20
property color fillColor: Settings.Colors.bgColor
property int arcRadius: 20 * size
// Position flags derived from position string
property bool _isTop: position.includes("top")
property bool _isLeft: position.includes("left")
property bool _isRight: position.includes("right")
property bool _isBottom: position.includes("bottom")
// Base coordinates for left corner shape
property real _baseStartX: 30 * size
property real _baseStartY: _isTop ? 20 * size : 0
property real _baseLineX: 30 * size
property real _baseLineY: _isTop ? 0 : 20 * size
property real _baseArcX: 50 * size
property real _baseArcY: _isTop ? 20 * size : 0
// Mirror coordinates for right corners
property real _startX: _isRight ? (concaveWidth - _baseStartX) : _baseStartX
property real _startY: _baseStartY
property real _lineX: _isRight ? (concaveWidth - _baseLineX) : _baseLineX
property real _lineY: _baseLineY
property real _arcX: _isRight ? (concaveWidth - _baseArcX) : _baseArcX
property real _arcY: _baseArcY
// Arc direction varies by corner to maintain proper concave shape
property int _arcDirection: {
if (_isTop && _isLeft)
return PathArc.Counterclockwise;
if (_isTop && _isRight)
return PathArc.Clockwise;
if (_isBottom && _isLeft)
return PathArc.Clockwise;
if (_isBottom && _isRight)
return PathArc.Counterclockwise;
return PathArc.Counterclockwise;
}
width: concaveWidth
height: concaveHeight
// Position relative to parent based on corner type
x: _isLeft ? offsetX : (parent ? parent.width - width + offsetX : 0)
y: _isTop ? offsetY : (parent ? parent.height - height + offsetY : 0)
preferredRendererType: Shape.CurveRenderer
layer.enabled: true
layer.samples: 4
ShapePath {
strokeWidth: 0
fillColor: root.fillColor
strokeColor: root.fillColor // Use same color as fill to eliminate artifacts
startX: root._startX
startY: root._startY
PathLine {
x: root._lineX
y: root._lineY
}
PathArc {
x: root._arcX
y: root._arcY
radiusX: root.arcRadius
radiusY: root.arcRadius
useLargeArc: false
direction: root._arcDirection
}
}
}

View File

@@ -0,0 +1,48 @@
import QtQuick
QtObject {
id: root
// Keep track of loaded components
property var activeLoaders: ({})
// Dynamically load a QML component
function load(componentUrl, parent, properties) {
if (!activeLoaders[componentUrl]) {
var loader = Qt.createQmlObject(`
import QtQuick
Loader {
active: false
asynchronous: true
visible: false
}
`, parent);
loader.source = componentUrl;
loader.active = true;
if (properties) {
for (var prop in properties) {
loader[prop] = properties[prop];
}
}
activeLoaders[componentUrl] = loader;
}
return activeLoaders[componentUrl];
}
// Destroy and remove a loaded component
function unload(componentUrl) {
if (activeLoaders[componentUrl]) {
activeLoaders[componentUrl].active = false;
activeLoaders[componentUrl].destroy();
delete activeLoaders[componentUrl];
}
}
// Check if a component is loaded
function isLoaded(componentUrl) {
return !!activeLoaders[componentUrl];
}
}

View File

@@ -0,0 +1,189 @@
pragma Singleton
import QtQuick
import Quickshell.Io
// System process and resource monitoring
QtObject {
id: root
// System resource metrics
property real cpuUsage: 0
property real ramUsage: 0
property real totalRam: 0
property real usedRam: 0
// System control processes
property Process shutdownProcess: Process {
command: ["shutdown", "-h", "now"]
}
property Process rebootProcess: Process {
command: ["reboot"]
}
property Process lockProcess: Process {
command: ["hyprlock"]
}
property Process logoutProcess: Process {
command: ["loginctl", "terminate-user", "$USER"]
}
property Process pavucontrolProcess: Process {
command: ["pavucontrol"]
}
// Resource monitoring processes
property Process cpuProcess: Process {
command: ["sh", "-c", "grep '^cpu ' /proc/stat | awk '{usage=($2+$3+$4)*100/($2+$3+$4+$5)} END {print usage}'"]
stdout: SplitParser {
onRead: data => {
root.cpuUsage = parseFloat(data);
}
}
}
property Process ramProcess: Process {
command: ["sh", "-c", "free -b | awk '/Mem:/ {print $2\" \"$3\" \"$3/$2*100}'"]
stdout: SplitParser {
onRead: data => {
var parts = data.trim().split(/\s+/);
if (parts.length >= 3) {
root.totalRam = parseFloat(parts[0]) / (1024 * 1024 * 1024);
root.usedRam = parseFloat(parts[1]) / (1024 * 1024 * 1024);
root.ramUsage = parseFloat(parts[2]);
}
}
}
}
// Monitoring timers (start manually when needed)
property Timer cpuTimer: Timer {
interval: 30000
running: false
repeat: true
onTriggered: {
cpuProcess.running = false;
cpuProcess.running = true;
}
}
property Timer ramTimer: Timer {
interval: 30000
running: false
repeat: true
onTriggered: {
ramProcess.running = false;
ramProcess.running = true;
}
}
// System control functions
function shutdown() {
console.log("Executing shutdown command");
shutdownProcess.running = true;
}
function reboot() {
console.log("Executing reboot command");
rebootProcess.running = true;
}
function lock() {
console.log("Executing lock command");
lockProcess.running = true;
}
function logout() {
console.log("Executing logout command");
logoutProcess.running = true;
}
function openPavuControl() {
console.log("Opening PavuControl");
pavucontrolProcess.running = true;
}
// Performance monitoring control
function startMonitoring() {
console.log("Starting system monitoring");
cpuTimer.running = true;
ramTimer.running = true;
}
function stopMonitoring() {
console.log("Stopping system monitoring");
cpuTimer.running = false;
ramTimer.running = false;
}
function setMonitoringInterval(intervalMs) {
console.log("Setting monitoring interval to", intervalMs, "ms");
cpuTimer.interval = intervalMs;
ramTimer.interval = intervalMs;
}
function refreshSystemStats() {
console.log("Manually refreshing system stats");
cpuProcess.running = false;
cpuProcess.running = true;
ramProcess.running = false;
ramProcess.running = true;
}
// Process state queries
function isShutdownRunning() {
return shutdownProcess.running;
}
function isRebootRunning() {
return rebootProcess.running;
}
function isLogoutRunning() {
return logoutProcess.running;
}
function isPavuControlRunning() {
return pavucontrolProcess.running;
}
function isMonitoringActive() {
return cpuTimer.running && ramTimer.running;
}
function stopPavuControl() {
pavucontrolProcess.running = false;
}
// Formatted output helpers
function getCpuUsageFormatted() {
return Math.round(cpuUsage) + "%";
}
function getRamUsageFormatted() {
return Math.round(ramUsage) + "% (" + usedRam.toFixed(1) + "GB/" + totalRam.toFixed(1) + "GB)";
}
function getRamUsageSimple() {
return Math.round(ramUsage) + "%";
}
Component.onDestruction: {
// Stop all timers
cpuTimer.running = false;
ramTimer.running = false;
// Stop monitoring processes
cpuProcess.running = false;
ramProcess.running = false;
// Stop control processes if running
if (shutdownProcess.running)
shutdownProcess.running = false;
if (rebootProcess.running)
rebootProcess.running = false;
if (lockProcess.running)
lockProcess.running = false;
if (logoutProcess.running)
logoutProcess.running = false;
if (pavucontrolProcess.running)
pavucontrolProcess.running = false;
}
}

View File

@@ -0,0 +1,38 @@
pragma Singleton
import QtQuick
QtObject {
property var service: null
// Expose current colors from the service
readonly property color primary: service?.colors?.raw?.primary || "#7ed7b8"
readonly property color on_primary: service?.colors?.raw?.on_primary || "#00382a"
readonly property color primary_container: service?.colors?.raw?.primary_container || "#454b03"
readonly property color on_primary_container: service?.colors?.raw?.on_primary_container || "#e2e993"
readonly property color secondary: service?.colors?.raw?.secondary || "#c8c9a6"
readonly property color surface_bright: service?.colors?.raw?.surface_bright || "#373b30"
readonly property bool hasColors: service?.isLoaded || false
// Expose all raw Material 3 colors for complete access
readonly property var rawColors: service?.colors?.raw || ({})
function setService(matugenService) {
service = matugenService;
console.log("MatugenManager: Service registered");
}
function reloadColors() {
if (service && service.reloadColors) {
console.log("MatugenManager: Triggering color reload");
service.reloadColors();
return true;
} else {
console.warn("MatugenManager: No service available for reload");
return false;
}
}
function isAvailable() {
return service !== null;
}
}

View File

@@ -0,0 +1,315 @@
pragma Singleton
import Quickshell
import QtQuick
import Quickshell.Io
Singleton {
id: settings
// Prevent auto-saving during initial load
property bool isLoading: true
// Settings persistence with atomic writes
FileView {
id: settingsFile
path: "settings.json"
blockWrites: true
atomicWrites: true
watchChanges: false
onLoaded: {
settings.isLoading = true; // Disable auto-save during loading
try {
var content = JSON.parse(text());
if (content) {
// Load with fallback defaults
settings.isDarkTheme = content.isDarkTheme ?? true;
settings.currentTheme = content.currentTheme ?? (content.isDarkTheme !== false ? "oxocarbon_dark" : "oxocarbon_light");
settings.useCustomAccent = content.useCustomAccent ?? false;
settings.avatarSource = content.avatarSource ?? "/home/imxyy/Pictures/icon.jpg";
settings.weatherLocation = content.weatherLocation ?? "Dinslaken";
settings.useFahrenheit = content.useFahrenheit ?? false;
settings.displayTime = content.displayTime ?? 6000;
settings.videoPath = content.videoPath ?? "~/Videos/";
settings.customDarkAccent = content.customDarkAccent ?? "#be95ff";
settings.customLightAccent = content.customLightAccent ?? "#8a3ffc";
settings.autoSwitchPlayer = content.autoSwitchPlayer ?? true;
settings.alwaysShowPlayerDropdown = content.alwaysShowPlayerDropdown ?? true;
settings.historyLimit = content.historyLimit ?? 25;
settings.nightLightEnabled = content.nightLightEnabled ?? false;
settings.nightLightWarmth = content.nightLightWarmth ?? 0.4;
settings.nightLightAuto = content.nightLightAuto ?? false;
settings.nightLightStartHour = content.nightLightStartHour ?? 20;
settings.nightLightEndHour = content.nightLightEndHour ?? 6;
settings.nightLightManualOverride = content.nightLightManualOverride ?? false;
settings.nightLightManuallyEnabled = content.nightLightManuallyEnabled ?? false;
settings.ignoredApps = content.ignoredApps ?? [];
settings.workspaceBurstEnabled = content.workspaceBurstEnabled ?? true;
settings.workspaceGlowEnabled = content.workspaceGlowEnabled ?? true;
}
} catch (e) {
console.log("Error parsing user settings:", e);
}
// Re-enable auto-save after loading is complete
settings.isLoading = false;
}
}
// User-configurable settings
property string avatarSource: "/home/imxyy/Pictures/icon.jpg"
property bool isDarkTheme: true // Keep for backwards compatibility
property string currentTheme: "oxocarbon_dark" // New theme system
property bool useCustomAccent: false // Whether to use custom accent colors
property string weatherLocation: "Dinslaken"
property bool useFahrenheit: false // Temperature unit setting
property int displayTime: 6000 // Notification display time in ms
property var ignoredApps: [] // Apps to ignore notifications from (case-insensitive)
property int historyLimit: 25 // Notification history limit
property string videoPath: "~/Videos/"
property string customDarkAccent: "#be95ff"
property string customLightAccent: "#8a3ffc"
// Music Player settings
property bool autoSwitchPlayer: true
property bool alwaysShowPlayerDropdown: true
// Night Light settings
property bool nightLightEnabled: false
property real nightLightWarmth: 0.4
property bool nightLightAuto: false
property int nightLightStartHour: 20 // 8 PM
property int nightLightEndHour: 6 // 6 AM
property bool nightLightManualOverride: false // Track manual user actions
property bool nightLightManuallyEnabled: false // Track if user manually enabled it
// Animation settings
property bool workspaceBurstEnabled: true
property bool workspaceGlowEnabled: true
// UI constants
readonly property real borderWidth: 9
readonly property real cornerRadius: 20
signal settingsChanged
// Helper functions for managing ignored apps
function addIgnoredApp(appName) {
if (appName && appName.trim() !== "") {
var trimmedName = appName.trim();
// Case-insensitive check for existing apps
var exists = false;
for (var i = 0; i < ignoredApps.length; i++) {
if (ignoredApps[i].toLowerCase() === trimmedName.toLowerCase()) {
exists = true;
break;
}
}
if (!exists) {
var newApps = ignoredApps.slice(); // Create a copy
newApps.push(trimmedName);
ignoredApps = newApps;
console.log("Added ignored app:", trimmedName, "Current list:", ignoredApps);
// Force save immediately (only if not loading)
if (!isLoading) {
saveSettings();
}
return true;
}
}
return false;
}
function removeIgnoredApp(appName) {
var index = ignoredApps.indexOf(appName);
if (index > -1) {
var newApps = ignoredApps.slice(); // Create a copy
newApps.splice(index, 1);
ignoredApps = newApps;
console.log("Removed ignored app:", appName, "Current list:", ignoredApps);
// Force save immediately (only if not loading)
if (!isLoading) {
saveSettings();
}
return true;
}
return false;
}
function saveSettings() {
try {
var content = {
isDarkTheme: settings.isDarkTheme,
currentTheme: settings.currentTheme,
useCustomAccent: settings.useCustomAccent,
avatarSource: settings.avatarSource,
weatherLocation: settings.weatherLocation,
useFahrenheit: settings.useFahrenheit,
displayTime: settings.displayTime,
videoPath: settings.videoPath,
customDarkAccent: settings.customDarkAccent,
customLightAccent: settings.customLightAccent,
autoSwitchPlayer: settings.autoSwitchPlayer,
alwaysShowPlayerDropdown: settings.alwaysShowPlayerDropdown,
historyLimit: settings.historyLimit,
nightLightEnabled: settings.nightLightEnabled,
nightLightWarmth: settings.nightLightWarmth,
nightLightAuto: settings.nightLightAuto,
nightLightStartHour: settings.nightLightStartHour,
nightLightEndHour: settings.nightLightEndHour,
nightLightManualOverride: settings.nightLightManualOverride,
nightLightManuallyEnabled: settings.nightLightManuallyEnabled,
ignoredApps: settings.ignoredApps,
workspaceBurstEnabled: settings.workspaceBurstEnabled,
workspaceGlowEnabled: settings.workspaceGlowEnabled
};
var jsonContent = JSON.stringify(content, null, 4);
settingsFile.setText(jsonContent);
} catch (e) {
console.log("Error saving user settings:", e);
}
}
// Auto-save watchers (only save when not loading)
onIsDarkThemeChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onCurrentThemeChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onUseCustomAccentChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onAvatarSourceChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onWeatherLocationChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onUseFahrenheitChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onDisplayTimeChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onHistoryLimitChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onVideoPathChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onCustomDarkAccentChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onCustomLightAccentChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onAutoSwitchPlayerChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onAlwaysShowPlayerDropdownChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onNightLightEnabledChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onNightLightWarmthChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onNightLightAutoChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onNightLightStartHourChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onNightLightEndHourChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onNightLightManualOverrideChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onNightLightManuallyEnabledChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onIgnoredAppsChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onWorkspaceBurstEnabledChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
onWorkspaceGlowEnabledChanged: {
if (!isLoading) {
settingsChanged();
saveSettings();
}
}
Component.onCompleted: {
settingsFile.reload();
}
}

View File

@@ -0,0 +1,240 @@
pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Io
import "Themes" as Themes
Singleton {
id: themeManager
// Import all theme definitions
property var oxocarbon: Themes.Oxocarbon
property var dracula: Themes.Dracula
property var gruvbox: Themes.Gruvbox
property var catppuccin: Themes.Catppuccin
property var matugen: Themes.Matugen
// Available theme definitions
readonly property var themes: ({
"oxocarbon_dark": oxocarbon.dark,
"oxocarbon_light": oxocarbon.light,
"dracula_dark": dracula.dark,
"dracula_light": dracula.light,
"gruvbox_dark": gruvbox.dark,
"gruvbox_light": gruvbox.light,
"catppuccin_dark": catppuccin.dark,
"catppuccin_light": catppuccin.light,
"matugen_dark": matugen.dark,
"matugen_light": matugen.light
})
// Current theme selection - defaults to oxocarbon_dark if not set
readonly property string currentThemeId: Settings.currentTheme || "oxocarbon_dark"
readonly property var currentTheme: themes[currentThemeId] || themes["oxocarbon_dark"]
// Auto-update accents when Matugen colors change
Connections {
target: MatugenManager
function onPrimaryChanged() {
if (currentThemeId.startsWith("matugen_")) {
updateMatugenAccents();
}
}
}
// Connect to MatugenService signals for automatic accent updates
Connections {
target: MatugenManager.service
function onMatugenColorsUpdated() {
if (currentThemeId.startsWith("matugen_")) {
console.log("ThemeManager: Received matugen colors update signal");
updateMatugenAccents();
}
}
}
// Initialize currentTheme in settings if not present
Component.onCompleted: {
if (!Settings.currentTheme) {
console.log("Initializing currentTheme in settings");
Settings.currentTheme = "oxocarbon_dark";
Settings.saveSettings();
}
// Matugen theme is now self-contained with service-based colors
console.log("Matugen theme initialized with service-based colors");
// Update accents if already using matugen theme
if (currentThemeId.startsWith("matugen_")) {
updateMatugenAccents();
}
}
// Custom accent colors (can be changed by user)
property string customDarkAccent: Settings.customDarkAccent || "#be95ff"
property string customLightAccent: Settings.customLightAccent || "#8a3ffc"
// Dynamic color properties based on current theme
readonly property color base00: currentTheme.base00
readonly property color base01: currentTheme.base01
readonly property color base02: currentTheme.base02
readonly property color base03: currentTheme.base03
readonly property color base04: currentTheme.base04
readonly property color base05: currentTheme.base05
readonly property color base06: currentTheme.base06
readonly property color base07: currentTheme.base07
readonly property color base08: currentTheme.base08
readonly property color base09: currentTheme.base09
readonly property color base0A: currentTheme.base0A
readonly property color base0B: currentTheme.base0B
readonly property color base0C: currentTheme.base0C
readonly property color base0D: currentTheme.base0D
readonly property color base0E: Settings.useCustomAccent ? (currentTheme.type === "dark" ? customDarkAccent : customLightAccent) : currentTheme.base0E
readonly property color base0F: currentTheme.base0F
// Common UI color mappings
readonly property color bgColor: base00
readonly property color bgLight: base01
readonly property color bgLighter: base02
readonly property color fgColor: base04
readonly property color fgColorBright: base05
readonly property color accentColor: base0E
readonly property color accentColorBright: base0D
readonly property color highlightBg: Qt.rgba(base0E.r, base0E.g, base0E.b, 0.15)
readonly property color errorColor: base08
readonly property color greenColor: base0B
readonly property color redColor: base08
// Alternative semantic aliases for convenience
readonly property color background: base00
readonly property color panelBackground: base01
readonly property color selection: base02
readonly property color border: base03
readonly property color secondaryText: base04
readonly property color primaryText: base05
readonly property color brightText: base06
readonly property color brightestText: base07
readonly property color error: base08
readonly property color warning: base09
readonly property color highlight: base0A
readonly property color success: base0B
readonly property color info: base0C
readonly property color primary: base0D
readonly property color accent: base0E
readonly property color special: base0F
// UI styling constants
readonly property real borderWidth: 9
readonly property real cornerRadius: 20
// Color utility functions
function withOpacity(color, opacity) {
return Qt.rgba(color.r, color.g, color.b, opacity);
}
function withHighlight(color) {
return Qt.rgba(color.r, color.g, color.b, 0.15);
}
// Theme management functions
function setTheme(themeId) {
if (themes[themeId]) {
const previousThemeId = Settings.currentTheme;
Settings.currentTheme = themeId;
// Check if switching between matugen light/dark modes
if (themeId.startsWith("matugen_") && previousThemeId && previousThemeId.startsWith("matugen_")) {
const newMode = themeId.includes("_light") ? "light" : "dark";
const oldMode = previousThemeId.includes("_light") ? "light" : "dark";
if (newMode !== oldMode) {
console.log(`🎨 Switching matugen from ${oldMode} to ${newMode} mode`);
}
}
// Auto-update accents for Matugen themes
if (themeId.startsWith("matugen_")) {
updateMatugenAccents();
}
Settings.saveSettings();
return true;
}
return false;
}
// Auto-update accent colors when using Matugen theme
function updateMatugenAccents() {
if (MatugenManager.isAvailable() && MatugenManager.hasColors) {
// Get colors from the raw matugen palette
const rawColors = MatugenManager.rawColors;
// Use primary for both dark and light themes - it's generated appropriately by matugen
const accent = rawColors.primary;
// Debug log the colors we're using
console.log("Raw colors available:", Object.keys(rawColors));
console.log("Selected accent for both themes:", accent);
// Update custom accents - use the same accent for both
setCustomAccent(accent, accent);
// Enable custom accents for Matugen theme
Settings.useCustomAccent = true;
Settings.saveSettings();
console.log("Auto-updated Matugen accents from service:", accent);
} else {
console.log("MatugenManager service not available or no colors loaded yet");
}
}
function getThemeList() {
return Object.keys(themes).map(function (key) {
return {
id: key,
name: themes[key].name,
type: themes[key].type
};
});
}
function getDarkThemes() {
return getThemeList().filter(function (theme) {
return theme.type === "dark";
});
}
function getLightThemes() {
return getThemeList().filter(function (theme) {
return theme.type === "light";
});
}
function setCustomAccent(darkColor, lightColor) {
customDarkAccent = darkColor;
customLightAccent = lightColor;
Settings.customDarkAccent = darkColor;
Settings.customLightAccent = lightColor;
Settings.saveSettings();
}
function toggleCustomAccent() {
Settings.useCustomAccent = !Settings.useCustomAccent;
Settings.saveSettings();
}
// Legacy function for backwards compatibility
function toggleTheme() {
// Switch between dark and light variants of current theme family
var currentFamily = currentThemeId.replace(/_dark|_light/, "");
var newThemeId = currentTheme.type === "dark" ? currentFamily + "_light" : currentFamily + "_dark";
// If the opposite variant doesn't exist, switch to oxocarbon
if (!themes[newThemeId]) {
newThemeId = currentTheme.type === "dark" ? "oxocarbon_light" : "oxocarbon_dark";
}
setTheme(newThemeId);
}
}

View File

@@ -0,0 +1,76 @@
pragma Singleton
import QtQuick
QtObject {
readonly property var dark: ({
name: "Catppuccin Mocha",
type: "dark",
base00: "#1e1e2e" // Base
,
base01: "#181825" // Mantle
,
base02: "#313244" // Surface0
,
base03: "#45475a" // Surface1
,
base04: "#585b70" // Surface2
,
base05: "#cdd6f4" // Text
,
base06: "#f5e0dc" // Rosewater
,
base07: "#b4befe" // Lavender
,
base08: "#f38ba8" // Red
,
base09: "#fab387" // Peach
,
base0A: "#f9e2af" // Yellow
,
base0B: "#a6e3a1" // Green
,
base0C: "#94e2d5" // Teal
,
base0D: "#89b4fa" // Blue
,
base0E: "#cba6f7" // Mauve
,
base0F: "#f2cdcd" // Flamingo
})
readonly property var light: ({
name: "Catppuccin Latte",
type: "light",
base00: "#eff1f5" // Base
,
base01: "#e6e9ef" // Mantle
,
base02: "#ccd0da" // Surface0
,
base03: "#bcc0cc" // Surface1
,
base04: "#acb0be" // Surface2
,
base05: "#4c4f69" // Text
,
base06: "#dc8a78" // Rosewater
,
base07: "#7287fd" // Lavender
,
base08: "#d20f39" // Red
,
base09: "#fe640b" // Peach
,
base0A: "#df8e1d" // Yellow
,
base0B: "#40a02b" // Green
,
base0C: "#179299" // Teal
,
base0D: "#1e66f5" // Blue
,
base0E: "#8839ef" // Mauve
,
base0F: "#dd7878" // Flamingo
})
}

View File

@@ -0,0 +1,76 @@
pragma Singleton
import QtQuick
QtObject {
readonly property var dark: ({
name: "Dracula",
type: "dark",
base00: "#282a36" // Background
,
base01: "#44475a" // Current line
,
base02: "#565761" // Selection
,
base03: "#6272a4" // Comment
,
base04: "#6272a4" // Dark foreground
,
base05: "#f8f8f2" // Foreground
,
base06: "#f8f8f2" // Light foreground
,
base07: "#ffffff" // Light background
,
base08: "#ff5555" // Red
,
base09: "#ffb86c" // Orange
,
base0A: "#f1fa8c" // Yellow
,
base0B: "#50fa7b" // Green
,
base0C: "#8be9fd" // Cyan
,
base0D: "#bd93f9" // Blue
,
base0E: "#ff79c6" // Magenta
,
base0F: "#ffb86c" // Orange
})
readonly property var light: ({
name: "Dracula Light",
type: "light",
base00: "#f8f8f2" // Light background
,
base01: "#ffffff" // Lighter background
,
base02: "#e5e5e5" // Selection
,
base03: "#bfbfbf" // Comment
,
base04: "#6272a4" // Dark foreground
,
base05: "#282a36" // Dark text
,
base06: "#21222c" // Darker text
,
base07: "#191a21" // Darkest
,
base08: "#e74c3c" // Red (adjusted for light)
,
base09: "#f39c12" // Orange
,
base0A: "#f1c40f" // Yellow
,
base0B: "#27ae60" // Green
,
base0C: "#17a2b8" // Cyan
,
base0D: "#6c7ce0" // Blue
,
base0E: "#e91e63" // Magenta
,
base0F: "#f39c12" // Orange
})
}

View File

@@ -0,0 +1,76 @@
pragma Singleton
import QtQuick
QtObject {
readonly property var dark: ({
name: "Gruvbox Dark",
type: "dark",
base00: "#282828" // Dark background
,
base01: "#3c3836" // Dark1
,
base02: "#504945" // Dark2
,
base03: "#665c54" // Dark3
,
base04: "#bdae93" // Light4
,
base05: "#d5c4a1" // Light3
,
base06: "#ebdbb2" // Light2
,
base07: "#fbf1c7" // Light1
,
base08: "#fb4934" // Red
,
base09: "#fe8019" // Orange
,
base0A: "#fabd2f" // Yellow
,
base0B: "#b8bb26" // Green
,
base0C: "#8ec07c" // Cyan
,
base0D: "#83a598" // Blue
,
base0E: "#d3869b" // Purple
,
base0F: "#d65d0e" // Brown
})
readonly property var light: ({
name: "Gruvbox Light",
type: "light",
base00: "#fbf1c7" // Light background
,
base01: "#ebdbb2" // Light1
,
base02: "#d5c4a1" // Light2
,
base03: "#bdae93" // Light3
,
base04: "#665c54" // Dark3
,
base05: "#504945" // Dark2
,
base06: "#3c3836" // Dark1
,
base07: "#282828" // Dark background
,
base08: "#cc241d" // Red
,
base09: "#d65d0e" // Orange
,
base0A: "#d79921" // Yellow
,
base0B: "#98971a" // Green
,
base0C: "#689d6a" // Cyan
,
base0D: "#458588" // Blue
,
base0E: "#b16286" // Purple
,
base0F: "#d65d0e" // Brown
})
}

View File

@@ -0,0 +1,141 @@
pragma Singleton
import QtQuick
QtObject {
// Reference to the MatugenService
property var matugenService: null
// Debug helper to check service status
function debugServiceStatus() {
console.log("🔍 Debug: matugenService =", matugenService);
console.log("🔍 Debug: matugenService.isLoaded =", matugenService ? matugenService.isLoaded : "N/A");
console.log("🔍 Debug: matugenService.colorVersion =", matugenService ? matugenService.colorVersion : "N/A");
console.log("🔍 Debug: condition result =", (matugenService && matugenService.isLoaded && matugenService.colorVersion >= 0));
if (matugenService && matugenService.colors) {
console.log("🔍 Debug: service.colors.dark =", JSON.stringify(matugenService.colors.dark));
}
}
// Map matugen colors to base16 scheme - using the service when available
// The colorVersion dependency forces re-evaluation when colors update
readonly property var dark: {
debugServiceStatus();
if (matugenService && matugenService.isLoaded && matugenService.colorVersion >= 0) {
// Use service colors if available, or generate fallback if we have light colors
return matugenService.colors.dark || {
name: "Matugen Dark (Generated from Light)",
type: "dark",
// If we only have light colors, create dark fallback
base00: "#141311",
base01: "#1c1c19",
base02: "#20201d",
base03: "#2a2a27",
base04: "#c9c7ba",
base05: "#e5e2de",
base06: "#31302e",
base07: "#e5e2de",
base08: "#ffb4ab",
base09: "#b5ccb9",
base0A: "#e4e5c1",
base0B: "#c8c7b7",
base0C: "#c8c9a6",
base0D: "#c8c9a6",
base0E: "#47483b",
base0F: "#000000"
};
} else {
return {
name: "Matugen Dark",
type: "dark",
// Updated fallback colors to match current quickshell-colors.qml
base00: "#141311",
base01: "#1c1c19",
base02: "#20201d",
base03: "#2a2a27",
base04: "#c9c7ba",
base05: "#e5e2de",
base06: "#31302e",
base07: "#e5e2de",
base08: "#ffb4ab",
base09: "#b5ccb9",
base0A: "#e4e5c1",
base0B: "#c8c7b7",
base0C: "#c8c9a6",
base0D: "#c8c9a6",
base0E: "#47483b",
base0F: "#000000"
};
}
}
readonly property var light: {
if (matugenService && matugenService.isLoaded && matugenService.colorVersion >= 0) {
// Use service colors if available, or generate fallback if we have dark colors
return matugenService.colors.light || {
name: "Matugen Light (Generated from Dark)",
type: "light",
// If we only have dark colors, create light fallback
base00: "#ffffff",
base01: "#f5f5f5",
base02: "#e8e8e8",
base03: "#d0d0d0",
base04: "#666666",
base05: "#1a1a1a",
base06: "#000000",
base07: "#ffffff",
base08: "#d32f2f",
base09: "#7b1fa2",
base0A: "#f57c00",
base0B: "#388e3c",
base0C: "#0097a7",
base0D: "#1976d2",
base0E: "#5e35b1",
base0F: "#000000"
};
} else {
return {
name: "Matugen Light",
type: "light",
// Updated fallback colors based on current colors
base00: "#ffffff",
base01: "#f5f5f5",
base02: "#e8e8e8",
base03: "#d0d0d0",
base04: "#666666",
base05: "#1a1a1a",
base06: "#000000",
base07: "#ffffff",
base08: "#d32f2f",
base09: "#7b1fa2",
base0A: "#f57c00",
base0B: "#388e3c",
base0C: "#0097a7",
base0D: "#1976d2",
base0E: "#5e35b1",
base0F: "#000000"
};
}
}
// Direct access to primary colors for accent updates
readonly property color primary: (matugenService && matugenService.getColor && matugenService.colorVersion >= 0) ? matugenService.getColor("primary") || "#c8c9a6" : "#c8c9a6"
readonly property color on_primary: (matugenService && matugenService.getColor && matugenService.colorVersion >= 0) ? matugenService.getColor("on_primary") || "#303219" : "#303219"
// Function to set the service reference
function setMatugenService(service) {
matugenService = service;
console.log("🔌 MatugenService connected to theme:", service);
// Connect to service signals for automatic updates
if (service) {
service.matugenColorsUpdated.connect(function () {
console.log("🎨 Matugen colors updated in theme (version " + service.colorVersion + ")");
debugServiceStatus();
});
}
}
Component.onCompleted: {
console.log("Matugen theme loaded, waiting for MatugenService connection");
}
}

View File

@@ -0,0 +1,76 @@
pragma Singleton
import QtQuick
QtObject {
readonly property var dark: ({
name: "Oxocarbon Dark",
type: "dark",
base00: "#161616" // OLED-friendly background
,
base01: "#262626" // Surface 1
,
base02: "#393939" // Surface 2
,
base03: "#525252" // Surface 3
,
base04: "#6f6f6f" // Text secondary
,
base05: "#c6c6c6" // Text primary
,
base06: "#e0e0e0" // Text on color
,
base07: "#f4f4f4" // Text inverse
,
base08: "#ff7eb6" // Red (pink)
,
base09: "#ee5396" // Magenta
,
base0A: "#42be65" // Green
,
base0B: "#be95ff" // Purple
,
base0C: "#3ddbd9" // Cyan
,
base0D: "#78a9ff" // Blue
,
base0E: "#be95ff" // Purple (accent)
,
base0F: "#08bdba" // Teal
})
readonly property var light: ({
name: "Oxocarbon Light",
type: "light",
base00: "#f4f4f4" // Light background
,
base01: "#ffffff" // Surface 1
,
base02: "#e0e0e0" // Surface 2
,
base03: "#c6c6c6" // Surface 3
,
base04: "#525252" // Text secondary
,
base05: "#262626" // Text primary
,
base06: "#161616" // Text on color
,
base07: "#000000" // Text inverse
,
base08: "#da1e28" // Red
,
base09: "#d12771" // Magenta
,
base0A: "#198038" // Green
,
base0B: "#8a3ffc" // Purple
,
base0C: "#007d79" // Cyan
,
base0D: "#0f62fe" // Blue
,
base0E: "#8a3ffc" // Purple (accent)
,
base0F: "#005d5d" // Teal
})
}

View File

@@ -0,0 +1,60 @@
pragma Singleton
import Quickshell
import QtQuick
Singleton {
readonly property color background: "#13140c"
readonly property color error: "#ffb4ab"
readonly property color error_container: "#93000a"
readonly property color inverse_on_surface: "#313128"
readonly property color inverse_primary: "#5d631c"
readonly property color inverse_surface: "#e5e3d6"
readonly property color on_background: "#e5e3d6"
readonly property color on_error: "#690005"
readonly property color on_error_container: "#ffdad6"
readonly property color on_primary: "#2f3300"
readonly property color on_primary_container: "#e2e993"
readonly property color on_primary_fixed: "#1b1d00"
readonly property color on_primary_fixed_variant: "#454b03"
readonly property color on_secondary: "#30321a"
readonly property color on_secondary_container: "#e4e5c1"
readonly property color on_secondary_fixed: "#1b1d07"
readonly property color on_secondary_fixed_variant: "#47492e"
readonly property color on_surface: "#e5e3d6"
readonly property color on_surface_variant: "#c8c7b7"
readonly property color on_tertiary: "#07372c"
readonly property color on_tertiary_container: "#beecdc"
readonly property color on_tertiary_fixed: "#002019"
readonly property color on_tertiary_fixed_variant: "#234e42"
readonly property color outline: "#929182"
readonly property color outline_variant: "#47483b"
readonly property color primary: "#c5cc7a"
readonly property color primary_container: "#454b03"
readonly property color primary_fixed: "#e2e993"
readonly property color primary_fixed_dim: "#c5cc7a"
readonly property color scrim: "#000000"
readonly property color secondary: "#c8c9a6"
readonly property color secondary_container: "#47492e"
readonly property color secondary_fixed: "#e4e5c1"
readonly property color secondary_fixed_dim: "#c8c9a6"
readonly property color shadow: "#000000"
readonly property color surface: "#13140c"
readonly property color surface_bright: "#3a3a31"
readonly property color surface_container: "#202018"
readonly property color surface_container_high: "#2a2a22"
readonly property color surface_container_highest: "#35352c"
readonly property color surface_container_low: "#1c1c14"
readonly property color surface_container_lowest: "#0e0f08"
readonly property color surface_dim: "#13140c"
readonly property color surface_tint: "#c5cc7a"
readonly property color surface_variant: "#47483b"
readonly property color tertiary: "#a3d0c0"
readonly property color tertiary_container: "#234e42"
readonly property color tertiary_fixed: "#beecdc"
readonly property color tertiary_fixed_dim: "#a3d0c0"
function withAlpha(color: color, alpha: real): color {
return Qt.rgba(color.r, color.g, color.b, alpha);
}
}

View File

@@ -0,0 +1,7 @@
{
"isDarkTheme": true,
"avatarSource": "/home/imxyy/Pictures/icon.jpg",
"weatherLocation": "Dinslaken",
"displayTime": 6000,
"videoPath": "~/Videos/"
}

View File

@@ -0,0 +1,35 @@
import QtQuick
import QtQuick.Effects
import "root:/Data" as Data
import "root:/Widgets/System" as System
import "root:/Widgets/Calendar" as Calendar
// Vertical sidebar layout
Rectangle {
id: bar
// Clean bar background
color: Data.ThemeManager.bgColor
// Workspace indicator at top
System.NiriWorkspaces {
id: workspaceIndicator
anchors {
top: parent.top
horizontalCenter: parent.horizontalCenter
horizontalCenterOffset: Data.Settings.borderWidth / 2
topMargin: 20
}
}
// Clock at bottom
Calendar.Clock {
id: clockWidget
anchors {
bottom: parent.bottom
horizontalCenter: parent.horizontalCenter
horizontalCenterOffset: Data.Settings.borderWidth / 2
bottomMargin: 20
}
}
}

View File

@@ -0,0 +1,575 @@
import QtQuick
import QtQuick.Shapes
import Qt5Compat.GraphicalEffects
import QtQuick.Effects
import "root:/Data" as Data
// Screen border with shadow effects
Shape {
id: borderShape
// Border dimensions
property real borderWidth: Data.Settings.borderWidth
property real radius: Data.Settings.cornerRadius
property real innerX: borderWidth
property real innerY: borderWidth
property real innerWidth: borderShape.width - (borderWidth * 2)
property real innerHeight: borderShape.height - (borderWidth * 2)
// Widget references for shadow positioning
property var workspaceIndicator: null
property var volumeOSD: null
property var clockWidget: null
// Initialization state to prevent ShaderEffect warnings
property bool effectsReady: false
// Burst effect properties - controlled by workspace indicator
property real masterProgress: workspaceIndicator ? workspaceIndicator.masterProgress : 0.0
property bool effectsActive: workspaceIndicator ? workspaceIndicator.effectsActive : false
property color effectColor: workspaceIndicator ? workspaceIndicator.effectColor : Data.ThemeManager.accent
// Delay graphics effects until component is fully loaded
Timer {
id: initTimer
interval: 100
running: true
onTriggered: borderShape.effectsReady = true
}
// Burst effect overlays (DISABLED - using unified overlay)
Item {
id: burstEffects
anchors.fill: parent
visible: false // Disabled in favor of unified overlay
z: 5
}
// Individual widget shadows (positioned separately)
// Workspace indicator shadow
Shape {
id: workspaceDropShadow
visible: borderShape.workspaceIndicator !== null
x: borderShape.workspaceIndicator ? borderShape.workspaceIndicator.x : 0 // Exact match
y: borderShape.workspaceIndicator ? borderShape.workspaceIndicator.y : 0
width: borderShape.workspaceIndicator ? borderShape.workspaceIndicator.width : 0 // Exact match
height: borderShape.workspaceIndicator ? borderShape.workspaceIndicator.height : 0
z: -1
layer.enabled: borderShape.workspaceIndicator !== null
layer.effect: DropShadow {
transparentBorder: true
horizontalOffset: 1
verticalOffset: 1
radius: 12 + (effectsActive && Data.Settings.workspaceGlowEnabled ? Math.sin(masterProgress * Math.PI) * 4 : 0)
samples: 25
color: {
if (!effectsActive)
return Qt.rgba(0, 0, 0, 0.4);
if (!Data.Settings.workspaceGlowEnabled)
return Qt.rgba(0, 0, 0, 0.4);
// Use accent color directly with reduced intensity
const intensity = Math.sin(masterProgress * Math.PI) * 0.4;
return Qt.rgba(effectColor.r * intensity + 0.08, effectColor.g * intensity + 0.08, effectColor.b * intensity + 0.08, 0.4 + intensity * 0.2);
}
cached: true
spread: 0.2 + (effectsActive && Data.Settings.workspaceGlowEnabled ? Math.sin(masterProgress * Math.PI) * 0.15 : 0)
}
ShapePath {
strokeWidth: 0
fillColor: "black"
startX: 12
startY: 0
// Right side - standard rounded corners
PathLine {
x: workspaceDropShadow.width - 16
y: 0
}
PathArc {
x: workspaceDropShadow.width
y: 16
radiusX: 16
radiusY: 16
direction: PathArc.Clockwise
}
PathLine {
x: workspaceDropShadow.width
y: workspaceDropShadow.height - 16
}
PathArc {
x: workspaceDropShadow.width - 16
y: workspaceDropShadow.height
radiusX: 16
radiusY: 16
direction: PathArc.Clockwise
}
PathLine {
x: 12
y: workspaceDropShadow.height
}
// Left side - concave curves for border integration
PathLine {
x: 0
y: workspaceDropShadow.height - 12
}
PathArc {
x: 12
y: workspaceDropShadow.height - 24
radiusX: 12
radiusY: 12
direction: PathArc.Clockwise
}
PathLine {
x: 12
y: 24
}
PathArc {
x: 0
y: 12
radiusX: 12
radiusY: 12
direction: PathArc.Clockwise
}
PathLine {
x: 12
y: 0
}
}
}
// Volume OSD shadow
Rectangle {
id: volumeOsdDropShadow
visible: borderShape.volumeOSD !== null && borderShape.volumeOSD.visible
opacity: borderShape.volumeOSD ? borderShape.volumeOSD.opacity : 0
x: parent.width - 45
y: (parent.height - 250) / 2
width: 45
height: 250
color: "black"
topLeftRadius: 20
bottomLeftRadius: 20
topRightRadius: 0
bottomRightRadius: 0
z: -1
// Sync opacity animations with volume OSD
Behavior on opacity {
NumberAnimation {
duration: 300
easing.type: Easing.OutCubic
}
}
layer.enabled: borderShape.volumeOSD !== null
layer.effect: DropShadow {
transparentBorder: true
horizontalOffset: -1
verticalOffset: 1
radius: 12 // Much more subtle
samples: 25
color: Qt.rgba(0, 0, 0, 0.4) // Very light shadow
cached: false
spread: 0.2 // Minimal spread
}
}
// Clock shadow
Rectangle {
id: clockDropShadow
visible: borderShape.clockWidget !== null
x: borderShape.clockWidget ? borderShape.clockWidget.x : 0
y: borderShape.clockWidget ? borderShape.clockWidget.y : 0
width: borderShape.clockWidget ? borderShape.clockWidget.width : 0
height: borderShape.clockWidget ? borderShape.clockWidget.height : 0
color: "black"
topLeftRadius: 0
topRightRadius: borderShape.clockWidget ? borderShape.clockWidget.height / 2 : 16
bottomLeftRadius: 0
bottomRightRadius: 0
z: -2 // Lower z-index to render behind border corners
layer.enabled: borderShape.clockWidget !== null
layer.effect: DropShadow {
transparentBorder: true
horizontalOffset: 1
verticalOffset: -1
radius: 12 // Much more subtle
samples: 25
color: Qt.rgba(0, 0, 0, 0.4) // Very light shadow
cached: false
spread: 0.2 // Minimal spread
}
}
// Shadow rendering source (hidden)
Item {
id: shadowSource
anchors.fill: parent
visible: false
Shape {
id: borderShadowShape
anchors.fill: parent
layer.enabled: true
layer.samples: 4
ShapePath {
fillColor: "black"
strokeWidth: 0
fillRule: ShapePath.OddEvenFill
// Outer rectangle (full screen)
PathMove {
x: 0
y: 0
}
PathLine {
x: shadowSource.width
y: 0
}
PathLine {
x: shadowSource.width
y: shadowSource.height
}
PathLine {
x: 0
y: shadowSource.height
}
PathLine {
x: 0
y: 0
}
// Inner rounded cutout creates border
PathMove {
x: borderShape.innerX + borderShape.radius
y: borderShape.innerY
}
PathLine {
x: borderShape.innerX + borderShape.innerWidth - borderShape.radius
y: borderShape.innerY
}
PathArc {
x: borderShape.innerX + borderShape.innerWidth
y: borderShape.innerY + borderShape.radius
radiusX: borderShape.radius
radiusY: borderShape.radius
direction: PathArc.Clockwise
}
PathLine {
x: borderShape.innerX + borderShape.innerWidth
y: borderShape.innerY + borderShape.innerHeight - borderShape.radius
}
PathArc {
x: borderShape.innerX + borderShape.innerWidth - borderShape.radius
y: borderShape.innerY + borderShape.innerHeight
radiusX: borderShape.radius
radiusY: borderShape.radius
direction: PathArc.Clockwise
}
PathLine {
x: borderShape.innerX + borderShape.radius
y: borderShape.innerY + borderShape.innerHeight
}
PathArc {
x: borderShape.innerX
y: borderShape.innerY + borderShape.innerHeight - borderShape.radius
radiusX: borderShape.radius
radiusY: borderShape.radius
direction: PathArc.Clockwise
}
PathLine {
x: borderShape.innerX
y: borderShape.innerY + borderShape.radius
}
PathArc {
x: borderShape.innerX + borderShape.radius
y: borderShape.innerY
radiusX: borderShape.radius
radiusY: borderShape.radius
direction: PathArc.Clockwise
}
}
}
// Workspace indicator shadow with concave curves
Shape {
id: workspaceShadowShape
visible: borderShape.workspaceIndicator !== null
x: borderShape.workspaceIndicator ? borderShape.workspaceIndicator.x : 0 // Exact match
y: borderShape.workspaceIndicator ? borderShape.workspaceIndicator.y : 0
width: borderShape.workspaceIndicator ? borderShape.workspaceIndicator.width : 0 // Exact match
height: borderShape.workspaceIndicator ? borderShape.workspaceIndicator.height : 0
preferredRendererType: Shape.CurveRenderer
layer.enabled: borderShape.workspaceIndicator !== null
layer.samples: 8
layer.effect: DropShadow {
transparentBorder: true
horizontalOffset: 2
verticalOffset: 3
radius: 25 + (effectsActive && Data.Settings.workspaceGlowEnabled ? Math.sin(masterProgress * Math.PI) * 6 : 0)
samples: 40
color: {
if (!effectsActive)
return Qt.rgba(0, 0, 0, 0.8);
if (!Data.Settings.workspaceGlowEnabled)
return Qt.rgba(0, 0, 0, 0.8);
// Accent color glow with reduced intensity
const intensity = Math.sin(masterProgress * Math.PI) * 0.3;
return Qt.rgba(effectColor.r * intensity + 0.1, effectColor.g * intensity + 0.1, effectColor.b * intensity + 0.1, 0.6 + intensity * 0.15);
}
cached: false
spread: 0.5 + (effectsActive && Data.Settings.workspaceGlowEnabled ? Math.sin(masterProgress * Math.PI) * 0.2 : 0)
}
ShapePath {
strokeWidth: 0
fillColor: "black"
strokeColor: "black"
startX: 12
startY: 0
// Right side - standard rounded corners
PathLine {
x: workspaceShadowShape.width - 16
y: 0
}
PathArc {
x: workspaceShadowShape.width
y: 16
radiusX: 16
radiusY: 16
direction: PathArc.Clockwise
}
PathLine {
x: workspaceShadowShape.width
y: workspaceShadowShape.height - 16
}
PathArc {
x: workspaceShadowShape.width - 16
y: workspaceShadowShape.height
radiusX: 16
radiusY: 16
direction: PathArc.Clockwise
}
PathLine {
x: 12
y: workspaceShadowShape.height
}
// Left side - concave curves for border integration
PathLine {
x: 0
y: workspaceShadowShape.height - 12
}
PathArc {
x: 12
y: workspaceShadowShape.height - 24
radiusX: 12
radiusY: 12
direction: PathArc.Clockwise
}
PathLine {
x: 12
y: 24
}
PathArc {
x: 0
y: 12
radiusX: 12
radiusY: 12
direction: PathArc.Clockwise
}
PathLine {
x: 12
y: 0
}
}
}
// Volume OSD shadow
Rectangle {
id: volumeOsdShadowShape
visible: borderShape.volumeOSD !== null && borderShape.volumeOSD.visible
x: shadowSource.width - 45
y: (shadowSource.height - 250) / 2
width: 45
height: 250
color: "black"
topLeftRadius: 20
bottomLeftRadius: 20
topRightRadius: 0
bottomRightRadius: 0
layer.enabled: borderShape.volumeOSD !== null && borderShape.volumeOSD.visible
layer.effect: DropShadow {
transparentBorder: true
horizontalOffset: -2 // Shadow to the left for right-side widget
verticalOffset: 3
radius: 25
samples: 40
color: Qt.rgba(0, 0, 0, 0.8)
cached: false
spread: 0.5
}
}
// Clock shadow
Rectangle {
id: clockShadowShape
visible: borderShape.clockWidget !== null
x: borderShape.clockWidget ? borderShape.clockWidget.x : 0
y: borderShape.clockWidget ? borderShape.clockWidget.y : 0
width: borderShape.clockWidget ? borderShape.clockWidget.width : 0
height: borderShape.clockWidget ? borderShape.clockWidget.height : 0
color: "black"
topLeftRadius: 0
topRightRadius: borderShape.clockWidget ? borderShape.clockWidget.height / 2 : 16
bottomLeftRadius: 0
bottomRightRadius: 0
layer.enabled: borderShape.clockWidget !== null
layer.effect: DropShadow {
transparentBorder: true
horizontalOffset: 2
verticalOffset: -2 // Shadow upward for bottom widget
radius: 25
samples: 40
color: Qt.rgba(0, 0, 0, 0.8)
cached: false
spread: 0.5
}
}
}
// Apply shadow effect to entire border shape
layer.enabled: true
layer.samples: 8
layer.smooth: true
layer.effect: DropShadow {
transparentBorder: true
horizontalOffset: 1
verticalOffset: 2
radius: 30 // Slightly less dramatic
samples: 45
color: Qt.rgba(0, 0, 0, 0.75) // A bit lighter
cached: false
spread: 0.5 // Less spread
}
// Main border shape
ShapePath {
fillColor: Data.ThemeManager.bgColor
strokeWidth: 0
fillRule: ShapePath.OddEvenFill
// Outer rectangle
PathMove {
x: 0
y: 0
}
PathLine {
x: borderShape.width
y: 0
}
PathLine {
x: borderShape.width
y: borderShape.height
}
PathLine {
x: 0
y: borderShape.height
}
PathLine {
x: 0
y: 0
}
// Inner rounded cutout
PathMove {
x: borderShape.innerX + borderShape.radius
y: borderShape.innerY
}
PathLine {
x: borderShape.innerX + borderShape.innerWidth - borderShape.radius
y: borderShape.innerY
}
PathArc {
x: borderShape.innerX + borderShape.innerWidth
y: borderShape.innerY + borderShape.radius
radiusX: borderShape.radius
radiusY: borderShape.radius
direction: PathArc.Clockwise
}
PathLine {
x: borderShape.innerX + borderShape.innerWidth
y: borderShape.innerY + borderShape.innerHeight - borderShape.radius
}
PathArc {
x: borderShape.innerX + borderShape.innerWidth - borderShape.radius
y: borderShape.innerY + borderShape.innerHeight
radiusX: borderShape.radius
radiusY: borderShape.radius
direction: PathArc.Clockwise
}
PathLine {
x: borderShape.innerX + borderShape.radius
y: borderShape.innerY + borderShape.innerHeight
}
PathArc {
x: borderShape.innerX
y: borderShape.innerY + borderShape.innerHeight - borderShape.radius
radiusX: borderShape.radius
radiusY: borderShape.radius
direction: PathArc.Clockwise
}
PathLine {
x: borderShape.innerX
y: borderShape.innerY + borderShape.radius
}
PathArc {
x: borderShape.innerX + borderShape.radius
y: borderShape.innerY
radiusX: borderShape.radius
radiusY: borderShape.radius
direction: PathArc.Clockwise
}
}
}

View File

@@ -0,0 +1,302 @@
import QtQuick
import QtQuick.Shapes
import Quickshell
import Quickshell.Wayland
import Qt5Compat.GraphicalEffects
import "root:/Data" as Data
import "root:/Widgets/System" as System
import "root:/Core" as Core
import "root:/Widgets" as Widgets
import "root:/Widgets/Notifications" as Notifications
import "root:/Widgets/ControlPanel" as ControlPanel
// Desktop with borders and UI widgets
Scope {
id: desktop
property var shell
property var notificationService
// Desktop UI layer per screen
Variants {
model: Quickshell.screens
PanelWindow {
required property var modelData
screen: modelData
implicitWidth: Screen.width
implicitHeight: Screen.height
color: "transparent"
exclusiveZone: 0
WlrLayershell.namespace: "quickshell-desktop"
// Interactive mask for workspace indicator only
mask: Region {
item: workspaceIndicator
}
anchors {
top: true
left: true
bottom: true
right: true
}
// Workspace indicator at left border
System.NiriWorkspaces {
id: workspaceIndicator
anchors {
left: parent.left
verticalCenter: parent.verticalCenter
leftMargin: Data.Settings.borderWidth
}
z: 10
width: 32
}
// Volume OSD at right border (primary screen only)
System.OSD {
id: osd
shell: desktop.shell
visible: modelData === Quickshell.primaryScreen
anchors {
right: parent.right
verticalCenter: parent.verticalCenter
rightMargin: Data.Settings.borderWidth
}
z: 10
}
// Widget shadows (positioned behind border for proper layering)
// Workspace indicator shadow
Rectangle {
id: workspaceShadow
visible: workspaceIndicator !== null
x: workspaceIndicator.x
y: workspaceIndicator.y
width: workspaceIndicator.width
height: workspaceIndicator.height
color: "black"
radius: 16
z: -10 // Behind border
layer.enabled: true
layer.effect: DropShadow {
transparentBorder: true
horizontalOffset: 2
verticalOffset: 2
radius: 8 + (workspaceIndicator.effectsActive && Data.Settings.workspaceGlowEnabled ? Math.sin(workspaceIndicator.masterProgress * Math.PI) * 3 : 0)
samples: 17
color: {
if (!workspaceIndicator.effectsActive)
return Qt.rgba(0, 0, 0, 0.3);
if (!Data.Settings.workspaceGlowEnabled)
return Qt.rgba(0, 0, 0, 0.3);
// Use accent color glow with reduced intensity
const intensity = Math.sin(workspaceIndicator.masterProgress * Math.PI) * 0.3;
return Qt.rgba(workspaceIndicator.effectColor.r * intensity + 0.05, workspaceIndicator.effectColor.g * intensity + 0.05, workspaceIndicator.effectColor.b * intensity + 0.05, 0.3 + intensity * 0.15);
}
cached: true
spread: 0.1 + (workspaceIndicator.effectsActive && Data.Settings.workspaceGlowEnabled ? Math.sin(workspaceIndicator.masterProgress * Math.PI) * 0.1 : 0)
}
}
// Clock widget shadow
Rectangle {
id: clockShadow
visible: clockWidget !== null
x: clockWidget.x
y: clockWidget.y
width: clockWidget.width
height: clockWidget.height
color: "black"
topLeftRadius: 0
topRightRadius: clockWidget.height / 2
bottomLeftRadius: 0
bottomRightRadius: 0
z: -10 // Behind border
layer.enabled: true
layer.effect: DropShadow {
transparentBorder: true
horizontalOffset: 1
verticalOffset: -1
radius: 8
samples: 17
color: Qt.rgba(0, 0, 0, 0.3)
cached: true
spread: 0.1
}
}
// Border background with shadow
Border {
id: screenBorder
anchors.fill: parent
workspaceIndicator: workspaceIndicator
volumeOSD: volumeOsd
clockWidget: clockWidget
z: -5 // Behind UI elements to prevent shadow from covering control panel
}
// Unified Wave Overlay - simple burst effect
Item {
id: waveOverlay
anchors.fill: parent
visible: workspaceIndicator.effectsActive && Data.Settings.workspaceBurstEnabled
z: 15
property real progress: workspaceIndicator.masterProgress
property color waveColor: workspaceIndicator.effectColor
// Workspace indicator burst effects
Item {
x: workspaceIndicator.x
y: workspaceIndicator.y
width: workspaceIndicator.width
height: workspaceIndicator.height
// Expanding pill burst - positioned at current workspace index (mimics pill shape)
Rectangle {
x: parent.width / 2 - width / 2
y: {
// Find current workspace index directly from currentWorkspace
let focusedIndex = 0;
for (let i = 0; i < workspaceIndicator.workspaces.count; i++) {
const workspace = workspaceIndicator.workspaces.get(i);
if (workspace && workspace.id === workspaceIndicator.currentWorkspace) {
focusedIndex = i;
break;
}
}
// Calculate position accounting for Column centering and pill sizes
let cumulativeHeight = 0;
for (let i = 0; i < focusedIndex; i++) {
const ws = workspaceIndicator.workspaces.get(i);
cumulativeHeight += (ws && ws.isFocused ? 36 : 22) + 6; // pill height + spacing
}
// Current pill height
const currentWs = workspaceIndicator.workspaces.get(focusedIndex);
const currentPillHeight = (currentWs && currentWs.isFocused ? 36 : 22);
// Column is centered, so start from center and calculate offset
const columnHeight = parent.height - 24; // Total available height minus padding
const columnTop = 12; // Top padding
return columnTop + cumulativeHeight + currentPillHeight / 2 - height / 2;
}
width: 20 + waveOverlay.progress * 30
height: 36 + waveOverlay.progress * 20 // Pill-like height
radius: width / 2 // Pill-like rounded shape
color: "transparent"
border.width: 2
border.color: Qt.rgba(waveOverlay.waveColor.r, waveOverlay.waveColor.g, waveOverlay.waveColor.b, 1.0 - waveOverlay.progress)
opacity: Math.max(0, 1.0 - waveOverlay.progress)
}
// Secondary expanding pill burst - positioned at current workspace index
Rectangle {
x: parent.width / 2 - width / 2
y: {
// Find current workspace index directly from currentWorkspace
let focusedIndex = 0;
for (let i = 0; i < workspaceIndicator.workspaces.count; i++) {
const workspace = workspaceIndicator.workspaces.get(i);
if (workspace && workspace.id === workspaceIndicator.currentWorkspace) {
focusedIndex = i;
break;
}
}
// Calculate position accounting for Column centering and pill sizes
let cumulativeHeight = 0;
for (let i = 0; i < focusedIndex; i++) {
const ws = workspaceIndicator.workspaces.get(i);
cumulativeHeight += (ws && ws.isFocused ? 36 : 22) + 6; // pill height + spacing
}
// Current pill height
const currentWs = workspaceIndicator.workspaces.get(focusedIndex);
const currentPillHeight = (currentWs && currentWs.isFocused ? 36 : 22);
// Column is centered, so start from center and calculate offset
const columnHeight = parent.height - 24; // Total available height minus padding
const columnTop = 12; // Top padding
return columnTop + cumulativeHeight + currentPillHeight / 2 - height / 2;
}
width: 18 + waveOverlay.progress * 45
height: 30 + waveOverlay.progress * 35 // Pill-like height
radius: width / 2 // Pill-like rounded shape
color: "transparent"
border.width: 1.5
border.color: Qt.rgba(waveOverlay.waveColor.r, waveOverlay.waveColor.g, waveOverlay.waveColor.b, 0.6)
opacity: Math.max(0, 0.8 - waveOverlay.progress * 1.2)
visible: waveOverlay.progress > 0.2
}
}
}
// Clock at bottom-left corner
Widgets.Clock {
id: clockWidget
anchors {
bottom: parent.bottom
left: parent.left
bottomMargin: Data.Settings.borderWidth
leftMargin: Data.Settings.borderWidth
}
z: 10
}
// Notification popups (primary screen only)
Notifications.Notification {
id: notificationPopup
visible: (modelData === (Quickshell.primaryScreen || Quickshell.screens[0])) && calculatedHeight > 20
anchors {
top: parent.top
right: parent.right
rightMargin: Data.Settings.borderWidth + 20
topMargin: 0
}
width: 420
height: calculatedHeight
shell: desktop.shell
notificationServer: desktop.notificationService ? desktop.notificationService.notificationServer : null
z: 15
Component.onCompleted: {
let targetScreen = Quickshell.primaryScreen || Quickshell.screens[0];
if (modelData === targetScreen) {
desktop.shell.notificationWindow = notificationPopup;
}
}
}
// UI overlay layer for modal components
Item {
id: uiLayer
anchors.fill: parent
z: 20
ControlPanel.ControlPanel {
id: controlPanelComponent
shell: desktop.shell
}
}
}
}
// Handle dynamic screen configuration changes
Connections {
target: Quickshell
function onScreensChanged() {
// Screen changes handled by Variants automatically
}
}
}

View File

@@ -0,0 +1,394 @@
import QtQuick
import Quickshell
import Quickshell.Io
// App launcher service - discovers and manages applications
Item {
id: appService
property var applications: []
property bool isLoading: false
// Categories for apps
property var categories: {
"AudioVideo": "🎵",
"Audio": "🎵",
"Video": "🎬",
"Development": "💻",
"Education": "📚",
"Game": "🎮",
"Graphics": "🎨",
"Network": "🌐",
"Office": "📄",
"Science": "🔬",
"Settings": "⚙️",
"System": "🔧",
"Utility": "🛠️",
"Other": "📦"
}
property string userName: ""
property string homeDirectory: ""
property bool userInfoLoaded: false
property var currentApp: ({})
property var pendingSearchPaths: []
Component.onCompleted: {
// First get user info, then load applications
loadUserInfo();
}
function loadUserInfo() {
userNameProcess.running = true;
}
Process {
id: userNameProcess
command: ["whoami"]
running: false
stdout: SplitParser {
splitMarker: "\n"
onRead: line => {
if (line.trim()) {
userName = line.trim();
}
}
}
onExited: {
// Now get home directory
homeDirProcess.running = true;
}
}
Process {
id: homeDirProcess
command: ["sh", "-c", "echo $HOME"]
running: false
stdout: SplitParser {
splitMarker: "\n"
onRead: line => {
if (line.trim()) {
homeDirectory = line.trim();
}
}
}
onExited: {
// Now we have user info, start loading applications
userInfoLoaded = true;
loadApplications();
}
}
function loadApplications() {
if (!userInfoLoaded) {
console.log("User info not loaded yet, skipping application scan");
return;
}
isLoading = true;
applications = [];
console.log("DEBUG: Starting application scan with user:", userName, "home:", homeDirectory);
// Comprehensive search paths for maximum Linux compatibility
appService.pendingSearchPaths = [
// User-specific locations (highest priority)
homeDirectory + "/.local/share/applications/",
// Standard FreeDesktop.org locations
"/usr/share/applications/", "/usr/local/share/applications/",
// Flatpak locations
"/var/lib/flatpak/exports/share/applications/", homeDirectory + "/.local/share/flatpak/exports/share/applications/",
// Snap locations
"/var/lib/snapd/desktop/applications/", "/snap/bin/",
// AppImage locations (common user directories)
homeDirectory + "/Applications/", homeDirectory + "/AppImages/",
// Distribution-specific paths
"/opt/*/share/applications/" // For manually installed software
, "/usr/share/applications/kde4/" // KDE4 legacy
,
// NixOS-specific (will be ignored on non-NixOS systems)
"/run/current-system/sw/share/applications/", "/etc/profiles/per-user/" + userName + "/share/applications/"];
console.log("DEBUG: Starting with essential paths:", JSON.stringify(appService.pendingSearchPaths));
// Add XDG and home-manager paths
getXdgDataDirs.running = true;
}
Process {
id: getXdgDataDirs
command: ["sh", "-c", "echo $XDG_DATA_DIRS"]
running: false
stdout: SplitParser {
splitMarker: "\n"
onRead: line => {
if (line.trim()) {
var xdgDirs = line.trim().split(":");
for (var i = 0; i < xdgDirs.length; i++) {
if (xdgDirs[i].trim()) {
var xdgPath = xdgDirs[i].trim() + "/applications/";
if (appService.pendingSearchPaths.indexOf(xdgPath) === -1) {
appService.pendingSearchPaths.push(xdgPath);
console.log("DEBUG: Added XDG path:", xdgPath);
}
}
}
}
}
}
onExited: {
// Now add home-manager path
getHomeManagerPaths.running = true;
}
}
Process {
id: getHomeManagerPaths
command: ["sh", "-c", "find /nix/store -maxdepth 1 -name '*home-manager-path*' -type d 2>/dev/null | head -1"]
running: false
stdout: SplitParser {
splitMarker: "\n"
onRead: line => {
if (line.trim()) {
var homeManagerPath = line.trim() + "/share/applications/";
appService.pendingSearchPaths.push(homeManagerPath);
console.log("DEBUG: Added home-manager path:", homeManagerPath);
}
}
}
onExited: {
// CRITICAL: Always ensure these essential directories are included
var essentialPaths = ["/run/current-system/sw/share/applications/", "/usr/share/applications/", "/usr/local/share/applications/"];
for (var i = 0; i < essentialPaths.length; i++) {
var path = essentialPaths[i];
if (appService.pendingSearchPaths.indexOf(path) === -1) {
appService.pendingSearchPaths.push(path);
console.log("DEBUG: Added missing essential path:", path);
}
}
// Start bulk parsing with all paths including XDG and home-manager
startBulkParsing(appService.pendingSearchPaths);
}
}
function startBulkParsing(searchPaths) {
// BULLETPROOF: Ensure critical system directories are always included
var criticalPaths = ["/run/current-system/sw/share/applications/", "/usr/share/applications/", "/usr/local/share/applications/"];
for (var i = 0; i < criticalPaths.length; i++) {
var path = criticalPaths[i];
if (searchPaths.indexOf(path) === -1) {
searchPaths.push(path);
console.log("DEBUG: BULLETPROOF: Added missing critical path:", path);
}
}
console.log("DEBUG: Final directories to scan:", searchPaths.join(", "));
// Single command to parse all .desktop files at once
// Only parse fields from the main [Desktop Entry] section, ignore [Desktop Action] sections
var cmd = 'for dir in ' + searchPaths.map(p => "'" + p + "'").join(" ") + '; do ' + 'if [ -d "$dir" ]; then ' + 'find "$dir" -name "*.desktop" 2>/dev/null | while read file; do ' + 'echo "===FILE:$file"; ' + 'sed -n \'/^\\[Desktop Entry\\]/,/^\\[.*\\]/{/^\\[Desktop Entry\\]/d; /^\\[.*\\]/q; /^Name=/p; /^Exec=/p; /^Icon=/p; /^Comment=/p; /^Categories=/p; /^Hidden=/p; /^NoDisplay=/p}\' "$file" 2>/dev/null || true; ' + 'done; ' + 'fi; ' + 'done';
bulkParseProcess.command = ["sh", "-c", cmd];
bulkParseProcess.running = true;
}
Process {
id: bulkParseProcess
running: false
stdout: SplitParser {
splitMarker: "\n"
onRead: line => {
if (line.startsWith("===FILE:")) {
// Start of new file
if (appService.currentApp.name && appService.currentApp.exec && !appService.currentApp.hidden && !appService.currentApp.noDisplay) {
applications.push(appService.currentApp);
}
appService.currentApp = {
name: "",
exec: "",
icon: "",
comment: "",
categories: [],
hidden: false,
noDisplay: false,
filePath: line.substring(8) // Remove "===FILE:" prefix
};
} else if (line.startsWith("Name=")) {
appService.currentApp.name = line.substring(5);
} else if (line.startsWith("Exec=")) {
appService.currentApp.exec = line.substring(5);
} else if (line.startsWith("Icon=")) {
appService.currentApp.icon = line.substring(5);
} else if (line.startsWith("Comment=")) {
appService.currentApp.comment = line.substring(8);
} else if (line.startsWith("Categories=")) {
appService.currentApp.categories = line.substring(11).split(";").filter(cat => cat.length > 0);
} else if (line === "Hidden=true") {
appService.currentApp.hidden = true;
} else if (line === "NoDisplay=true") {
appService.currentApp.noDisplay = true;
}
}
}
onStarted: {
appService.currentApp = {};
}
onExited: {
// Process the last app
if (appService.currentApp.name && appService.currentApp.exec && !appService.currentApp.hidden && !appService.currentApp.noDisplay) {
applications.push(appService.currentApp);
}
console.log("DEBUG: Before deduplication: Found", applications.length, "applications");
// Deduplicate applications - prefer user installations over system ones
var uniqueApps = {};
var finalApps = [];
for (var i = 0; i < applications.length; i++) {
var app = applications[i];
var key = app.name + "|" + app.exec.split(" ")[0]; // Use name + base command as key
if (!uniqueApps[key]) {
// First occurrence of this app
uniqueApps[key] = app;
finalApps.push(app);
} else {
// Duplicate found - check if this version should replace the existing one
var existing = uniqueApps[key];
var shouldReplace = false;
// Priority order (higher priority replaces lower):
// 1. User local applications (highest priority)
// 2. Home-manager applications
// 3. User profile applications
// 4. System applications (lowest priority)
if (app.filePath.includes("/.local/share/applications/")) {
shouldReplace = true; // User local always wins
} else if (app.filePath.includes("home-manager-path") && !existing.filePath.includes("/.local/share/applications/")) {
shouldReplace = true; // Home-manager beats system
} else if (app.filePath.includes("/home/") && !existing.filePath.includes("/.local/share/applications/") && !existing.filePath.includes("home-manager-path")) {
shouldReplace = true; // User profile beats system
}
if (shouldReplace) {
// Replace the existing app in finalApps array
for (var j = 0; j < finalApps.length; j++) {
if (finalApps[j] === existing) {
finalApps[j] = app;
uniqueApps[key] = app;
break;
}
}
}
// If not replacing, just ignore the duplicate
}
}
applications = finalApps;
console.log("DEBUG: After deduplication: Found", applications.length, "unique applications");
isLoading = false;
applicationsChanged();
}
}
function launchApplication(app) {
if (!app || !app.exec)
return;
// Clean up the exec command (remove field codes like %f, %F, %u, %U)
var cleanExec = app.exec.replace(/%[fFuU]/g, "").trim();
launchProcess.command = ["sh", "-c", cleanExec];
launchProcess.running = true;
console.log("Launching:", app.name, "with command:", cleanExec);
}
Process {
id: launchProcess
running: false
onExited: {
if (exitCode !== 0) {
console.log("Failed to launch application, exit code:", exitCode);
}
}
}
// Fuzzy search function
function fuzzySearch(query, apps) {
if (!query || query.length === 0) {
return apps;
}
query = query.toLowerCase();
return apps.filter(app => {
var searchText = (app.name + " " + app.comment).toLowerCase();
// Simple fuzzy matching - check if all characters of query appear in order
var queryIndex = 0;
for (var i = 0; i < searchText.length && queryIndex < query.length; i++) {
if (searchText[i] === query[queryIndex]) {
queryIndex++;
}
}
return queryIndex === query.length;
}).sort((a, b) => {
// Sort by relevance - exact matches first, then by name
var aName = a.name.toLowerCase();
var bName = b.name.toLowerCase();
var aExact = aName.includes(query);
var bExact = bName.includes(query);
if (aExact && !bExact)
return -1;
if (!aExact && bExact)
return 1;
return aName.localeCompare(bName);
});
}
function getCategoryIcon(app) {
if (!app.categories || app.categories.length === 0) {
return categories["Other"];
}
// Find the first matching category
for (var i = 0; i < app.categories.length; i++) {
var category = app.categories[i];
if (categories[category]) {
return categories[category];
}
}
return categories["Other"];
}
}

Some files were not shown because too many files have changed in this diff Show More