diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..8392d15 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake \ No newline at end of file diff --git a/.gitignore b/.gitignore index 91fcc75..f4c87f6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ -node_modules/ +node_modules @types/ build/ -pnpm-lock.yaml *.log + +result +.direnv/ diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..bfe454e --- /dev/null +++ b/flake.lock @@ -0,0 +1,106 @@ +{ + "nodes": { + "ags": { + "inputs": { + "astal": [ + "astal" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1762046771, + "narHash": "sha256-baVZvZZN0t9F3fvVhxmQA1/oNykXGd/YhlF19JqCLc8=", + "owner": "aylur", + "repo": "ags", + "rev": "fe13af2daec716226ccdb3158606a8577853e0ff", + "type": "github" + }, + "original": { + "owner": "aylur", + "repo": "ags", + "type": "github" + } + }, + "astal": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1762012522, + "narHash": "sha256-ncEN4OVFM5M9VFc4oR3gOI5K8r99GcYxtU+Cf4Z8pbs=", + "owner": "aylur", + "repo": "astal", + "rev": "671d4229c798834190a50fb8b8d8addd19b529e9", + "type": "github" + }, + "original": { + "owner": "aylur", + "repo": "astal", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1762040540, + "narHash": "sha256-z5PlZ47j50VNF3R+IMS9LmzI5fYRGY/Z5O5tol1c9I4=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "0010412d62a25d959151790968765a70c436598b", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1761907660, + "narHash": "sha256-kJ8lIZsiPOmbkJypG+B5sReDXSD1KGu2VEPNqhRa/ew=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2fb006b87f04c4d3bdf08cfdbc7fab9c13d94a15", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1761765539, + "narHash": "sha256-b0yj6kfvO8ApcSE+QmA6mUfu8IYG6/uU28OFn4PaC8M=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "719359f4562934ae99f5443f20aa06c2ffff91fc", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "root": { + "inputs": { + "ags": "ags", + "astal": "astal", + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..7b8b954 --- /dev/null +++ b/flake.nix @@ -0,0 +1,60 @@ +{ + description = "Super cool desktop shell for Hyprland!"; + + inputs = { + flake-parts.url = "github:hercules-ci/flake-parts"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + astal = { + url = "github:aylur/astal"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + ags = { + url = "github:aylur/ags"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.astal.follows = "astal"; + }; + }; + + outputs = + inputs@{ flake-parts, ... }: + flake-parts.lib.mkFlake { inherit inputs; } { + imports = [ + # To import an internal flake module: ./other.nix + # To import an external flake module: + # 1. Add foo to inputs + # 2. Add foo as a parameter to the outputs function + # 3. Add here: foo.flakeModule + ]; + systems = [ + "x86_64-linux" + "aarch64-linux" + ]; + perSystem = + { + config, + self', + inputs', + pkgs, + system, + ... + }: + let + colorshell = pkgs.callPackage ./nix/package.nix { inherit inputs'; }; + in + { + packages = { + inherit colorshell; + default = colorshell; + }; + + devShells = import ./nix/devshell.nix { inherit self' pkgs; }; + }; + flake = { + passthru = { + inherit inputs; + }; + }; + }; +} diff --git a/nix/devshell.nix b/nix/devshell.nix new file mode 100644 index 0000000..6fd265c --- /dev/null +++ b/nix/devshell.nix @@ -0,0 +1,52 @@ +{ + self', + pkgs, +}: +let + colorshell = self'.packages.colorshell; + + packages = [ + ]; + + devPackages = with pkgs; [ + nodePackages.nodejs + pnpm + + # dev scripts + jq + + # pywal16 + pywal16 + imagemagick + ]; + + colorshellDeps = pkgs.stdenvNoCC.mkDerivation { + inherit (colorshell.pnpmDeps) name src; + inherit (colorshell) pnpmDeps sourceRoot; + + buildInputs = [ colorshell.npmConfigHook ]; + installPhase = '' + mkdir -p $out/lib + cp -rp node_modules $out/lib/node_modules + ''; + }; +in +{ + default = pkgs.mkShell { + inputsFrom = [ colorshell ]; + packages = devPackages ++ packages; + + shellHook = '' + NODE_MODULES_PATH="${colorshellDeps}/lib/node_modules" + if [ -L ./node_modules ] || [ -e ./node_modules ]; then + rm -rf ./node_modules + fi + echo "Linking $NODE_MODULES_PATH" to $PWD/node_modules... + ln -s $NODE_MODULES_PATH . + ''; + + passthru = { + inherit colorshellDeps; + }; + }; +} diff --git a/nix/package.nix b/nix/package.nix new file mode 100644 index 0000000..34568f4 --- /dev/null +++ b/nix/package.nix @@ -0,0 +1,159 @@ +{ + inputs', + lib, + stdenv, + stdenvNoCC, + pnpm_10, + buildNpmPackage, + wrapGAppsHook4, + gobject-introspection, + glib, + gjs, + libadwaita, +}: +let + packageJSON = lib.importJSON ../package.json; + pname = packageJSON.name; + version = packageJSON.version; + + # Cleaned sources from this repository + src = lib.fileset.toSource { + root = ../.; + fileset = lib.fileset.difference ../. ( + lib.fileset.unions [ + ../flake.nix + ../flake.lock + ./. + ] + ); + }; + + # Derivation building just the gresources file + colorshellResources = stdenv.mkDerivation { + pname = "${pname}-resources.gresource"; + inherit version; + + inherit src; + + buildInputs = [ + glib + ]; + + buildPhase = '' + runHook preBuild + + glib-compile-resources resources.gresource.xml \ + --sourcedir ./resources \ + --target resources.gresource + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + cp resources.gresource $out + + runHook postInstall + ''; + }; + + # Cleaned sources, with FHS paths patched out. + colorshellSrc = stdenvNoCC.mkDerivation { + pname = "${pname}-src"; + inherit version; + + inherit src; + + # Replace reference to ags FHS install path + postPatch = '' + substituteInPlace package.json pnpm-lock.yaml \ + --replace-fail "/usr/share/ags/js" "${inputs'.ags.packages.ags.jsPackage}" + ''; + + installPhase = '' + mkdir $out + cp -rp * $out + ''; + }; +in +buildNpmPackage (finalAttrs: { + inherit pname version; + + src = colorshellSrc; + sourceRoot = "${finalAttrs.src.name}"; + + npmConfigHook = pnpm_10.configHook; + npmDeps = finalAttrs.pnpmDeps; + pnpmDeps = pnpm_10.fetchDeps { + inherit (finalAttrs) + pname + version + src + sourceRoot + ; + + fetcherVersion = 2; + hash = "sha256-m/aPNvv26r0DUvRUR4TL2GwwAHKvEIkc8Nvlm/jpnPc="; + + # fetcher version 2 fails if there are no *-exec files in the output + preFixup = '' + touch $out/.dummy-exec + ''; + }; + + nativeBuildInputs = [ + wrapGAppsHook4 + gobject-introspection + inputs'.ags.packages.default + ]; + + buildInputs = [ + glib + gjs + libadwaita + inputs'.astal.packages.astal4 + inputs'.astal.packages.apps + inputs'.astal.packages.auth + inputs'.astal.packages.battery + inputs'.astal.packages.bluetooth + inputs'.astal.packages.hyprland + inputs'.astal.packages.io + inputs'.astal.packages.mpris + inputs'.astal.packages.network + inputs'.astal.packages.notifd + inputs'.astal.packages.tray + inputs'.astal.packages.wireplumber + ]; + + buildPhase = '' + runHook preBuild + + mkdir -p $out/bin + ags bundle ./src/app.ts $out/bin/${packageJSON.name} \ + --gtk 4 \ + --root ./src \ + --define "DEVEL=false" \ + --define "COLORSHELL_VERSION='${finalAttrs.version}'" \ + --define "GRESOURCES_FILE='${colorshellResources}'" + + runHook postBuild + ''; + + # the above buildPhase installs for us + dontInstall = true; + + preFixup = '' + gappsWrapperArgs+=( + --prefix PATH : ${ + lib.makeBinPath [ + # runtime executables + ] + } + ) + ''; + + passthru = { + resources = colorshellResources; + }; +}) diff --git a/package.json b/package.json index 8bd3832..8ff15aa 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "sync-config": "sh ./scripts/sync-config.sh" }, "devDependencies": { - "ags": "link:/usr/share/ags/js", + "ags": "file:/usr/share/ags/js", "gnim-utils": "github:retrozinndev/gnim-utils#1.0.0", "fuse.js": "^7.1.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..8979f1c --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,56 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + ags: + specifier: file:/usr/share/ags/js + version: file:../../../../usr/share/ags/js(gnim@1.8.2) + fuse.js: + specifier: ^7.1.0 + version: 7.1.0 + gnim-utils: + specifier: github:retrozinndev/gnim-utils#1.0.0 + version: https://codeload.github.com/retrozinndev/gnim-utils/tar.gz/8bfb7d21817ac91a639c3cc90f1b4f66eb990b1e(gnim@1.8.2) + +packages: + + ags@file:../../../../usr/share/ags/js: + resolution: {directory: ../../../../usr/share/ags/js, type: directory} + engines: {gjs: '>=1.79.0'} + os: [linux] + peerDependencies: + gnim: ^1.8.2 + + fuse.js@7.1.0: + resolution: {integrity: sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==} + engines: {node: '>=10'} + + gnim-utils@https://codeload.github.com/retrozinndev/gnim-utils/tar.gz/8bfb7d21817ac91a639c3cc90f1b4f66eb990b1e: + resolution: {tarball: https://codeload.github.com/retrozinndev/gnim-utils/tar.gz/8bfb7d21817ac91a639c3cc90f1b4f66eb990b1e} + version: 1.0.0 + peerDependencies: + gnim: ^1.8.2 + + gnim@1.8.2: + resolution: {integrity: sha512-VwvTLclraJPAhS//SzdlWNOdaA7xKqC7KkJpIq5jq9DKDTXPis5SCrExFxrcjtcujK+I2l4drNvoXp6s1G78NA==} + engines: {gjs: '>=1.79.0'} + +snapshots: + + ags@file:../../../../usr/share/ags/js(gnim@1.8.2): + dependencies: + gnim: 1.8.2 + + fuse.js@7.1.0: {} + + gnim-utils@https://codeload.github.com/retrozinndev/gnim-utils/tar.gz/8bfb7d21817ac91a639c3cc90f1b4f66eb990b1e(gnim@1.8.2): + dependencies: + gnim: 1.8.2 + + gnim@1.8.2: {} diff --git a/src/app.ts b/src/app.ts index b8608ec..361ca92 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,5 +1,5 @@ // thanks Aylur!! -import "/usr/share/ags/js/lib/overrides"; +import "ags/overrides"; import "./config"; import { PluginApps, @@ -168,7 +168,7 @@ you should use the socket in the XDG_RUNTIME_DIR/colorshell.sock for a faster re private init(): void { // load gresource from build-defined path try { - this.#gresource = Gio.Resource.load(GRESOURCES_FILE.split('/').filter(s => + const gresourcesPath: string = GRESOURCES_FILE.startsWith('/') ? GRESOURCES_FILE : (GRESOURCES_FILE.split('/').filter(s => s !== "" ).map(path => { // support environment variables at runtime @@ -179,9 +179,9 @@ you should use the socket in the XDG_RUNTIME_DIR/colorshell.sock for a faster re return env; } - return path; }).join('/')); + this.#gresource = Gio.Resource.load(gresourcesPath); Gio.resources_register(this.#gresource); // add icons