mirror of
https://github.com/Theaninova/TheaninovOS.git
synced 2025-12-12 11:36:20 +00:00
545 lines
17 KiB
Nix
545 lines
17 KiB
Nix
{
|
|
pkgs,
|
|
lib,
|
|
osConfig,
|
|
config,
|
|
...
|
|
}:
|
|
|
|
let
|
|
cfg = config.theme.md3-evo;
|
|
in
|
|
{
|
|
options.theme.md3-evo = {
|
|
enable = lib.mkEnableOption "the MD3-EVO theme";
|
|
auto-dark = {
|
|
enable = lib.mkEnableOption "Automatically switch between light and dark mode";
|
|
lon = lib.mkOption {
|
|
type = lib.types.float;
|
|
};
|
|
lat = lib.mkOption {
|
|
type = lib.types.float;
|
|
};
|
|
};
|
|
flavour = lib.mkOption {
|
|
type = lib.types.enum [
|
|
"content"
|
|
"expressive"
|
|
"fidelity"
|
|
"fruit-salad"
|
|
"monochrome"
|
|
"neutral"
|
|
"rainbow"
|
|
"tonal-spot"
|
|
];
|
|
default = "tonal-spot";
|
|
description = "The flavour of the theme";
|
|
};
|
|
contrast = lib.mkOption {
|
|
type = lib.types.numbers.between (-1) 1;
|
|
default = 0;
|
|
description = "Use a modified contrast";
|
|
};
|
|
transparency = lib.mkOption {
|
|
type = lib.types.numbers.between 0 1;
|
|
default = 0.9;
|
|
description = "The transparency of apps";
|
|
};
|
|
radius = lib.mkOption {
|
|
type = lib.types.ints.positive;
|
|
default = 24;
|
|
description = "The radius of the corners";
|
|
};
|
|
padding = lib.mkOption {
|
|
type = lib.types.ints.positive;
|
|
default = 12;
|
|
description = "The padding of the windows";
|
|
};
|
|
blur = lib.mkOption {
|
|
type = lib.types.ints.positive;
|
|
default = 16;
|
|
description = "The blur amount of windows";
|
|
};
|
|
semantic = {
|
|
blend = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Blend the colors";
|
|
};
|
|
danger = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#ff0000";
|
|
description = "The color of danger";
|
|
};
|
|
warning = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#ffff00";
|
|
description = "The color of warning";
|
|
};
|
|
success = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#00ff00";
|
|
description = "The color of success";
|
|
};
|
|
info = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#0000ff";
|
|
description = "The color of info";
|
|
};
|
|
};
|
|
syntax = {
|
|
blend = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = "Blend the colors";
|
|
};
|
|
keywords = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#ff8000";
|
|
description = "The color of keywords";
|
|
};
|
|
functions = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#0000ff";
|
|
description = "The color of functions";
|
|
};
|
|
properties = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#ff00ff";
|
|
description = "The color of properties";
|
|
};
|
|
constants = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#ff00ff";
|
|
description = "The color of constants";
|
|
};
|
|
strings = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#00ff00";
|
|
description = "The color of variables";
|
|
};
|
|
numbers = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#00ffff";
|
|
description = "The color of numbers";
|
|
};
|
|
structures = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#ffff00";
|
|
description = "The color of structures";
|
|
};
|
|
types = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#00ffff";
|
|
description = "The color of types";
|
|
};
|
|
};
|
|
ansi = {
|
|
blend = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = "Blend the colors";
|
|
};
|
|
red = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#ff0000";
|
|
description = "The color of red";
|
|
};
|
|
green = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#00ff00";
|
|
description = "The color of green";
|
|
};
|
|
yellow = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#ffff00";
|
|
description = "The color of yellow";
|
|
};
|
|
orange = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#ff8000";
|
|
description = "The color of orange";
|
|
};
|
|
blue = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#0000ff";
|
|
description = "The color of blue";
|
|
};
|
|
magenta = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#ff00ff";
|
|
description = "The color of magenta";
|
|
};
|
|
cyan = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "#00ffff";
|
|
description = "The color of cyan";
|
|
};
|
|
};
|
|
};
|
|
|
|
config =
|
|
let
|
|
theme-script = (
|
|
pkgs.writeShellApplication {
|
|
name = "theme";
|
|
runtimeInputs = [
|
|
pkgs.matugen
|
|
pkgs.swww
|
|
pkgs.zenity
|
|
pkgs.sunwait
|
|
];
|
|
text = ''
|
|
WALLPAPER=${config.xdg.configHome}/matugen/wallpaper
|
|
STATE=${config.xdg.stateHome}/md3-evo
|
|
|
|
SCHEME=$(dconf read /org/gnome/desktop/interface/color-scheme)
|
|
if [ "$SCHEME" = "'prefer-light'" ]; then
|
|
MODE="light"
|
|
else
|
|
MODE="dark"
|
|
fi
|
|
|
|
if [ ! -d "$STATE" ]; then
|
|
mkdir -p "$STATE"
|
|
fi
|
|
if [ -f "$STATE/mode" ]; then
|
|
MODE=$(cat "$STATE/mode")
|
|
fi
|
|
|
|
if [ $# -eq 0 ]; then
|
|
echo -e "\033[1mUsage:\033[0m mode|light|dark|auto|toggle|wallpaper"
|
|
exit 1
|
|
elif [ "$1" = "mode" ]; then
|
|
echo -e "$MODE"
|
|
exit 0
|
|
elif [ "$1" = "wallpaper" ]; then
|
|
if [ $# -eq 1 ]; then
|
|
PICKED=$(zenity --file-selection --file-filter='Images | *.png *.jpg *.jpeg *.svg *.bmp *.gif')
|
|
cp "$PICKED" "$WALLPAPER"
|
|
else
|
|
cp "$2" "$WALLPAPER"
|
|
fi
|
|
elif [ "$1" = "toggle" ]; then
|
|
if [ "$MODE" = "light" ]; then
|
|
MODE="dark"
|
|
else
|
|
MODE="light"
|
|
fi
|
|
echo "$MODE" > "$STATE/mode"
|
|
elif [ "$1" = "light" ] || [ "$1" = "dark" ] || [ "$1" == "auto" ]; then
|
|
MODE="$1"
|
|
echo "$MODE" > "$STATE/mode"
|
|
elif [ "$1" = "init" ]; then
|
|
echo -e "\033[1mSetting up matugen\033[0m"
|
|
else
|
|
echo -e "\033[31mInvalid argument\033[0m"
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f $WALLPAPER ]; then
|
|
echo -e "\033[31,1mNo wallpaper set\033[0m"
|
|
exit 1
|
|
fi
|
|
|
|
THEME_SERVICE_PATH="${config.xdg.configHome}/systemd/user/theme-init.timer"
|
|
if [ "$MODE" = "auto" ]; then
|
|
TIME=$(sunwait poll ${builtins.toString cfg.auto-dark.lat}N ${builtins.toString cfg.auto-dark.lon}E || :)
|
|
if [ "$TIME" = "DAY" ]; then
|
|
MODE="light"
|
|
NEXT=6
|
|
else
|
|
MODE="dark"
|
|
NEXT=4
|
|
fi
|
|
NEXT=$(sunwait report ${builtins.toString cfg.auto-dark.lat}N ${builtins.toString cfg.auto-dark.lon}E | awk "/Daylight:/ {print \$$NEXT}")
|
|
cat <<EOF | tee "$THEME_SERVICE_PATH" > /dev/null
|
|
[Unit]
|
|
Description=Next theme change timer
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* $(date -d "$NEXT today + 5 minutes" +'%H:%M'):00
|
|
AccuracySec=1min
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
EOF
|
|
else
|
|
rm -f "$THEME_SERVICE_PATH"
|
|
fi
|
|
systemctl --user daemon-reload &> /dev/null || :
|
|
systemctl --user restart theme-init.timer &> /dev/null || :
|
|
|
|
if command -v niri &> /dev/null; then
|
|
niri msg action do-screen-transition --delay-ms 500
|
|
fi
|
|
|
|
if [ "$MODE" = "light" ]; then
|
|
GTK_THEME="adw-gtk3"
|
|
else
|
|
GTK_THEME="adw-gtk3-dark"
|
|
fi
|
|
|
|
matugen image "$WALLPAPER" --type scheme-${cfg.flavour} --contrast ${builtins.toString cfg.contrast} --mode "$MODE"
|
|
|
|
dconf write /org/gnome/desktop/interface/gtk-theme "'$GTK_THEME'"
|
|
dconf write /org/gnome/desktop/interface/color-scheme "'prefer-$MODE'"
|
|
dconf write /org/gnome/desktop/interface/icon-theme "'Adwaita'"
|
|
'';
|
|
}
|
|
);
|
|
in
|
|
lib.mkIf cfg.enable {
|
|
home.packages = [
|
|
pkgs.adw-gtk3
|
|
pkgs.swww
|
|
theme-script
|
|
];
|
|
|
|
gtk = {
|
|
gtk3.extraCss = # css
|
|
"@import './theme.css';";
|
|
gtk4.extraCss = # css
|
|
"@import './theme.css';";
|
|
theme = {
|
|
name = "Adwaita";
|
|
};
|
|
iconTheme = {
|
|
name = "Tela";
|
|
package = pkgs.tela-icon-theme;
|
|
};
|
|
};
|
|
qt.platformTheme.name = "qtct";
|
|
|
|
systemd.user.services = {
|
|
swww-daemon = {
|
|
Unit = {
|
|
Description = "Swww Daemon";
|
|
After = [ "graphical-session.target" ];
|
|
};
|
|
Install.WantedBy = [ "graphical-session.target" ];
|
|
Service = {
|
|
ExecStart = "${pkgs.swww}/bin/swww-daemon";
|
|
Restart = "always";
|
|
};
|
|
};
|
|
theme-init = {
|
|
Unit = {
|
|
Description = "MD3 Evo Theme Init";
|
|
After = [
|
|
"graphical-session.target"
|
|
"swww-daemon.service"
|
|
];
|
|
};
|
|
Install.WantedBy = [ "graphical-session.target" ];
|
|
Service = {
|
|
ExecStart = "${lib.getExe theme-script} init";
|
|
Restart = "on-failure";
|
|
};
|
|
};
|
|
};
|
|
|
|
wayland.windowManager.hyprland = {
|
|
settings = {
|
|
windowrulev2 = [ "float,class:^(zenity)$" ];
|
|
decoration = {
|
|
inactive_opacity = 0.8;
|
|
shadow = {
|
|
enabled = true;
|
|
range = 32;
|
|
render_power = 8;
|
|
color = "rgba(000000aa)";
|
|
color_inactive = "rgba(00000011)";
|
|
};
|
|
};
|
|
animations = {
|
|
enabled = "yes";
|
|
bezier = [
|
|
"expoOut, 0.16, 1, 0.3, 1"
|
|
];
|
|
animation = [
|
|
"windowsIn, 1, 5, expoOut, slide bottom"
|
|
"windows, 1, 5, expoOut, slide"
|
|
"windowsOut, 1, 5, expoOut, slide bottom"
|
|
"border, 1, 10, default"
|
|
"fade, 1, 7, default"
|
|
"fadeShadow, 1, 10, default"
|
|
"fadeDim, 1, 10, default"
|
|
"workspaces, 1, 6, default"
|
|
];
|
|
};
|
|
};
|
|
extraConfig = ''
|
|
source=./theme.conf
|
|
'';
|
|
};
|
|
|
|
# TODO: include is coming in the next release
|
|
/*
|
|
xdg.configFile.niri-config = {
|
|
enable = osConfig.programs.niri.enable;
|
|
target = "niri/override.kdl";
|
|
text = ''
|
|
include "${config.xdg.configHome}/niri/config.kdl"
|
|
include "${config.programs.matugen.settings.templates.niri.output_path}"
|
|
'';
|
|
};
|
|
home.sessionVariables.NIRI_CONFIG = "${config.xdg.configHome}/niri/override.kdl";
|
|
*/
|
|
|
|
programs = {
|
|
kitty.extraConfig = ''
|
|
include ${config.programs.matugen.settings.templates.kitty.output_path}
|
|
'';
|
|
|
|
nixvim = {
|
|
opts.termguicolors = true;
|
|
colorscheme = "md3-evo";
|
|
autoCmd = [
|
|
{
|
|
event = [ "Signal" ];
|
|
pattern = [ "SIGUSR1" ];
|
|
command = # vim
|
|
"colorscheme md3-evo";
|
|
nested = true;
|
|
}
|
|
];
|
|
plugins.lualine.settings.options.theme.__raw = # lua
|
|
"function() return vim.g.lualine_theme end";
|
|
};
|
|
matugen = {
|
|
enable = true;
|
|
settings = {
|
|
config = {
|
|
version_check = false;
|
|
|
|
reload_apps_list = {
|
|
waybar = config.programs.waybar.enable;
|
|
dunst = config.services.dunst.enable;
|
|
};
|
|
|
|
wallpaper.command = lib.getExe pkgs.swww;
|
|
|
|
custom_colors =
|
|
let
|
|
mkColor = category: color: {
|
|
inherit (cfg.${category}) blend;
|
|
color = cfg.${category}.${color};
|
|
};
|
|
in
|
|
{
|
|
red = mkColor "ansi" "red";
|
|
green = mkColor "ansi" "green";
|
|
yellow = mkColor "ansi" "yellow";
|
|
orange = mkColor "ansi" "orange";
|
|
blue = mkColor "ansi" "blue";
|
|
magenta = mkColor "ansi" "magenta";
|
|
cyan = mkColor "ansi" "cyan";
|
|
|
|
keywords = mkColor "syntax" "keywords";
|
|
functions = mkColor "syntax" "functions";
|
|
constants = mkColor "syntax" "constants";
|
|
properties = mkColor "syntax" "properties";
|
|
strings = mkColor "syntax" "strings";
|
|
numbers = mkColor "syntax" "numbers";
|
|
structures = mkColor "syntax" "structures";
|
|
types = mkColor "syntax" "types";
|
|
|
|
danger = mkColor "semantic" "danger";
|
|
warning = mkColor "semantic" "warning";
|
|
success = mkColor "semantic" "success";
|
|
info = mkColor "semantic" "info";
|
|
};
|
|
|
|
custom_keywords = {
|
|
inherit (cfg) flavour;
|
|
padding = builtins.toString cfg.padding;
|
|
double_padding = builtins.toString (cfg.padding * 2);
|
|
radius = builtins.toString cfg.radius;
|
|
transparency = builtins.toString cfg.transparency;
|
|
blur = builtins.toString cfg.blur;
|
|
contrast = builtins.toString cfg.contrast;
|
|
transparency_hex =
|
|
let
|
|
zeroPad = hex: if builtins.stringLength hex == 1 then "0${hex}" else hex;
|
|
in
|
|
zeroPad (lib.trivial.toHexString (builtins.floor (cfg.transparency * 255)));
|
|
};
|
|
};
|
|
|
|
templates =
|
|
let
|
|
gtk = pkgs.writeText "gtk4.css" (import ./gtk.nix);
|
|
signal =
|
|
name: signal:
|
|
(pkgs.writeShellScript "kill-${name}" ''
|
|
pkill -${signal} -u "$USER" -x ${name} || :
|
|
'');
|
|
in
|
|
{
|
|
nvim = {
|
|
input_path = ./nvim.vim;
|
|
output_path = "${config.xdg.configHome}/nvim/colors/md3-evo.vim";
|
|
post_hook = signal "nvim" "USR1";
|
|
};
|
|
gtk3 = {
|
|
input_path = gtk;
|
|
output_path = "${config.xdg.configHome}/gtk-3.0/theme.css";
|
|
};
|
|
gtk4 = {
|
|
input_path = gtk;
|
|
output_path = "${config.xdg.configHome}/gtk-4.0/theme.css";
|
|
};
|
|
vesktop = {
|
|
input_path = ./discord.css;
|
|
output_path = "${config.xdg.configHome}/vesktop/themes/matugen.theme.css";
|
|
};
|
|
}
|
|
// (lib.optionalAttrs osConfig.programs.niri.enable {
|
|
niri = {
|
|
input_path = ./niri.kdl;
|
|
output_path = "${config.xdg.configHome}/niri/md3-evo.kdl";
|
|
};
|
|
})
|
|
// (lib.optionalAttrs config.programs.kitty.enable {
|
|
kitty = {
|
|
input_path = ./kitty.conf;
|
|
output_path = "${config.xdg.configHome}/kitty/theme.conf";
|
|
post_hook = signal ".kitty-wrapped" "USR1";
|
|
};
|
|
})
|
|
// (lib.optionalAttrs osConfig.programs.hyprland.enable {
|
|
hyprland = {
|
|
input_path = ./hyprland.conf;
|
|
output_path = "${config.xdg.configHome}/hypr/theme.conf";
|
|
post_hook = pkgs.writeShellScript "reload-hyprland-theme" ''
|
|
if command -v hyprctl &> /dev/null; then
|
|
hyprctl reload
|
|
fi
|
|
'';
|
|
};
|
|
})
|
|
// (lib.optionalAttrs config.programs.waybar.enable {
|
|
waybar = {
|
|
input_path = ./waybar.css;
|
|
output_path = "${config.xdg.configHome}/waybar/style.css";
|
|
post_hook = signal "waybar" "USR2";
|
|
};
|
|
})
|
|
// (lib.optionalAttrs config.services.swaync.enable {
|
|
swaync = {
|
|
input_path = ./swaync.css;
|
|
output_path = "${config.xdg.configHome}/swaync/style.css";
|
|
post_hook = pkgs.writeShellScript "reload-swaync" ''
|
|
if which swaync-client; then
|
|
swaync-client --reload-css
|
|
fi
|
|
'';
|
|
};
|
|
});
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|