From 0cb936c75c0ef1a8ac9a5ff11cc5b3fa3b8625db Mon Sep 17 00:00:00 2001 From: Fernando Rodrigues Date: Tue, 10 Jun 2025 09:11:41 -0300 Subject: [PATCH 1/3] formatter-module: enable jsonfmt There will be several JSON files in the matrix-icons directory. To ensure all of them have a consistent style, we can use jsonfmt to automatically format all of them. Signed-off-by: Fernando Rodrigues --- formatter-module/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/formatter-module/default.nix b/formatter-module/default.nix index 567afc1..704ee12 100644 --- a/formatter-module/default.nix +++ b/formatter-module/default.nix @@ -11,6 +11,7 @@ inputs.self.library.defaultSystems ( enableDefaultExcludes = true; projectRootFile = "flake.nix"; programs = { + jsonfmt.enable = true; mdformat.enable = true; mdsh.enable = true; nixfmt.enable = true; From ed4d1df223c6d29540795daff1292bd0e6ba95a0 Mon Sep 17 00:00:00 2001 From: Fernando Rodrigues Date: Tue, 10 Jun 2025 09:11:41 -0300 Subject: [PATCH 2/3] matrix-icons: init at 0.1.0 A simple Typst builder to produce SVG matrix room icons. New rooms are automatically detected from their respective icon.json files. Signed-off-by: Fernando Rodrigues --- package-sets/top-level/matrix-icons/README.md | 29 +++++ package-sets/top-level/matrix-icons/main.typ | 91 ++++++++++++++ .../top-level/matrix-icons/package.nix | 113 ++++++++++++++++++ 3 files changed, 233 insertions(+) create mode 100644 package-sets/top-level/matrix-icons/README.md create mode 100644 package-sets/top-level/matrix-icons/main.typ create mode 100644 package-sets/top-level/matrix-icons/package.nix diff --git a/package-sets/top-level/matrix-icons/README.md b/package-sets/top-level/matrix-icons/README.md new file mode 100644 index 0000000..170c72a --- /dev/null +++ b/package-sets/top-level/matrix-icons/README.md @@ -0,0 +1,29 @@ +# NixOS Matrix Room Icons + +This directory contains the builder scripts and the sources that generate the icons for NixOS-managed Matrix rooms. + +## Creating a New Room Icon + +1. Create a new subdirectory inside the `rooms/` directory with your room's alias in the [nixos.org](https://matrix.to/#/#community:nixos.org) space. + +- For example, if your new room can be reached with the `#haskell:nixos.org` address, you would name the subdirectory `haskell`. + +2. Inside your new subdirectory, create a file named `icon.json`. This file determines how your icon will be generated from the default templates. + +- See the "`icon.json` Syntax" section below for more information on the valid fields for the `icon.json` file. + +3. Build your new icon with `nix build .#matrix-icons.your-room-name`. Following the same example above, you would build the `#haskell:nixos.org` room icon with `nix build .#matrix-icons.haskell`. + +- You can also build all room icons at once using `nix build .#matrix-icons`. + +## `icon.json` Syntax + + + +## Custom Assets + + + +## Examples + + diff --git a/package-sets/top-level/matrix-icons/main.typ b/package-sets/top-level/matrix-icons/main.typ new file mode 100644 index 0000000..49093bb --- /dev/null +++ b/package-sets/top-level/matrix-icons/main.typ @@ -0,0 +1,91 @@ +// Date must be set to none for deterministic builds +#set document(date: none) +#set page(margin: 0pt, width: 2048pt, height: 2048pt) + +#let data = json("final.json") +#let palette-colour(int) = if int == 0 { luma(0) } else if int == 1 { + luma(255) +} else if int == 2 { rgb("#5b7ec8") } else if int == 3 { + rgb("#87adfa") +} else if int == 4 { rgb("#5fb8f2") } else if int == 5 { + rgb("#aaa1f6") +} else if int == 6 { rgb("#e99861") } else if int == 7 { + rgb("#f08d94") +} else if int == 8 { rgb("#d991d2") } else if int == 9 { rgb("#6fc488") } + +#let icon( + type: none, + colours: none, + contents: none, +) = { + set page( + fill: palette-colour(if type == "standard" { colours.background } else { + colours.border + }), + background: { + if type == "standard" { + grid( + columns: 1, + rows: (992pt, 64pt, 992pt), + gutter: 0pt, + rect( + width: 100%, + height: 100%, + stroke: none, + inset: if contents.style == "text" { 128pt } else { 0pt }, + if contents.style == "text" { + text( + font: "Route 159", + weight: "bold", + fill: palette-colour(colours.text), + size: 800pt, + align(center + bottom, contents.text), + ) + } else if contents.style == "image" { + align(center + bottom, image( + { "icons/" + contents.image + ".svg" }, + height: 992pt, + fit: "contain", + )) + } else { panic("Invalid style: " + content.style) }, + ), + + rect(width: 100%, height: 100%, fill: palette-colour(colours.border)), + + rect( + width: 100%, + height: 100%, + fill: palette-colour(2), + inset: 0pt, + image( + "icons/nixos-logomark-white-flat-minimal.svg", + fit: "contain", + ), + ), + ) + } else { + circle( + radius: 768pt, + fill: palette-colour(colours.background), + inset: -224pt, + image({ "icons/" + contents.image + ".svg" }, fit: "contain"), + ) + } + }, + ) + pagebreak(weak: true) + // FIXME: For some reason, the icons aren't generated correctly if there isn't *something* in the first page. + text(fill: rgb("#00000000"), [.]) +} + +#if sys.inputs.singleIcon == "null" { + for room in data.values() { + icon(type: room.type, colours: room.colours, contents: room.contents) + } +} else { + icon( + type: data.at(sys.inputs.singleIcon).type, + colours: data.at(sys.inputs.singleIcon).colours, + contents: data.at(sys.inputs.singleIcon).contents, + ) +} diff --git a/package-sets/top-level/matrix-icons/package.nix b/package-sets/top-level/matrix-icons/package.nix new file mode 100644 index 0000000..ed95bd9 --- /dev/null +++ b/package-sets/top-level/matrix-icons/package.nix @@ -0,0 +1,113 @@ +{ + jq, + jura, + lib, + matrix-icons, + nixos-branding, + efficient-compression-tool, + route159, + symlinkJoin, + typix-lib, + + singleIcon ? null, +}: + +let + inherit (builtins) + readDir + ; + inherit (lib.asserts) + assertOneOf + ; + inherit (lib.attrsets) + attrNames + attrValues + genAttrs + removeAttrs + ; + inherit (lib.fileset) + toSource + unions + ; + inherit (typix-lib) + buildDeterministicTypstProject + ; + + typstSource = "main.typ"; + listOfRooms = attrNames (readDir ./rooms); +in + +assert assertOneOf "The selected room icon" singleIcon ([ null ] ++ listOfRooms); + +buildDeterministicTypstProject { + pname = "matrix-icons"; + version = "0.1.0"; + + src = toSource { + root = ./.; + fileset = unions [ ./main.typ ]; + }; + + nativeBuildInputs = [ + jq + efficient-compression-tool + ]; + + inherit typstSource; + + fontPaths = [ + "${jura}/share/fonts/truetype/jura" + "${route159}/share/fonts/opentype/route159" + ]; + + virtualPaths = [ + { + dest = "icons"; + src = "${symlinkJoin { + name = "helper-icons"; + paths = ( + attrValues ( + removeAttrs nixos-branding.artifacts.media-kit [ + "callPackage" + "newScope" + "overrideScope" + "packages" + "recurseForDerivations" + ] + ) + ); + postBuild = '' + find ${./rooms} -type f -name "*.svg" -exec cp {} $out \; + ''; + }}"; + } + ]; + + buildPhaseTypstCommand = '' + find ${./rooms} -type f -name icon.json -print0 | xargs -0 jq -n 'reduce inputs as $item ({}; . + { (input_filename | split("/")[4]): $item })' >> final.json + typst compile \ + --format png \ + --input singleIcon=${if (isNull singleIcon) then "null" else singleIcon} \ + ${typstSource} "{p}.png" + ''; + + installPhaseCommand = '' + mkdir $out + ${ + if (isNull singleIcon) then + '' + paste \ + <(jq -r 'keys[]' final.json) \ + <(find . -maxdepth 1 -type f -name '*.png' -printf '%f\n') \ + | while IFS=$'\t' read key png; do + mv -- "$png" "$out/$key.png" + done + '' + else + "mv 1.png $out/${singleIcon}.png" + } + ect -9 -keep --strip --strict $out + ''; + + passthru = genAttrs listOfRooms (name: matrix-icons.override { singleIcon = name; }); +} From 9669a739bdc5f39d0be9e2a5c2924e870b5e743f Mon Sep 17 00:00:00 2001 From: Fernando Rodrigues Date: Tue, 10 Jun 2025 09:11:41 -0300 Subject: [PATCH 3/3] matrix-icons: import existing rooms from nixos-artwork Signed-off-by: Fernando Rodrigues --- package-sets/top-level/matrix-icons/rooms/.gitignore | 1 + .../top-level/matrix-icons/rooms/arm/icon.json | 12 ++++++++++++ .../top-level/matrix-icons/rooms/dev/icon.json | 12 ++++++++++++ .../top-level/matrix-icons/rooms/kde/icon.json | 11 +++++++++++ .../top-level/matrix-icons/rooms/kde/kde.svg | 1 + .../top-level/matrix-icons/rooms/users/icon.json | 10 ++++++++++ 6 files changed, 47 insertions(+) create mode 100644 package-sets/top-level/matrix-icons/rooms/.gitignore create mode 100644 package-sets/top-level/matrix-icons/rooms/arm/icon.json create mode 100644 package-sets/top-level/matrix-icons/rooms/dev/icon.json create mode 100644 package-sets/top-level/matrix-icons/rooms/kde/icon.json create mode 100644 package-sets/top-level/matrix-icons/rooms/kde/kde.svg create mode 100644 package-sets/top-level/matrix-icons/rooms/users/icon.json diff --git a/package-sets/top-level/matrix-icons/rooms/.gitignore b/package-sets/top-level/matrix-icons/rooms/.gitignore new file mode 100644 index 0000000..e461c58 --- /dev/null +++ b/package-sets/top-level/matrix-icons/rooms/.gitignore @@ -0,0 +1 @@ +!*.svg diff --git a/package-sets/top-level/matrix-icons/rooms/arm/icon.json b/package-sets/top-level/matrix-icons/rooms/arm/icon.json new file mode 100644 index 0000000..92ad353 --- /dev/null +++ b/package-sets/top-level/matrix-icons/rooms/arm/icon.json @@ -0,0 +1,12 @@ +{ + "type": "standard", + "colours": { + "background": 1, + "border": 6, + "text": 4 + }, + "contents": { + "style": "text", + "text": "arm" + } +} diff --git a/package-sets/top-level/matrix-icons/rooms/dev/icon.json b/package-sets/top-level/matrix-icons/rooms/dev/icon.json new file mode 100644 index 0000000..acde874 --- /dev/null +++ b/package-sets/top-level/matrix-icons/rooms/dev/icon.json @@ -0,0 +1,12 @@ +{ + "type": "standard", + "colours": { + "background": 1, + "border": 3, + "text": 2 + }, + "contents": { + "style": "text", + "text": "dev" + } +} diff --git a/package-sets/top-level/matrix-icons/rooms/kde/icon.json b/package-sets/top-level/matrix-icons/rooms/kde/icon.json new file mode 100644 index 0000000..d3a8e4b --- /dev/null +++ b/package-sets/top-level/matrix-icons/rooms/kde/icon.json @@ -0,0 +1,11 @@ +{ + "type": "standard", + "colours": { + "background": 4, + "border": 1 + }, + "contents": { + "style": "image", + "image": "kde" + } +} diff --git a/package-sets/top-level/matrix-icons/rooms/kde/kde.svg b/package-sets/top-level/matrix-icons/rooms/kde/kde.svg new file mode 100644 index 0000000..ea3a8d8 --- /dev/null +++ b/package-sets/top-level/matrix-icons/rooms/kde/kde.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/package-sets/top-level/matrix-icons/rooms/users/icon.json b/package-sets/top-level/matrix-icons/rooms/users/icon.json new file mode 100644 index 0000000..557ad7b --- /dev/null +++ b/package-sets/top-level/matrix-icons/rooms/users/icon.json @@ -0,0 +1,10 @@ +{ + "type": "main", + "colours": { + "background": 1, + "border": 2 + }, + "contents": { + "image": "nixos-logomark-default-gradient-minimal" + } +}