Compare commits

..

5 commits

Author SHA1 Message Date
a88ef1e8b2 Merge remote-tracking branch 'origin/main' 2026-08-21 14:44:16 +01:00
1d7bc04cf5 Merge branch 'worktree-yamis-survey' 2026-08-21 14:42:47 +01:00
1bea54f30c quickshell: tint YAMIS app icons to the wallpaper palette
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017EHJfY5Q72punsWX38nY1w
2026-08-21 14:40:02 +01:00
cb7b576a71 theming: YAMIS app icons under Papirus-Fred
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017EHJfY5Q72punsWX38nY1w
2026-08-21 14:25:34 +01:00
a0cd304e53 gaming: drop geary 2026-08-21 12:22:44 +01:00
3 changed files with 113 additions and 22 deletions

View file

@ -20,8 +20,6 @@
protonplus protonplus
]; ];
programs.geary.enable = true;
# Nova Pro Wireless base station: open up its vendor HID interface so # Nova Pro Wireless base station: open up its vendor HID interface so
# quickshell's ANC switcher can write to it directly (nova-anc script in # quickshell's ANC switcher can write to it directly (nova-anc script in
# settings/quickshell.nix). Single-user desktop, 0666 is fine. # settings/quickshell.nix). Single-user desktop, 0666 is fine.

View file

