312 lines
9.6 KiB
Nix
312 lines
9.6 KiB
Nix
{ lib, pkgs, stdenv, writeTextFile, ... }:
|
|
|
|
# OmniXY Plymouth Theme Package
|
|
# Creates theme-aware Plymouth boot screens
|
|
|
|
let
|
|
# Theme color definitions
|
|
themeColors = {
|
|
tokyo-night = {
|
|
bg = "#1a1b26";
|
|
fg = "#c0caf5";
|
|
accent = "#7aa2f7";
|
|
secondary = "#bb9af7";
|
|
};
|
|
catppuccin = {
|
|
bg = "#1e1e2e";
|
|
fg = "#cdd6f4";
|
|
accent = "#89b4fa";
|
|
secondary = "#cba6f7";
|
|
};
|
|
gruvbox = {
|
|
bg = "#282828";
|
|
fg = "#ebdbb2";
|
|
accent = "#d79921";
|
|
secondary = "#b16286";
|
|
};
|
|
nord = {
|
|
bg = "#2e3440";
|
|
fg = "#eceff4";
|
|
accent = "#5e81ac";
|
|
secondary = "#b48ead";
|
|
};
|
|
everforest = {
|
|
bg = "#2d353b";
|
|
fg = "#d3c6aa";
|
|
accent = "#a7c080";
|
|
secondary = "#e67e80";
|
|
};
|
|
rose-pine = {
|
|
bg = "#191724";
|
|
fg = "#e0def4";
|
|
accent = "#31748f";
|
|
secondary = "#c4a7e7";
|
|
};
|
|
kanagawa = {
|
|
bg = "#1f1f28";
|
|
fg = "#dcd7ba";
|
|
accent = "#7e9cd8";
|
|
secondary = "#957fb8";
|
|
};
|
|
catppuccin-latte = {
|
|
bg = "#eff1f5";
|
|
fg = "#4c4f69";
|
|
accent = "#1e66f5";
|
|
secondary = "#8839ef";
|
|
};
|
|
matte-black = {
|
|
bg = "#000000";
|
|
fg = "#ffffff";
|
|
accent = "#666666";
|
|
secondary = "#999999";
|
|
};
|
|
osaka-jade = {
|
|
bg = "#0d1b1e";
|
|
fg = "#c5d4d7";
|
|
accent = "#5fb3a1";
|
|
secondary = "#7ba05b";
|
|
};
|
|
ristretto = {
|
|
bg = "#2c1810";
|
|
fg = "#d4c5a7";
|
|
accent = "#d08b5b";
|
|
secondary = "#a67458";
|
|
};
|
|
};
|
|
|
|
# Base assets (copied from omarchy)
|
|
assets = pkgs.runCommand "omnixy-plymouth-assets" {} ''
|
|
mkdir -p $out
|
|
|
|
# Create base logo (OmniXY branding)
|
|
cat > $out/logo.svg <<'EOF'
|
|
<svg width="120" height="120" xmlns="http://www.w3.org/2000/svg">
|
|
<defs>
|
|
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
<stop offset="0%" style="stop-color:#7aa2f7;stop-opacity:1" />
|
|
<stop offset="100%" style="stop-color:#bb9af7;stop-opacity:1" />
|
|
</linearGradient>
|
|
</defs>
|
|
<circle cx="60" cy="60" r="50" fill="url(#grad1)" opacity="0.8"/>
|
|
<text x="60" y="70" font-family="JetBrains Mono" font-size="24" font-weight="bold"
|
|
text-anchor="middle" fill="white">XY</text>
|
|
</svg>
|
|
EOF
|
|
|
|
# Convert SVG to PNG
|
|
${pkgs.librsvg}/bin/rsvg-convert -w 120 -h 120 $out/logo.svg -o $out/logo.png
|
|
rm $out/logo.svg
|
|
|
|
# Create other UI elements (simplified versions of omarchy assets)
|
|
${pkgs.imagemagick}/bin/convert -size 32x32 xc:none -fill '#ffffff' -draw 'circle 16,16 16,8' $out/lock.png
|
|
${pkgs.imagemagick}/bin/convert -size 200x32 xc:'rgba(255,255,255,0.1)' -stroke white -strokewidth 1 -fill none -draw 'roundrectangle 1,1 198,30 8,8' $out/entry.png
|
|
${pkgs.imagemagick}/bin/convert -size 8x8 xc:white $out/bullet.png
|
|
${pkgs.imagemagick}/bin/convert -size 300x8 xc:'rgba(255,255,255,0.2)' -stroke white -strokewidth 1 -fill none -draw 'roundrectangle 1,1 298,6 4,4' $out/progress_box.png
|
|
${pkgs.imagemagick}/bin/convert -size 296x4 xc:'rgba(255,255,255,0.8)' $out/progress_bar.png
|
|
'';
|
|
|
|
# Plymouth script template
|
|
createPlymouthScript = themeName: colors: writeTextFile {
|
|
name = "omnixy-${themeName}.script";
|
|
text = ''
|
|
# OmniXY Plymouth Theme Script
|
|
# Theme: ${themeName}
|
|
# Generated for NixOS/OmniXY
|
|
|
|
// Theme color configuration
|
|
bg_color = Colour("${colors.bg}");
|
|
fg_color = Colour("${colors.fg}");
|
|
accent_color = Colour("${colors.accent}");
|
|
secondary_color = Colour("${colors.secondary}");
|
|
|
|
// Screen setup
|
|
screen_width = Window.GetWidth();
|
|
screen_height = Window.GetHeight();
|
|
Window.SetBackgroundTopColor(bg_color);
|
|
Window.SetBackgroundBottomColor(bg_color);
|
|
|
|
// Load assets
|
|
logo_image = Image("logo.png");
|
|
lock_image = Image("lock.png");
|
|
entry_image = Image("entry.png");
|
|
bullet_image = Image("bullet.png");
|
|
progress_box_image = Image("progress_box.png");
|
|
progress_bar_image = Image("progress_bar.png");
|
|
|
|
// Logo setup
|
|
logo_sprite = Sprite(logo_image);
|
|
logo_sprite.SetX((screen_width - logo_image.GetWidth()) / 2);
|
|
logo_sprite.SetY(screen_height / 2 - 100);
|
|
logo_sprite.SetOpacity(0.9);
|
|
|
|
// Progress bar setup
|
|
progress_box_sprite = Sprite(progress_box_image);
|
|
progress_box_sprite.SetX((screen_width - progress_box_image.GetWidth()) / 2);
|
|
progress_box_sprite.SetY(screen_height / 2 + 50);
|
|
|
|
progress_bar_sprite = Sprite(progress_bar_image);
|
|
progress_bar_sprite.SetX((screen_width - progress_box_image.GetWidth()) / 2 + 2);
|
|
progress_bar_sprite.SetY(screen_height / 2 + 52);
|
|
|
|
// Animation variables
|
|
fake_progress = 0;
|
|
real_progress = 0;
|
|
start_time = Plymouth.GetTime();
|
|
fake_duration = 15; // 15 seconds fake progress
|
|
|
|
// Easing function (ease-out quadratic)
|
|
fun easeOutQuad(x) {
|
|
return 1 - (1 - x) * (1 - x);
|
|
}
|
|
|
|
// Progress update function
|
|
fun progress_callback() {
|
|
current_time = Plymouth.GetTime();
|
|
elapsed = current_time - start_time;
|
|
|
|
// Calculate fake progress (0 to 0.7 over fake_duration)
|
|
if (elapsed < fake_duration) {
|
|
fake_progress = 0.7 * easeOutQuad(elapsed / fake_duration);
|
|
} else {
|
|
fake_progress = 0.7;
|
|
}
|
|
|
|
// Use the maximum of fake and real progress
|
|
display_progress = fake_progress;
|
|
if (real_progress > fake_progress) {
|
|
display_progress = real_progress;
|
|
}
|
|
|
|
// Update progress bar
|
|
bar_width = progress_bar_image.GetWidth() * display_progress;
|
|
progress_bar_sprite.SetImage(progress_bar_image.Scale(bar_width, progress_bar_image.GetHeight()));
|
|
|
|
// Add subtle pulsing to logo during boot
|
|
pulse = Math.Sin(elapsed * 3) * 0.1 + 0.9;
|
|
logo_sprite.SetOpacity(pulse);
|
|
}
|
|
|
|
Plymouth.SetUpdateFunction(progress_callback);
|
|
|
|
// Boot progress callback
|
|
Plymouth.SetBootProgressFunction(
|
|
fun (duration, progress) {
|
|
real_progress = progress;
|
|
}
|
|
);
|
|
|
|
// Password dialog setup
|
|
question_sprite = Sprite();
|
|
answer_sprite = Sprite();
|
|
|
|
fun DisplayQuestionCallback(prompt, entry) {
|
|
question_sprite.SetImage(Image.Text(prompt, 1, 1, 1));
|
|
question_sprite.SetX((screen_width - question_sprite.GetImage().GetWidth()) / 2);
|
|
question_sprite.SetY(screen_height / 2 - 50);
|
|
|
|
// Show lock icon
|
|
lock_sprite = Sprite(lock_image);
|
|
lock_sprite.SetX((screen_width - lock_image.GetWidth()) / 2);
|
|
lock_sprite.SetY(screen_height / 2 - 20);
|
|
|
|
// Show entry field
|
|
entry_sprite = Sprite(entry_image);
|
|
entry_sprite.SetX((screen_width - entry_image.GetWidth()) / 2);
|
|
entry_sprite.SetY(screen_height / 2 + 20);
|
|
|
|
// Show bullets for password
|
|
bullet_sprites = [];
|
|
for (i = 0; i < entry.GetLength(); i++) {
|
|
bullet_sprites[i] = Sprite(bullet_image);
|
|
bullet_sprites[i].SetX((screen_width / 2) - (entry.GetLength() * 10 / 2) + i * 10);
|
|
bullet_sprites[i].SetY(screen_height / 2 + 28);
|
|
}
|
|
}
|
|
|
|
Plymouth.SetDisplayQuestionFunction(DisplayQuestionCallback);
|
|
|
|
// Hide question callback
|
|
Plymouth.SetDisplayPasswordFunction(DisplayQuestionCallback);
|
|
|
|
// Message display
|
|
message_sprite = Sprite();
|
|
|
|
Plymouth.SetMessageFunction(
|
|
fun (text) {
|
|
message_sprite.SetImage(Image.Text(text, 1, 1, 1));
|
|
message_sprite.SetX((screen_width - message_sprite.GetImage().GetWidth()) / 2);
|
|
message_sprite.SetY(screen_height - 50);
|
|
}
|
|
);
|
|
|
|
// Quit callback
|
|
Plymouth.SetQuitFunction(
|
|
fun () {
|
|
// Fade out animation
|
|
for (i = 0; i < 30; i++) {
|
|
opacity = 1 - (i / 30);
|
|
logo_sprite.SetOpacity(opacity);
|
|
Plymouth.Sleep(16); // ~60fps
|
|
}
|
|
}
|
|
);
|
|
'';
|
|
};
|
|
|
|
# Create theme definition file
|
|
createPlymouthTheme = themeName: colors: writeTextFile {
|
|
name = "omnixy-${themeName}.plymouth";
|
|
text = ''
|
|
[Plymouth Theme]
|
|
Name=OmniXY ${themeName}
|
|
Description=OmniXY boot splash theme for ${themeName}
|
|
ModuleName=script
|
|
|
|
[script]
|
|
ImageDir=/run/current-system/sw/share/plymouth/themes/omnixy-${themeName}
|
|
ScriptFile=/run/current-system/sw/share/plymouth/themes/omnixy-${themeName}/omnixy-${themeName}.script
|
|
'';
|
|
};
|
|
|
|
in
|
|
|
|
# Create derivation for all Plymouth themes
|
|
stdenv.mkDerivation rec {
|
|
pname = "omnixy-plymouth-themes";
|
|
version = "1.0";
|
|
|
|
src = assets;
|
|
|
|
buildInputs = with pkgs; [ coreutils ];
|
|
|
|
installPhase = ''
|
|
mkdir -p $out/share/plymouth/themes
|
|
|
|
${lib.concatStringsSep "\n" (lib.mapAttrsToList (themeName: colors: ''
|
|
# Create theme directory
|
|
theme_dir="$out/share/plymouth/themes/omnixy-${themeName}"
|
|
mkdir -p "$theme_dir"
|
|
|
|
# Copy assets
|
|
cp ${src}/* "$theme_dir/"
|
|
|
|
# Install theme files
|
|
cp ${createPlymouthScript themeName colors} "$theme_dir/omnixy-${themeName}.script"
|
|
cp ${createPlymouthTheme themeName colors} "$theme_dir/omnixy-${themeName}.plymouth"
|
|
|
|
# Make script executable
|
|
chmod +x "$theme_dir/omnixy-${themeName}.script"
|
|
'') themeColors)}
|
|
|
|
# Create a default symlink to tokyo-night
|
|
ln -sf omnixy-tokyo-night $out/share/plymouth/themes/omnixy-default
|
|
'';
|
|
|
|
meta = with lib; {
|
|
description = "OmniXY Plymouth boot splash themes";
|
|
homepage = "https://github.com/TheArctesian/omnixy";
|
|
license = licenses.mit;
|
|
platforms = platforms.linux;
|
|
maintainers = [];
|
|
};
|
|
} |