Make flake self-contained - consolidate installer-replication

BREAKING CHANGE: Remove external dots-hyprland dependency

- Imported all essential configs from dots-hyprland/installer-replication
- Added complete configs/ directory with:
  - hypr/ - Hyprland configuration
  - quickshell/ - Quickshell widgets and config
  - applications/ - Application configurations
  - scripts/ - Utility scripts
  - matugen/ - Material You theming
- Updated flake.nix to use local ./configs instead of external repo
- Simplified update-flake script (removed external repo management)
- Updated README to reflect self-contained architecture
- All builds pass with local configurations

Benefits:
- No external repository dependencies
- Faster builds (no network dependencies)
- Version controlled configs in single repo
- Easier maintenance and development
- Complete installer replication in one place
This commit is contained in:
Celes Renata
2025-08-08 22:26:47 -07:00
parent 22b65891ac
commit ac6d3adeb9
710 changed files with 81319 additions and 115 deletions
+103
View File
@@ -0,0 +1,103 @@
#!/usr/bin/env bash
# Demo script for Material You theming system
set -euo pipefail
echo "🎨 dots-hyprland Material You Theming Demo"
echo "=========================================="
echo
# Check if system is configured
if [[ ! -f "$HOME/.config/home-manager/home.nix" ]]; then
echo "❌ Home Manager not configured. Please set up dots-hyprland first."
exit 1
fi
# Check if wallpaper directory exists
WALLPAPER_DIR="$HOME/Pictures/Wallpapers"
if [[ ! -d "$WALLPAPER_DIR" ]]; then
echo "📁 Creating wallpaper directory: $WALLPAPER_DIR"
mkdir -p "$WALLPAPER_DIR"
echo " Please add some wallpapers to this directory!"
fi
# Check for wallpapers
WALLPAPER_COUNT=$(find "$WALLPAPER_DIR" -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.webp" \) | wc -l)
if [[ $WALLPAPER_COUNT -eq 0 ]]; then
echo "⚠️ No wallpapers found in $WALLPAPER_DIR"
echo " Please add some wallpapers and run this script again."
exit 1
fi
echo "✅ Found $WALLPAPER_COUNT wallpapers in $WALLPAPER_DIR"
echo
# Show available commands
echo "🛠️ Available Material You Commands:"
echo " theme-switch [directory] [mode] - Switch to random wallpaper and generate theme"
echo " theme-toggle - Toggle between light/dark mode"
echo " theme-generate <wallpaper> [mode] - Generate theme from specific wallpaper"
echo
# Demo workflow
echo "🎯 Demo Workflow:"
echo "1. Switch to a random wallpaper with dark theme:"
echo " $ theme-switch"
echo
echo "2. Toggle to light mode:"
echo " $ theme-toggle"
echo
echo "3. Generate theme from specific wallpaper:"
echo " $ theme-generate ~/Pictures/Wallpapers/my-wallpaper.jpg dark"
echo
# Show what gets themed
echo "🎨 What Gets Themed:"
echo " ✅ Hyprland (borders, backgrounds, shadows)"
echo " ✅ Fuzzel launcher (colors, selection)"
echo " ✅ Foot terminal (all colors)"
echo " ✅ GTK applications (buttons, headers, etc.)"
echo " ✅ Hyprlock screen (backgrounds, text)"
echo " ✅ Quickshell widgets (when implemented)"
echo
# Show file locations
echo "📂 Generated Files:"
echo " ~/.local/share/dots-hyprland/generated/colors.json"
echo " ~/.config/hypr/colors.conf"
echo " ~/.config/fuzzel/fuzzel_theme.ini"
echo " ~/.config/foot/foot.ini"
echo " ~/.config/gtk-3.0/gtk.css"
echo " ~/.config/gtk-4.0/gtk.css"
echo " ~/.config/hypr/hyprlock.conf"
echo
# Interactive demo
read -p "🚀 Would you like to try switching to a random wallpaper now? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "🎨 Switching to random wallpaper..."
# Find a random wallpaper
RANDOM_WALLPAPER=$(find "$WALLPAPER_DIR" -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.webp" \) | shuf -n 1)
if [[ -n "$RANDOM_WALLPAPER" ]]; then
echo "📸 Selected: $(basename "$RANDOM_WALLPAPER")"
# Check if theme commands are available
if command -v theme-switch >/dev/null 2>&1; then
theme-switch "$WALLPAPER_DIR" dark
echo "✅ Theme applied! Check your desktop for the new colors."
else
echo "⚠️ Theme commands not available. Please activate your Home Manager configuration first:"
echo " $ home-manager switch --flake .#example"
fi
else
echo "❌ No wallpapers found"
fi
else
echo "👍 Demo complete! Use the commands above to try Material You theming."
fi
echo
echo "🎉 Material You theming is ready to use!"
+398
View File
@@ -0,0 +1,398 @@
#!/usr/bin/env bash
# Emoji picker using fuzzel
# Bound to SUPER + PERIOD in Hyprland
set -euo pipefail
# Emoji database - common emojis with descriptions
EMOJI_LIST="😀 grinning face
😃 grinning face with big eyes
😄 grinning face with smiling eyes
😁 beaming face with smiling eyes
😆 grinning squinting face
😅 grinning face with sweat
🤣 rolling on the floor laughing
😂 face with tears of joy
🙂 slightly smiling face
🙃 upside down face
😉 winking face
😊 smiling face with smiling eyes
😇 smiling face with halo
🥰 smiling face with hearts
😍 smiling face with heart eyes
🤩 star struck
😘 face blowing a kiss
😗 kissing face
😚 kissing face with closed eyes
😙 kissing face with smiling eyes
🥲 smiling face with tear
😋 face savoring food
😛 face with tongue
😜 winking face with tongue
🤪 zany face
😝 squinting face with tongue
🤑 money mouth face
🤗 hugging face
🤭 face with hand over mouth
🤫 shushing face
🤔 thinking face
🤐 zipper mouth face
🤨 face with raised eyebrow
😐 neutral face
😑 expressionless face
😶 face without mouth
😏 smirking face
😒 unamused face
🙄 face with rolling eyes
😬 grimacing face
🤥 lying face
😔 pensive face
😪 sleepy face
🤤 drooling face
😴 sleeping face
😷 face with medical mask
🤒 face with thermometer
🤕 face with head bandage
🤢 nauseated face
🤮 face vomiting
🤧 sneezing face
🥵 hot face
🥶 cold face
🥴 woozy face
😵 dizzy face
🤯 exploding head
🤠 cowboy hat face
🥳 partying face
🥸 disguised face
😎 smiling face with sunglasses
🤓 nerd face
🧐 face with monocle
😕 confused face
😟 worried face
🙁 slightly frowning face
😮 face with open mouth
😯 hushed face
😲 astonished face
😳 flushed face
🥺 pleading face
😦 frowning face with open mouth
😧 anguished face
😨 fearful face
😰 anxious face with sweat
😥 sad but relieved face
😢 crying face
😭 loudly crying face
😱 face screaming in fear
😖 confounded face
😣 persevering face
😞 disappointed face
😓 downcast face with sweat
😩 weary face
😫 tired face
🥱 yawning face
😤 face with steam from nose
😡 pouting face
😠 angry face
🤬 face with symbols on mouth
😈 smiling face with horns
👿 angry face with horns
💀 skull
💩 pile of poo
🤡 clown face
👹 ogre
👺 goblin
👻 ghost
👽 alien
👾 alien monster
🤖 robot
😺 grinning cat
😸 grinning cat with smiling eyes
😹 cat with tears of joy
😻 smiling cat with heart eyes
😼 cat with wry smile
😽 kissing cat
🙀 weary cat
😿 crying cat
😾 pouting cat
❤️ red heart
🧡 orange heart
💛 yellow heart
💚 green heart
💙 blue heart
💜 purple heart
🖤 black heart
🤍 white heart
🤎 brown heart
💔 broken heart
❣️ heavy heart exclamation
💕 two hearts
💞 revolving hearts
💓 beating heart
💗 growing heart
💖 sparkling heart
💘 heart with arrow
💝 heart with ribbon
💟 heart decoration
👍 thumbs up
👎 thumbs down
👌 ok hand
✌️ victory hand
🤞 crossed fingers
🤟 love you gesture
🤘 sign of the horns
🤙 call me hand
👈 backhand index pointing left
👉 backhand index pointing right
👆 backhand index pointing up
👇 backhand index pointing down
☝️ index pointing up
✋ raised hand
🤚 raised back of hand
🖐️ hand with fingers splayed
🖖 vulcan salute
👋 waving hand
🤏 pinching hand
✊ raised fist
👊 oncoming fist
🤛 left facing fist
🤜 right facing fist
👏 clapping hands
🙌 raising hands
👐 open hands
🤲 palms up together
🤝 handshake
🙏 folded hands
💪 flexed biceps
🦾 mechanical arm
🦿 mechanical leg
🦵 leg
🦶 foot
👂 ear
🦻 ear with hearing aid
👃 nose
🧠 brain
🫀 anatomical heart
🫁 lungs
🦷 tooth
🦴 bone
👀 eyes
👁️ eye
👅 tongue
👄 mouth
💋 kiss mark
🔥 fire
💫 dizzy
⭐ star
🌟 glowing star
✨ sparkles
⚡ high voltage
💥 collision
💢 anger symbol
💦 sweat droplets
💨 dashing away
🕳️ hole
💣 bomb
💤 zzz
🎉 party popper
🎊 confetti ball
🎈 balloon
🎁 wrapped gift
🏆 trophy
🥇 1st place medal
🥈 2nd place medal
🥉 3rd place medal
🏅 sports medal
🎖️ military medal
🎗️ reminder ribbon
🎫 ticket
🎟️ admission tickets
🎪 circus tent
🎭 performing arts
🎨 artist palette
🎬 clapper board
🎤 microphone
🎧 headphone
🎼 musical score
🎵 musical note
🎶 musical notes
🎹 musical keyboard
🥁 drum
🎷 saxophone
🎺 trumpet
🎸 guitar
🪕 banjo
🎻 violin
🎲 game die
♠️ spade suit
♥️ heart suit
♦️ diamond suit
♣️ club suit
🃏 joker
🀄 mahjong red dragon
🎴 flower playing cards
🎯 direct hit
🎳 bowling
🎮 video game
🕹️ joystick
🎰 slot machine
🧩 puzzle piece
♟️ chess pawn
🎱 pool 8 ball
🪀 yo yo
🪁 kite
🔮 crystal ball
🪄 magic wand
🧿 nazar amulet
🎊 confetti ball
🎉 party popper
🎈 balloon
🎁 wrapped gift
🎀 ribbon
🎗️ reminder ribbon
🎟️ admission tickets
🎫 ticket
🏆 trophy
🏅 sports medal
🥇 1st place medal
🥈 2nd place medal
🥉 3rd place medal
🎖️ military medal
🏵️ rosette
🎗️ reminder ribbon
🎫 ticket
🎟️ admission tickets
🎪 circus tent
🤹 person juggling
🎭 performing arts
🩰 ballet shoes
🎨 artist palette
🎬 clapper board
🎤 microphone
🎧 headphone
🎼 musical score
🎵 musical note
🎶 musical notes
🎹 musical keyboard
🥁 drum
🪘 long drum
🎷 saxophone
🎺 trumpet
🎸 guitar
🪕 banjo
🎻 violin
🪗 accordion
🪈 flute
📱 mobile phone
💻 laptop
🖥️ desktop computer
🖨️ printer
⌨️ keyboard
🖱️ computer mouse
🖲️ trackball
💽 computer disk
💾 floppy disk
💿 optical disk
📀 dvd
🧮 abacus
🎥 movie camera
📹 video camera
📷 camera
📸 camera with flash
📼 videocassette
🔍 magnifying glass tilted left
🔎 magnifying glass tilted right
🕯️ candle
💡 light bulb
🔦 flashlight
🏮 red paper lantern
🪔 diya lamp
📔 notebook with decorative cover
📕 closed book
📖 open book
📗 green book
📘 blue book
📙 orange book
📚 books
📓 notebook
📒 ledger
📃 page with curl
📜 scroll
📄 page facing up
📰 newspaper
🗞️ rolled up newspaper
📑 bookmark tabs
🔖 bookmark
🏷️ label
💰 money bag
🪙 coin
💴 yen banknote
💵 dollar banknote
💶 euro banknote
💷 pound banknote
💸 money with wings
💳 credit card
🧾 receipt
💎 gem stone
⚖️ balance scale
🪜 ladder
🧰 toolbox
🪛 screwdriver
🔧 wrench
🔨 hammer
⛏️ pick
🛠️ hammer and wrench
⚒️ hammer and pick
💣 bomb
🪃 boomerang
🏹 bow and arrow
🛡️ shield
🪚 carpentry saw
🔪 kitchen knife
🗡️ dagger
⚔️ crossed swords
🔫 water pistol
🪄 magic wand
🎣 fishing pole
🤿 diving mask
🎿 skis
🛷 sled
🥌 curling stone
🎯 direct hit
🪀 yo yo
🪁 kite
🎱 pool 8 ball
🔮 crystal ball
🪩 mirror ball
🧿 nazar amulet
🎊 confetti ball
🎉 party popper
🎈 balloon
🎁 wrapped gift
🎀 ribbon
🎗️ reminder ribbon
🎟️ admission tickets
🎫 ticket"
# Create temporary file for emoji list
TEMP_FILE=$(mktemp)
echo "$EMOJI_LIST" > "$TEMP_FILE"
# Use fuzzel to select emoji
SELECTED=$(cat "$TEMP_FILE" | fuzzel --dmenu --prompt="Emoji: " --width=50 --lines=15)
# Clean up temp file
rm "$TEMP_FILE"
# Extract just the emoji (first character)
if [[ -n "$SELECTED" ]]; then
EMOJI=$(echo "$SELECTED" | cut -d' ' -f1)
# Copy to clipboard using wl-clipboard
echo -n "$EMOJI" | wl-copy
# Send notification
notify-send "Emoji Copied" "$EMOJI copied to clipboard" --icon="face-smile" --timeout=2000
# Also type it directly (optional - can be disabled)
# wtype "$EMOJI"
fi
+127
View File
@@ -0,0 +1,127 @@
#!/usr/bin/env bash
# Color generation script for quickshell Material You theming
# Based on the original dots-hyprland color generation system
WALLPAPER="${1:-$HOME/Backgrounds/love-is-love.jpg}"
CACHE_DIR="$HOME/.cache/dots-hyprland/colors"
echo "🎨 Generating Material You colors from: $WALLPAPER"
# Create cache directory
mkdir -p "$CACHE_DIR"
# Check if wallpaper exists
if [[ ! -f "$WALLPAPER" ]]; then
echo "❌ Wallpaper not found: $WALLPAPER"
echo "Using default colors..."
# Create basic color scheme as fallback
cat > "$CACHE_DIR/colors.json" << 'EOF'
{
"colors": {
"primary": "#bb86fc",
"onPrimary": "#000000",
"secondary": "#03dac6",
"onSecondary": "#000000",
"surface": "#121212",
"onSurface": "#ffffff",
"background": "#121212",
"onBackground": "#ffffff",
"error": "#cf6679",
"onError": "#000000"
}
}
EOF
exit 0
fi
# Generate colors using matugen if available
if command -v matugen >/dev/null 2>&1; then
echo "Using matugen for color generation..."
matugen image "$WALLPAPER" \
--mode dark \
--type scheme-content \
--contrast 0.0 \
--json > "$CACHE_DIR/colors.json"
if [[ $? -eq 0 ]]; then
echo "✅ Colors generated successfully with matugen"
else
echo "❌ matugen failed, using fallback colors"
fi
else
echo "⚠️ matugen not found, using basic color extraction..."
# Basic color extraction using imagemagick if available
if command -v convert >/dev/null 2>&1; then
# Extract dominant color
DOMINANT=$(convert "$WALLPAPER" -resize 1x1\! -format '%[pixel:u]' info:-)
echo "Dominant color: $DOMINANT"
# Create basic color scheme
cat > "$CACHE_DIR/colors.json" << EOF
{
"colors": {
"primary": "#bb86fc",
"onPrimary": "#000000",
"secondary": "#03dac6",
"onSecondary": "#000000",
"surface": "#1a1b26",
"onSurface": "#ffffff",
"background": "#1a1b26",
"onBackground": "#ffffff",
"error": "#cf6679",
"onError": "#000000"
}
}
EOF
else
echo "❌ No color generation tools available"
exit 1
fi
fi
# Generate quickshell-specific color files
echo "Generating quickshell color configurations..."
# Extract colors for quickshell
if [[ -f "$CACHE_DIR/colors.json" ]]; then
# Create quickshell color configuration
cat > "$CACHE_DIR/quickshell-colors.qml" << 'EOF'
// Generated Material You colors for quickshell
pragma Singleton
import QtQuick
QtObject {
// Material You color scheme
readonly property string primary: "#bb86fc"
readonly property string onPrimary: "#000000"
readonly property string secondary: "#03dac6"
readonly property string onSecondary: "#000000"
readonly property string surface: "#1a1b26"
readonly property string onSurface: "#ffffff"
readonly property string background: "#1a1b26"
readonly property string onBackground: "#ffffff"
readonly property string error: "#cf6679"
readonly property string onError: "#000000"
// Additional colors for UI elements
readonly property string accent: primary
readonly property string outline: "#444444"
readonly property string surfaceVariant: "#2a2b36"
readonly property string onSurfaceVariant: "#cccccc"
}
EOF
echo "✅ Quickshell colors generated"
fi
# Update wallpaper if using swww
if command -v swww >/dev/null 2>&1; then
echo "Updating wallpaper with swww..."
swww img "$WALLPAPER" --transition-type fade --transition-duration 1
fi
echo "🎨 Color generation complete!"
echo "Colors saved to: $CACHE_DIR/"
+243
View File
@@ -0,0 +1,243 @@
#!/usr/bin/env bash
# Screen recording script using wf-recorder
# Bound to SUPER + ALT + R in Hyprland
set -euo pipefail
# Configuration
RECORDINGS_DIR="$HOME/Videos/Recordings"
TEMP_DIR="/tmp/dots-hyprland-recording"
PID_FILE="$TEMP_DIR/recording.pid"
STATUS_FILE="$TEMP_DIR/recording.status"
# Ensure directories exist
mkdir -p "$RECORDINGS_DIR"
mkdir -p "$TEMP_DIR"
# Function to show notification
notify_user() {
local title="$1"
local message="$2"
local icon="${3:-video-display}"
local timeout="${4:-3000}"
notify-send "$title" "$message" --icon="$icon" --timeout="$timeout"
}
# Function to get current timestamp
get_timestamp() {
date +"%Y-%m-%d_%H-%M-%S"
}
# Function to start recording
start_recording() {
local mode="$1"
local output_file="$RECORDINGS_DIR/recording_$(get_timestamp()).mp4"
case "$mode" in
"fullscreen")
notify_user "Screen Recording" "Starting fullscreen recording..." "media-record"
wf-recorder -f "$output_file" &
;;
"region")
notify_user "Screen Recording" "Select region to record..." "media-record"
# Use slurp to select region
local geometry
geometry=$(slurp 2>/dev/null) || {
notify_user "Recording Cancelled" "No region selected" "dialog-error"
return 1
}
wf-recorder -g "$geometry" -f "$output_file" &
;;
"window")
notify_user "Screen Recording" "Click on window to record..." "media-record"
# Get window geometry using hyprctl
local window_info
window_info=$(hyprctl activewindow -j 2>/dev/null) || {
notify_user "Recording Error" "Could not get window info" "dialog-error"
return 1
}
# Extract geometry from JSON
local x y width height
x=$(echo "$window_info" | jq -r '.at[0]')
y=$(echo "$window_info" | jq -r '.at[1]')
width=$(echo "$window_info" | jq -r '.size[0]')
height=$(echo "$window_info" | jq -r '.size[1]')
wf-recorder -g "${x},${y} ${width}x${height}" -f "$output_file" &
;;
*)
notify_user "Recording Error" "Invalid recording mode: $mode" "dialog-error"
return 1
;;
esac
local pid=$!
echo "$pid" > "$PID_FILE"
echo "$output_file" > "$STATUS_FILE"
# Wait a moment to ensure recording started
sleep 1
if kill -0 "$pid" 2>/dev/null; then
notify_user "Recording Started" "Recording to: $(basename "$output_file")" "media-record" 5000
echo "Recording started with PID: $pid"
echo "Output file: $output_file"
else
notify_user "Recording Failed" "Could not start recording" "dialog-error"
rm -f "$PID_FILE" "$STATUS_FILE"
return 1
fi
}
# Function to stop recording
stop_recording() {
if [[ ! -f "$PID_FILE" ]]; then
notify_user "No Recording" "No active recording found" "dialog-information"
return 1
fi
local pid
pid=$(cat "$PID_FILE")
local output_file
output_file=$(cat "$STATUS_FILE" 2>/dev/null || echo "unknown")
if kill -0 "$pid" 2>/dev/null; then
# Send SIGINT to gracefully stop recording
kill -INT "$pid"
# Wait for process to finish
local count=0
while kill -0 "$pid" 2>/dev/null && [[ $count -lt 10 ]]; do
sleep 0.5
((count++))
done
# Force kill if still running
if kill -0 "$pid" 2>/dev/null; then
kill -KILL "$pid" 2>/dev/null || true
fi
rm -f "$PID_FILE" "$STATUS_FILE"
# Check if file was created and has content
if [[ -f "$output_file" ]] && [[ -s "$output_file" ]]; then
local file_size
file_size=$(du -h "$output_file" | cut -f1)
notify_user "Recording Stopped" "Saved: $(basename "$output_file") ($file_size)" "media-record" 5000
# Optionally open the recordings directory
# nautilus "$RECORDINGS_DIR" &
else
notify_user "Recording Error" "Recording file is empty or missing" "dialog-error"
fi
else
notify_user "Recording Error" "Recording process not found" "dialog-error"
rm -f "$PID_FILE" "$STATUS_FILE"
fi
}
# Function to check recording status
check_status() {
if [[ -f "$PID_FILE" ]]; then
local pid
pid=$(cat "$PID_FILE")
if kill -0 "$pid" 2>/dev/null; then
local output_file
output_file=$(cat "$STATUS_FILE" 2>/dev/null || echo "unknown")
notify_user "Recording Active" "Currently recording to: $(basename "$output_file")" "media-record"
return 0
else
# Clean up stale files
rm -f "$PID_FILE" "$STATUS_FILE"
fi
fi
notify_user "No Recording" "No active recording" "dialog-information"
return 1
}
# Function to show recording menu
show_menu() {
local choice
choice=$(echo -e "🔴 Start Fullscreen Recording\n📱 Start Region Recording\n🪟 Start Window Recording\n⏹️ Stop Recording\n📊 Check Status\n📁 Open Recordings Folder" | \
fuzzel --dmenu --prompt="Recording: " --width=40 --lines=6)
case "$choice" in
"🔴 Start Fullscreen Recording")
start_recording "fullscreen"
;;
"📱 Start Region Recording")
start_recording "region"
;;
"🪟 Start Window Recording")
start_recording "window"
;;
"⏹️ Stop Recording")
stop_recording
;;
"📊 Check Status")
check_status
;;
"📁 Open Recordings Folder")
nautilus "$RECORDINGS_DIR" &
;;
"")
# User cancelled
exit 0
;;
*)
notify_user "Invalid Choice" "Unknown option selected" "dialog-error"
;;
esac
}
# Main logic
main() {
# Check if required tools are available
local missing_tools=()
command -v wf-recorder >/dev/null || missing_tools+=("wf-recorder")
command -v slurp >/dev/null || missing_tools+=("slurp")
command -v jq >/dev/null || missing_tools+=("jq")
command -v notify-send >/dev/null || missing_tools+=("libnotify")
if [[ ${#missing_tools[@]} -gt 0 ]]; then
echo "Error: Missing required tools: ${missing_tools[*]}"
notify_user "Recording Error" "Missing tools: ${missing_tools[*]}" "dialog-error"
exit 1
fi
# Parse command line arguments
case "${1:-menu}" in
"start"|"fullscreen")
start_recording "fullscreen"
;;
"region")
start_recording "region"
;;
"window")
start_recording "window"
;;
"stop")
stop_recording
;;
"status")
check_status
;;
"toggle")
if check_status >/dev/null 2>&1; then
stop_recording
else
show_menu
fi
;;
"menu"|*)
show_menu
;;
esac
}
# Run main function
main "$@"
+226
View File
@@ -0,0 +1,226 @@
#!/usr/bin/env bash
# Phase 4 Testing Script
# Tests all advanced features of dots-hyprland
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
NC='\033[0m' # No Color
log() {
echo -e "${GREEN}[$(date +'%H:%M:%S')] $1${NC}"
}
warn() {
echo -e "${YELLOW}[$(date +'%H:%M:%S')] WARNING: $1${NC}"
}
error() {
echo -e "${RED}[$(date +'%H:%M:%S')] ERROR: $1${NC}"
}
info() {
echo -e "${BLUE}[$(date +'%H:%M:%S')] $1${NC}"
}
phase4() {
echo -e "${PURPLE}[$(date +'%H:%M:%S')] PHASE 4: $1${NC}"
}
# Test functions
test_build() {
log "Testing Phase 4 build..."
if nix build "$PROJECT_ROOT#homeConfigurations.example.activationPackage" --no-link; then
log "✅ Phase 4 build successful"
return 0
else
error "❌ Phase 4 build failed"
return 1
fi
}
test_ai_integration() {
phase4 "Testing AI Integration"
# Check if Ollama is available
if command -v ollama >/dev/null 2>&1; then
log "✅ Ollama available"
else
warn "⚠️ Ollama not found - AI features may not work"
fi
# Test AI configuration generation
if [[ -f "$PROJECT_ROOT/modules/components/ai.nix" ]]; then
log "✅ AI module exists"
else
error "❌ AI module missing"
return 1
fi
}
test_advanced_widgets() {
phase4 "Testing Advanced Widget System"
local widgets=(
"overview/Overview.qml.template"
"sidebarLeft/SidebarLeft.qml.template"
"screenCorners/ScreenCorners.qml.template"
"session/SessionManager.qml.template"
)
for widget in "${widgets[@]}"; do
if [[ -f "$PROJECT_ROOT/configs/quickshell/ii/modules/$widget" ]]; then
log "✅ Widget template exists: $widget"
else
error "❌ Widget template missing: $widget"
return 1
fi
done
}
test_material_you_theming() {
phase4 "Testing Material You Theming System"
if [[ -f "$PROJECT_ROOT/lib/material-colors.nix" ]]; then
log "✅ Material You theming system exists"
else
error "❌ Material You theming system missing"
return 1
fi
# Check if matugen is available
if nix shell nixpkgs#matugen -c matugen --version >/dev/null 2>&1; then
log "✅ matugen available for color generation"
else
warn "⚠️ matugen not available - theming may not work"
fi
}
test_quality_of_life() {
phase4 "Testing Quality of Life Features"
local features=(
"screenCorners/ScreenCorners.qml.template"
"session/SessionManager.qml.template"
)
for feature in "${features[@]}"; do
if [[ -f "$PROJECT_ROOT/configs/quickshell/ii/modules/$feature" ]]; then
log "✅ QoL feature exists: $feature"
else
error "❌ QoL feature missing: $feature"
return 1
fi
done
}
test_development_environment() {
phase4 "Testing Development Environment"
log "Entering development environment..."
if nix develop "$PROJECT_ROOT" -c bash -c "echo 'Development environment working' && which quickshell" >/dev/null 2>&1; then
log "✅ Development environment functional"
else
error "❌ Development environment issues"
return 1
fi
}
show_phase4_status() {
phase4 "Phase 4 Implementation Status"
echo
echo "🤖 AI Integration:"
echo " - [x] AI module with Gemini & Ollama support"
echo " - [x] Configurable providers and features"
echo " - [x] Systemd service integration"
echo " - [x] AI chat interface scripts"
echo
echo "🎨 Advanced Widget System:"
echo " - [x] Overview with window previews"
echo " - [x] AI-powered left sidebar"
echo " - [x] Interactive components"
echo " - [x] Search functionality"
echo
echo "🌈 Material You Theming:"
echo " - [x] Advanced color generation"
echo " - [x] Multi-application theming"
echo " - [x] Dynamic palette creation"
echo " - [x] Theme application system"
echo
echo "🖱️ Quality of Life:"
echo " - [x] Screen corner interactions"
echo " - [x] Session management"
echo " - [x] Brightness controls"
echo " - [x] Confirmation dialogs"
echo
echo "📊 Overall Progress: Phase 4 Foundation Complete! 🎉"
}
# Main execution
main() {
echo "🚀 Phase 4: Advanced Features Testing"
echo "======================================"
echo
local failed_tests=()
# Run all tests
if ! test_build; then
failed_tests+=("build")
fi
if ! test_ai_integration; then
failed_tests+=("ai_integration")
fi
if ! test_advanced_widgets; then
failed_tests+=("advanced_widgets")
fi
if ! test_material_you_theming; then
failed_tests+=("material_you_theming")
fi
if ! test_quality_of_life; then
failed_tests+=("quality_of_life")
fi
if ! test_development_environment; then
failed_tests+=("development_environment")
fi
echo
echo "======================================"
# Show results
if [[ ${#failed_tests[@]} -eq 0 ]]; then
log "🎉 All Phase 4 tests passed!"
show_phase4_status
echo
log "🚀 Ready to enable advanced features!"
echo
echo "Next steps:"
echo "1. Enable AI integration: components.ai = true"
echo "2. Enable theming: components.theming = true"
echo "3. Enable advanced features: features.sidebar = true"
echo "4. Test in VM or real environment"
exit 0
else
error "${#failed_tests[@]} test(s) failed:"
printf '%s\n' "${failed_tests[@]}"
exit 1
fi
}
# Run tests
main "$@"
+404
View File
@@ -0,0 +1,404 @@
#!/usr/bin/env bash
# Phase 5 Testing Script
# Tests NixOS-specific adaptations and integration patterns
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
log() {
echo -e "${GREEN}[$(date +'%H:%M:%S')] $1${NC}"
}
warn() {
echo -e "${YELLOW}[$(date +'%H:%M:%S')] WARNING: $1${NC}"
}
error() {
echo -e "${RED}[$(date +'%H:%M:%S')] ERROR: $1${NC}"
}
info() {
echo -e "${BLUE}[$(date +'%H:%M:%S')] $1${NC}"
}
phase5() {
echo -e "${CYAN}[$(date +'%H:%M:%S')] PHASE 5: $1${NC}"
}
# Test functions
test_build() {
log "Testing Phase 5 build..."
if nix build "$PROJECT_ROOT#homeConfigurations.example.activationPackage" --no-link; then
log "✅ Phase 5 build successful"
return 0
else
error "❌ Phase 5 build failed"
return 1
fi
}
test_nixos_system_integration() {
phase5 "Testing NixOS System Integration"
if [[ -f "$PROJECT_ROOT/modules/nixos-system.nix" ]]; then
log "✅ NixOS system module exists"
# Test module syntax
if nix-instantiate --parse "$PROJECT_ROOT/modules/nixos-system.nix" >/dev/null 2>&1; then
log "✅ NixOS system module syntax valid"
else
error "❌ NixOS system module syntax invalid"
return 1
fi
else
error "❌ NixOS system module missing"
return 1
fi
# Check for key NixOS integration features
local features=(
"hardware support"
"display manager"
"security integration"
"network configuration"
"virtualization support"
"development tools"
)
for feature in "${features[@]}"; do
if grep -q "$(echo "$feature" | tr ' ' '.')" "$PROJECT_ROOT/modules/nixos-system.nix"; then
log "✅ NixOS integration includes: $feature"
else
warn "⚠️ NixOS integration missing: $feature"
fi
done
}
test_user_customization_system() {
phase5 "Testing User Customization System"
if [[ -f "$PROJECT_ROOT/modules/components/customization.nix" ]]; then
log "✅ User customization module exists"
# Test module syntax
if nix-instantiate --parse "$PROJECT_ROOT/modules/components/customization.nix" >/dev/null 2>&1; then
log "✅ User customization module syntax valid"
else
error "❌ User customization module syntax invalid"
return 1
fi
else
error "❌ User customization module missing"
return 1
fi
# Check for customization features
local features=(
"customConfigs"
"customScripts"
"environmentVariables"
"hooks"
"templateOverrides"
"keybindOverrides"
"widgets"
)
for feature in "${features[@]}"; do
if grep -q "$feature" "$PROJECT_ROOT/modules/components/customization.nix"; then
log "✅ Customization includes: $feature"
else
warn "⚠️ Customization missing: $feature"
fi
done
}
test_template_processing() {
phase5 "Testing Template Processing Framework"
if [[ -f "$PROJECT_ROOT/lib/template-processor.nix" ]]; then
log "✅ Template processor exists"
# Test template processor syntax
if nix-instantiate --parse "$PROJECT_ROOT/lib/template-processor.nix" >/dev/null 2>&1; then
log "✅ Template processor syntax valid"
else
error "❌ Template processor syntax invalid"
return 1
fi
else
error "❌ Template processor missing"
return 1
fi
# Check for template processing features
local features=(
"processTemplate"
"generateConfigFromTemplate"
"applyColorScheme"
"createTemplateSystem"
"validateConfig"
"createHotReloader"
"processMultiFormat"
)
for feature in "${features[@]}"; do
if grep -q "$feature" "$PROJECT_ROOT/lib/template-processor.nix"; then
log "✅ Template processing includes: $feature"
else
warn "⚠️ Template processing missing: $feature"
fi
done
}
test_service_management() {
phase5 "Testing Service Management Adaptation"
if [[ -f "$PROJECT_ROOT/modules/components/service-management-simple.nix" ]]; then
log "✅ Service management module exists"
# Test module syntax
if nix-instantiate --parse "$PROJECT_ROOT/modules/components/service-management-simple.nix" >/dev/null 2>&1; then
log "✅ Service management module syntax valid"
else
error "❌ Service management module syntax invalid"
return 1
fi
else
error "❌ Service management module missing"
return 1
fi
# Check for service management features
local features=(
"session target"
"core services"
"quickshell"
"hypridle"
)
for feature in "${features[@]}"; do
if grep -q "$(echo "$feature" | tr ' ' '.')" "$PROJECT_ROOT/modules/components/service-management-simple.nix"; then
log "✅ Service management includes: $feature"
else
warn "⚠️ Service management missing: $feature"
fi
done
}
test_arch_replacement() {
phase5 "Testing Arch-Specific Element Replacement"
log "Checking for Arch-specific patterns..."
# Check that we don't have Arch-specific commands
local arch_patterns=(
"pacman"
"yay"
"systemctl --user enable"
"cp -r .config"
"makepkg"
"PKGBUILD"
)
local found_arch=false
for pattern in "${arch_patterns[@]}"; do
if find "$PROJECT_ROOT" -name "*.nix" -exec grep -l "$pattern" {} \; 2>/dev/null | grep -v test; then
warn "⚠️ Found Arch-specific pattern: $pattern"
found_arch=true
fi
done
if [[ $found_arch == false ]]; then
log "✅ No Arch-specific patterns found in Nix files"
fi
# Check for NixOS patterns
local nixos_patterns=(
"xdg.configFile"
"home.packages"
"systemd.user.services"
"programs\."
"services\."
"mkEnableOption"
"mkOption"
)
local found_nixos=0
for pattern in "${nixos_patterns[@]}"; do
if find "$PROJECT_ROOT" -name "*.nix" -exec grep -l "$pattern" {} \; 2>/dev/null | wc -l | grep -q "[1-9]"; then
log "✅ Found NixOS pattern: $pattern"
((found_nixos++))
fi
done
if [[ $found_nixos -ge 5 ]]; then
log "✅ Strong NixOS integration patterns detected"
else
warn "⚠️ Limited NixOS integration patterns found"
fi
}
test_declarative_configuration() {
phase5 "Testing Declarative Configuration Management"
# Check for declarative patterns
local declarative_features=(
"enable.*mkEnableOption"
"mkOption.*type.*types\."
"config.*mkIf.*cfg\."
"home\.packages.*with.*pkgs"
"systemd\.user\.services"
"xdg\.configFile"
)
local found_declarative=0
for feature in "${declarative_features[@]}"; do
if find "$PROJECT_ROOT" -name "*.nix" -exec grep -l "$feature" {} \; 2>/dev/null | wc -l | grep -q "[1-9]"; then
log "✅ Found declarative pattern: $feature"
((found_declarative++))
fi
done
if [[ $found_declarative -ge 4 ]]; then
log "✅ Strong declarative configuration patterns"
else
warn "⚠️ Limited declarative configuration patterns"
fi
}
test_development_environment() {
phase5 "Testing Development Environment"
log "Testing development environment..."
if nix develop "$PROJECT_ROOT" -c bash -c "echo 'Development environment working' && which quickshell" >/dev/null 2>&1; then
log "✅ Development environment functional"
else
error "❌ Development environment issues"
return 1
fi
}
show_phase5_status() {
phase5 "Phase 5 Implementation Status"
echo
echo "🏗️ NixOS System Integration:"
echo " - [x] Comprehensive hardware support configuration"
echo " - [x] Display manager integration (GDM, SDDM, LightDM, Greetd)"
echo " - [x] Security framework (PolicyKit, AppArmor, Firewall)"
echo " - [x] Network configuration (NetworkManager, Wireless, VPN)"
echo " - [x] Virtualization support (Docker, Podman, libvirt)"
echo " - [x] Development tools with language support"
echo
echo "🎨 User Customization System:"
echo " - [x] Custom configuration file overrides"
echo " - [x] Custom script management with dependencies"
echo " - [x] Environment variable customization"
echo " - [x] Hook system (pre/post-start, color-change, shutdown)"
echo " - [x] Template and keybind overrides"
echo " - [x] Widget configuration system"
echo
echo "🔧 Template Processing Framework:"
echo " - [x] Advanced template system with inheritance"
echo " - [x] Conditional template blocks"
echo " - [x] Multi-format processing (QML, JSON, CSS)"
echo " - [x] Color scheme integration"
echo " - [x] Hot-reloading system"
echo " - [x] Template validation and debugging"
echo
echo "⚙️ Service Management Adaptation:"
echo " - [x] Declarative systemd user service management"
echo " - [x] Session target integration"
echo " - [x] Core and optional service configuration"
echo " - [x] Custom service definition system"
echo " - [x] Service monitoring and health checks"
echo " - [x] Service management CLI tools"
echo
echo "🔄 NixOS Pattern Replacements:"
echo " - [x] Arch package management → Declarative Nix"
echo " - [x] Manual service management → systemd user services"
echo " - [x] Direct file copying → xdg.configFile patterns"
echo " - [x] Imperative configuration → Declarative options"
echo " - [x] Manual customization → Structured override system"
echo
echo "📊 Overall Progress: Phase 5 NixOS Adaptations Complete! 🎉"
}
# Main execution
main() {
echo "🔧 Phase 5: NixOS-Specific Adaptations Testing"
echo "=============================================="
echo
local failed_tests=()
# Run all tests
if ! test_build; then
failed_tests+=("build")
fi
if ! test_nixos_system_integration; then
failed_tests+=("nixos_system_integration")
fi
if ! test_user_customization_system; then
failed_tests+=("user_customization_system")
fi
if ! test_template_processing; then
failed_tests+=("template_processing")
fi
if ! test_service_management; then
failed_tests+=("service_management")
fi
if ! test_arch_replacement; then
failed_tests+=("arch_replacement")
fi
if ! test_declarative_configuration; then
failed_tests+=("declarative_configuration")
fi
if ! test_development_environment; then
failed_tests+=("development_environment")
fi
echo
echo "=============================================="
# Show results
if [[ ${#failed_tests[@]} -eq 0 ]]; then
log "🎉 All Phase 5 tests passed!"
show_phase5_status
echo
log "🚀 Ready for Phase 6: Testing & Validation!"
echo
echo "Next steps:"
echo "1. Enable advanced components: AI, customization, service management"
echo "2. Test complete integration in VM environment"
echo "3. Validate user customization workflows"
echo "4. Proceed to comprehensive testing phase"
exit 0
else
error "${#failed_tests[@]} test(s) failed:"
printf '%s\n' "${failed_tests[@]}"
exit 1
fi
}
# Run tests
main "$@"
+312
View File
@@ -0,0 +1,312 @@
#!/usr/bin/env bash
# Screen magnification script for accessibility
# Bound to SUPER + ALT + = in Hyprland
set -euo pipefail
# Configuration
ZOOM_LEVELS=(1.0 1.25 1.5 1.75 2.0 2.5 3.0 4.0 5.0)
CONFIG_DIR="$HOME/.config/dots-hyprland"
STATE_FILE="$CONFIG_DIR/zoom_state"
TEMP_DIR="/tmp/dots-hyprland-zoom"
# Ensure directories exist
mkdir -p "$CONFIG_DIR"
mkdir -p "$TEMP_DIR"
# Function to show notification
notify_user() {
local title="$1"
local message="$2"
local icon="${3:-zoom-in}"
local timeout="${4:-2000}"
notify-send "$title" "$message" --icon="$icon" --timeout="$timeout"
}
# Function to get current zoom level
get_current_zoom() {
if [[ -f "$STATE_FILE" ]]; then
cat "$STATE_FILE"
else
echo "1.0"
fi
}
# Function to save zoom level
save_zoom_level() {
local level="$1"
echo "$level" > "$STATE_FILE"
}
# Function to find next zoom level
get_next_zoom_level() {
local current="$1"
local direction="${2:-up}" # up or down
# Find current index
local current_index=-1
for i in "${!ZOOM_LEVELS[@]}"; do
if [[ "${ZOOM_LEVELS[$i]}" == "$current" ]]; then
current_index=$i
break
fi
done
# If current level not found, start from 1.0
if [[ $current_index -eq -1 ]]; then
current_index=0
fi
# Calculate next index
local next_index
if [[ "$direction" == "up" ]]; then
next_index=$((current_index + 1))
if [[ $next_index -ge ${#ZOOM_LEVELS[@]} ]]; then
next_index=$((${#ZOOM_LEVELS[@]} - 1))
fi
else
next_index=$((current_index - 1))
if [[ $next_index -lt 0 ]]; then
next_index=0
fi
fi
echo "${ZOOM_LEVELS[$next_index]}"
}
# Function to apply zoom using Hyprland
apply_hyprland_zoom() {
local zoom_level="$1"
# Use hyprctl to set zoom
if command -v hyprctl >/dev/null; then
# Get current monitor
local monitor
monitor=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .name' 2>/dev/null || echo "")
if [[ -n "$monitor" ]]; then
# Apply zoom to the focused monitor
hyprctl keyword monitor "$monitor,preferred,auto,$zoom_level" 2>/dev/null || {
# Fallback: try to set global zoom
hyprctl keyword misc:cursor_zoom_factor "$zoom_level" 2>/dev/null || true
}
fi
fi
}
# Function to apply zoom using wlr-randr (fallback)
apply_wlr_zoom() {
local zoom_level="$1"
if command -v wlr-randr >/dev/null; then
# Get current output
local output
output=$(wlr-randr | grep -E "^[A-Z]" | head -n1 | cut -d' ' -f1)
if [[ -n "$output" ]]; then
wlr-randr --output "$output" --scale "$zoom_level" 2>/dev/null || true
fi
fi
}
# Function to set zoom level
set_zoom() {
local zoom_level="$1"
# Validate zoom level
local valid=false
for level in "${ZOOM_LEVELS[@]}"; do
if [[ "$level" == "$zoom_level" ]]; then
valid=true
break
fi
done
if [[ "$valid" != "true" ]]; then
notify_user "Zoom Error" "Invalid zoom level: $zoom_level" "dialog-error"
return 1
fi
# Apply zoom
apply_hyprland_zoom "$zoom_level"
# Save state
save_zoom_level "$zoom_level"
# Show notification
local percentage
percentage=$(echo "$zoom_level * 100" | bc -l | cut -d. -f1)
if [[ "$zoom_level" == "1.0" ]]; then
notify_user "Zoom Reset" "Zoom level: ${percentage}% (Normal)" "zoom-original"
else
notify_user "Zoom Level" "Zoom level: ${percentage}%" "zoom-in"
fi
}
# Function to zoom in
zoom_in() {
local current
current=$(get_current_zoom)
local next
next=$(get_next_zoom_level "$current" "up")
if [[ "$next" == "$current" ]]; then
notify_user "Maximum Zoom" "Already at maximum zoom level" "zoom-in"
else
set_zoom "$next"
fi
}
# Function to zoom out
zoom_out() {
local current
current=$(get_current_zoom)
local next
next=$(get_next_zoom_level "$current" "down")
if [[ "$next" == "$current" ]]; then
notify_user "Minimum Zoom" "Already at minimum zoom level" "zoom-out"
else
set_zoom "$next"
fi
}
# Function to reset zoom
reset_zoom() {
set_zoom "1.0"
}
# Function to show zoom menu
show_menu() {
local current
current=$(get_current_zoom)
local current_percentage
current_percentage=$(echo "$current * 100" | bc -l | cut -d. -f1)
# Build menu options
local menu_options=""
for level in "${ZOOM_LEVELS[@]}"; do
local percentage
percentage=$(echo "$level * 100" | bc -l | cut -d. -f1)
local marker=""
if [[ "$level" == "$current" ]]; then
marker=" ✓"
fi
if [[ "$level" == "1.0" ]]; then
menu_options+="🔍 ${percentage}% (Normal)${marker}\n"
else
menu_options+="🔍 ${percentage}%${marker}\n"
fi
done
# Add control options
menu_options+="\n Zoom In\n Zoom Out\n🔄 Reset Zoom\n📊 Current: ${current_percentage}%"
local choice
choice=$(echo -e "$menu_options" | fuzzel --dmenu --prompt="Zoom: " --width=30 --lines=12)
case "$choice" in
*"Zoom In")
zoom_in
;;
*"Zoom Out")
zoom_out
;;
*"Reset Zoom")
reset_zoom
;;
*"Current:"*)
# Just show current status
notify_user "Current Zoom" "Zoom level: ${current_percentage}%" "zoom-in"
;;
🔍*)
# Extract percentage and convert to decimal
local selected_percentage
selected_percentage=$(echo "$choice" | grep -o '[0-9]\+%' | tr -d '%')
local selected_level
selected_level=$(echo "scale=2; $selected_percentage / 100" | bc -l)
set_zoom "$selected_level"
;;
"")
# User cancelled
exit 0
;;
*)
notify_user "Invalid Choice" "Unknown option selected" "dialog-error"
;;
esac
}
# Function to toggle zoom (between 1.0 and 2.0)
toggle_zoom() {
local current
current=$(get_current_zoom)
if [[ "$current" == "1.0" ]]; then
set_zoom "2.0"
else
set_zoom "1.0"
fi
}
# Function to show current zoom status
show_status() {
local current
current=$(get_current_zoom)
local percentage
percentage=$(echo "$current * 100" | bc -l | cut -d. -f1)
notify_user "Zoom Status" "Current zoom level: ${percentage}%" "zoom-in" 3000
}
# Main logic
main() {
# Check if required tools are available
local missing_tools=()
command -v bc >/dev/null || missing_tools+=("bc")
command -v notify-send >/dev/null || missing_tools+=("libnotify")
if [[ ${#missing_tools[@]} -gt 0 ]]; then
echo "Error: Missing required tools: ${missing_tools[*]}"
notify_user "Zoom Error" "Missing tools: ${missing_tools[*]}" "dialog-error"
exit 1
fi
# Parse command line arguments
case "${1:-menu}" in
"in"|"zoom-in"|"+")
zoom_in
;;
"out"|"zoom-out"|"-")
zoom_out
;;
"reset"|"normal"|"1")
reset_zoom
;;
"toggle")
toggle_zoom
;;
"status")
show_status
;;
"set")
if [[ -n "${2:-}" ]]; then
set_zoom "$2"
else
echo "Usage: $0 set <zoom_level>"
exit 1
fi
;;
"menu"|*)
show_menu
;;
esac
}
# Run main function
main "$@"