@ -18,6 +18,7 @@ let
wallsJson = builtins.toJSON config.fred.theming.walls; wallsJson = builtins.toJSON config.fred.theming.walls;
defaultWall = config.fred.theming.defaultWall; defaultWall = config.fred.theming.defaultWall;
themeApply = config.fred.theming.apply; themeApply = config.fred.theming.apply;
monoIcons = config.fred.theming.monoIcons;
in in
{ {
config = lib.mkIf (lib.elem config.networking.hostName [ "FredOS-Gaming" "FredOS-Macbook" ]) { config = lib.mkIf (lib.elem config.networking.hostName [ "FredOS-Gaming" "FredOS-Macbook" ]) {
@ -1312,6 +1313,10 @@ in
readonly property string wxFetch: "${wxFetchScript}" readonly property string wxFetch: "${wxFetchScript}"
readonly property string xdgOpen: "${pkgs.xdg-utils}/bin/xdg-open" readonly property string xdgOpen: "${pkgs.xdg-utils}/bin/xdg-open"
readonly property string themeApply: "${themeApply}" readonly property string themeApply: "${themeApply}"
// Prefix of the monochrome app-icon tree. AppIcon tests a
// resolved icon path against this to decide whether it may
// be tinted see the component for why that is not blanket.
readonly property string monoIconDir: "${monoIcons}"
} }
''; '';
}; };
@ -1730,6 +1735,53 @@ in
// act on. Stroke weight is fixed by the design. // act on. Stroke weight is fixed by the design.
} }
// AppIcon: an application icon in a square slot, tinted to
// the wallpaper's text colour when and only when it came
// from the monochrome set.
//
// YAMIS declares FollowsColorScheme=true, which is a KDE key:
// only Plasma rewrites the <style> block inside each SVG, so
// here every icon would otherwise render at the fixed #d8dee9
// baked into the file and sit dead against a themed bar.
// Overlaying at draw time follows the palette live and costs
// no disk copy (the same hidden-Image trick as the tray).
//
// The test is deliberately narrow rather than tinting every
// icon. A few apps have no YAMIS icon and fall through to
// Papirus, whose artwork encodes its detail as colour
// separation Spotify's waves are white-on-green, not cut
// out of the shape. Flatten one of those and you get a
// featureless blob, so full-colour fallbacks are left alone.
component AppIcon: Item {
id: _ai
property string path: ""
property int size: 32
readonly property bool mono:
_ai.path !== "" && _ai.path.indexOf(Commands.monoIconDir) !== -1
width: size
height: size
Image {
id: _aiImg
anchors.fill: parent
source: _ai.path
sourceSize.width: _ai.size
sourceSize.height: _ai.size
smooth: true
mipmap: true
// Hidden only when the overlay is drawing in its
// place; ColorOverlay reads it as a texture either way.
visible: _ai.path !== "" && !_ai.mono
}
ColorOverlay {
anchors.fill: _aiImg
source: _aiImg
visible: _ai.mono
color: Theme.base05
}
}
// BarSep: extra whitespace between widget groups. Groups are // BarSep: extra whitespace between widget groups. Groups are
// separated by air, not by lines a drawn rule read as clutter // separated by air, not by lines a drawn rule read as clutter
// in a 46px column. // in a 46px column.
@ -1981,14 +2033,13 @@ in
Row { Row {
width: parent.width width: parent.width
spacing: 4 spacing: 4
visible: _nc.notif && (_nc.notif.appName !== "" || _appIcon.source != "") visible: _nc.notif && (_nc.notif.appName !== "" || _appIcon.path != "")
Image { AppIcon {
id: _appIcon id: _appIcon
width: 14; height: 14 size: 14
sourceSize.width: 14; sourceSize.height: 14
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
source: _nc.notif && _nc.notif.appIcon ? Quickshell.iconPath(_nc.notif.appIcon, true) : "" path: _nc.notif && _nc.notif.appIcon ? Quickshell.iconPath(_nc.notif.appIcon, true) : ""
visible: source != "" visible: path != ""
} }
SText { SText {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@ -3320,14 +3371,10 @@ in
anchors.centerIn: parent anchors.centerIn: parent
spacing: 4 spacing: 4
Image { AppIcon {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
visible: source != "" path: pinCell.icon
width: 28 size: 28
height: 28
sourceSize.width: 28
sourceSize.height: 28
source: pinCell.icon
} }
SText { SText {
width: pinCell.width - 12 width: pinCell.width - 12
@ -3490,12 +3537,10 @@ in
width: 32 width: 32
height: 32 height: 32
Image { AppIcon {
anchors.fill: parent anchors.fill: parent
visible: source != "" path: icon
sourceSize.width: 32 size: 32
sourceSize.height: 32
source: icon
} }
SIcon { SIcon {
anchors.centerIn: parent anchors.centerIn: parent

View file

@ -293,6 +293,40 @@ let
''misc={background_color="rgb(${s.base00})"}'' ''misc={background_color="rgb(${s.base00})"}''
] + "})"); ] + "})");
# ── App icons ──────────────────────────────────────────────────────────
# YAMIS draws the app icons in the launcher. Picked over the far bigger
# monochrome sets because coverage beats library size: it is the only one
# still shipping commits, so it has the apps actually installed here
# (zen, ghostty, vesktop, bazaar, faugus, protonplus) where the 10k-icon
# archives — Suru++ Asprómauros, dead since 2019 — do not.
#
# Not in nixpkgs. Upstream is a bare icon tree with the theme at its root,
# so the "build" is a copy into the directory name the spec resolves by.
#
# FollowsColorScheme=true is a KDE key: only Plasma rewrites the embedded
# <style id="current-color-scheme"> block. Anywhere else the icons render
# at that block's literal fallback, #d8dee9, and never track the wallpaper.
#
# Rewriting that string on disk would mean a copy of all 6101 files per
# wallpaper — 75MB across the set, and a 15MB rm -rf + cp inside
# theme-apply on every switch, which is the one path that has to stay
# quick. quickshell tints these at draw time instead (ColorOverlay against
# base05, the same trick the tray uses), so the launcher follows the
# palette live and nothing is copied. monoIcons below hands it the prefix
# that identifies a YAMIS icon.
#
# Consequence: GTK apps still see #d8dee9. That is fine on these dark
# themes, and it is the only consumer that reads these files directly.
yamisIcons = pkgs.runCommand "yamis-icon-theme" { } ''
mkdir -p $out/share/icons
cp -r ${pkgs.fetchgit {
url = "https://bitbucket.org/dirn-typo/yet-another-monochrome-icon-set.git";
rev = "4294d5d51f896e54de3f01c12ed35a46d9451258";
hash = "sha256-oVztgqlGB8qkOlJU7HCWXT8BBZLAHHajdws6FIe33XA=";
}} $out/share/icons/yet-another-monochrome-icon-set
chmod -R u+w $out/share/icons
'';
# A featherweight icon theme that inherits Papirus-Dark and overrides only # A featherweight icon theme that inherits Papirus-Dark and overrides only
# the folder faces, rather than a recoloured copy of the whole 200MB tree # the folder faces, rather than a recoloured copy of the whole 200MB tree
# per wallpaper. Papirus-Dark delegates its size dirs to ../Papirus by # per wallpaper. Papirus-Dark delegates its size dirs to ../Papirus by
@ -304,8 +338,12 @@ let
{ {
echo "[Icon Theme]" echo "[Icon Theme]"
echo "Name=Papirus-Fred" echo "Name=Papirus-Fred"
echo "Comment=Papirus-Dark with ${color} folders" echo "Comment=YAMIS app icons with ${color} Papirus folders"
echo "Inherits=Papirus-Dark,Papirus,hicolor" # YAMIS first, so every app it covers wins; its own index.theme falls
# through to Papirus-Dark for the rest. Papirus is repeated here
# anyway — an upstream edit to YAMIS's Inherits must not be able to
# break the fallback that the folder overrides below depend on.
echo "Inherits=yet-another-monochrome-icon-set,Papirus-Dark,Papirus,hicolor"
printf 'Directories=' printf 'Directories='
first=1 first=1
for size in $sizes; do for size in $sizes; do
@ -539,6 +577,10 @@ in
}; };
defaultWall = lib.mkOption { internal = true; type = lib.types.str; }; defaultWall = lib.mkOption { internal = true; type = lib.types.str; };
apply = lib.mkOption { internal = true; type = lib.types.path; }; apply = lib.mkOption { internal = true; type = lib.types.path; };
# The installed YAMIS tree. quickshell needs the prefix to tell a
# monochrome icon from a Papirus fallback at draw time — see the tint
# note on yamisIcons above.
monoIcons = lib.mkOption { internal = true; type = lib.types.str; };
}; };
config = lib.mkMerge [{ config = lib.mkMerge [{
@ -573,8 +615,14 @@ in
fred.theming = { fred.theming = {
inherit walls defaultWall; inherit walls defaultWall;
apply = themeApply; apply = themeApply;
monoIcons = "${yamisIcons}/share/icons/yet-another-monochrome-icon-set";
}; };
# Papirus-Fred inherits this by name, so it has to be on the icon search
# path for the lookup to resolve — installing the theme is what makes the
# Inherits= line above mean anything.
environment.systemPackages = [ yamisIcons ];
home-manager.users.fred = { config, lib, pkgs, osConfig, ... }: { home-manager.users.fred = { config, lib, pkgs, osConfig, ... }: {
# These targets write build-time files that theme-apply replaces at # These targets write build-time files that theme-apply replaces at
# runtime; leaving them on means stylix and the switcher fight over the # runtime; leaving them on means stylix and the switcher fight over the