added quickshell and updated zsh

This commit is contained in:
2026-08-17 23:16:05 -07:00
parent 9bca669f4e
commit 1f3dde6de2
55 changed files with 4251 additions and 381 deletions

66
flake.lock generated
View File

@@ -77,6 +77,27 @@
"type": "github" "type": "github"
} }
}, },
"herdr": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1787017031,
"narHash": "sha256-FeF4eZhxRl4jBbAkMaEzDCmMcaitV6GZapjaeeNZy7A=",
"owner": "herdrdev",
"repo": "herdr",
"rev": "2d24950ad9a02096921bc764e2e3dcd8900c3366",
"type": "github"
},
"original": {
"owner": "herdrdev",
"repo": "herdr",
"type": "github"
}
},
"home-manager": { "home-manager": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -193,15 +214,58 @@
"type": "github" "type": "github"
} }
}, },
"quickshell": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1786864924,
"narHash": "sha256-9nqIJWuSlAwy4Vs98N9ffoVeU2dmsWcAJ7/DyIDihqM=",
"ref": "refs/heads/master",
"rev": "532a0606cafb05851a203e65be22c9a057447ee2",
"revCount": 844,
"type": "git",
"url": "https://git.outfoxxed.me/outfoxxed/quickshell"
},
"original": {
"type": "git",
"url": "https://git.outfoxxed.me/outfoxxed/quickshell"
}
},
"root": { "root": {
"inputs": { "inputs": {
"antigravity": "antigravity", "antigravity": "antigravity",
"comfy-ui": "comfy-ui", "comfy-ui": "comfy-ui",
"disko": "disko", "disko": "disko",
"herdr": "herdr",
"home-manager": "home-manager", "home-manager": "home-manager",
"nixos-hardware": "nixos-hardware", "nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs_3", "nixpkgs": "nixpkgs_3",
"nixpkgs-unstable": "nixpkgs-unstable" "nixpkgs-unstable": "nixpkgs-unstable",
"quickshell": "quickshell"
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": [
"herdr",
"nixpkgs"
]
},
"locked": {
"lastModified": 1783577481,
"narHash": "sha256-EWMxOWrJ031f8f/lrcEmhTRs4npw1/5N3Hcjin846c8=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "4cdea398dc491b082dccdce0fad1ed0b75fa3394",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
} }
} }
}, },

View File

@@ -24,6 +24,16 @@
comfy-ui = { comfy-ui = {
url = "github:utensils/comfyui-nix"; url = "github:utensils/comfyui-nix";
}; };
quickshell = {
url = "git+https://git.outfoxxed.me/outfoxxed/quickshell";
inputs.nixpkgs.follows = "nixpkgs";
};
herdr = {
url = "github:herdrdev/herdr";
inputs.nixpkgs.follows = "nixpkgs";
};
}; };
outputs = outputs =

View File

@@ -1,11 +1,73 @@
{ pkgs, ... }: { pkgs, inputs, ... }:
let
herdrPkg = if (inputs ? herdr && inputs.herdr ? packages && inputs.herdr.packages ? ${pkgs.stdenv.hostPlatform.system})
then inputs.herdr.packages.${pkgs.stdenv.hostPlatform.system}.default
else (pkgs.herdr or null);
herdrPicker = pkgs.writeShellScriptBin "herdr-picker" (builtins.readFile ./scripts/herdr-picker.sh);
in
{ {
home.packages = (if herdrPkg != null then [ herdrPkg ] else []) ++ [
herdrPicker
];
programs.foot = { programs.foot = {
enable = true; enable = true;
settings = { settings = {
main = { main = {
font = "JetBrainsMono Nerd Font:size=16"; font = "JetBrainsMono Nerd Font:size=15";
font-bold = "JetBrainsMono Nerd Font:size=15:weight=bold";
font-italic = "JetBrainsMono Nerd Font:size=15:slant=italic";
pad = "16x16 center";
shell = "${herdrPicker}/bin/herdr-picker";
selection-target = "clipboard";
};
scrollback = {
lines = 10000;
multiplier = 3.0;
};
cursor = {
style = "beam";
blink = "yes";
beam-thickness = 1.5;
};
mouse = {
hide-when-typing = "yes";
};
colors = {
alpha = 0.90;
background = "18181a";
foreground = "f2f2f7";
# macOS Catalina Apple System Dark Palette
regular0 = "1c1c1e"; # Black / Slate
regular1 = "ff453a"; # Apple Red
regular2 = "30d158"; # Apple Green
regular3 = "ffd60a"; # Apple Yellow
regular4 = "0a84ff"; # Apple Blue
regular5 = "bf5af2"; # Apple Purple
regular6 = "64d2ff"; # Apple Cyan
regular7 = "f2f2f7"; # Apple Light Gray
# Bright Colors
bright0 = "636366"; # Gray
bright1 = "ff6961"; # Bright Red
bright2 = "34c759"; # Bright Green
bright3 = "ffe066"; # Bright Yellow
bright4 = "409cff"; # Bright Blue
bright5 = "c774f4"; # Bright Purple
bright6 = "70d7ff"; # Bright Cyan
bright7 = "ffffff"; # Pure White
# Selection & URLs
selection-foreground = "ffffff";
selection-background = "0058d0"; # Apple selection blue
urls = "0a84ff";
}; };
}; };
}; };

View File

@@ -5,7 +5,7 @@
./hyprland.nix ./hyprland.nix
./hyprlock.nix ./hyprlock.nix
./hypridle.nix ./hypridle.nix
./waybar.nix ./quickshell.nix
]; ];
home.packages = with pkgs; [ home.packages = with pkgs; [
@@ -17,11 +17,8 @@
brightnessctl brightnessctl
# Desktop Environment / Hyprland ecosystem # Desktop Environment / Hyprland ecosystem
waybar
hyprpaper hyprpaper
swaynotificationcenter
rofi rofi
wlogout
hyprpolkitagent hyprpolkitagent
]; ];
} }

View File

@@ -178,9 +178,8 @@ in
_args = [ _args = [
"hyprland.start" "hyprland.start"
(mkLua ''function() (mkLua ''function()
hl.exec_cmd("waybar") hl.exec_cmd("quickshell")
hl.exec_cmd("hyprpaper") hl.exec_cmd("hyprpaper")
hl.exec_cmd("swaync")
hl.exec_cmd("${pkgs.hyprpolkitagent}/libexec/hyprpolkitagent") hl.exec_cmd("${pkgs.hyprpolkitagent}/libexec/hyprpolkitagent")
end'') end'')
]; ];
@@ -194,9 +193,10 @@ in
# Launchers & Window Controls # Launchers & Window Controls
{ _args = [ (mkLua "mainMod .. \" + Q\"") (mkLua "hl.dsp.exec_cmd(terminal)") ]; } { _args = [ (mkLua "mainMod .. \" + Q\"") (mkLua "hl.dsp.exec_cmd(terminal)") ]; }
{ _args = [ (mkLua "mainMod .. \" + C\"") (mkLua "hl.dsp.window.close()") ]; } { _args = [ (mkLua "mainMod .. \" + C\"") (mkLua "hl.dsp.window.close()") ]; }
{ _args = [ (mkLua "mainMod .. \" + N\"") (mkLua "hl.dsp.exec_cmd(\"swaync-client -t -sw\")") ]; } { _args = [ (mkLua "mainMod .. \" + SPACE\"") (mkLua "hl.dsp.exec_cmd(\"quickshell ipc call spotlight toggle || rofi -show combi -show-icons\")") ]; }
{ _args = [ (mkLua "mainMod .. \" + N\"") (mkLua "hl.dsp.exec_cmd(\"quickshell ipc call controlCenter toggle || swaync-client -t -sw\")") ]; }
{ _args = [ (mkLua "mainMod .. \" + V\"") (mkLua "hl.dsp.window.float({ action = \"toggle\" })") ]; } { _args = [ (mkLua "mainMod .. \" + V\"") (mkLua "hl.dsp.window.float({ action = \"toggle\" })") ]; }
{ _args = [ (mkLua "mainMod .. \" + R\"") (mkLua "hl.dsp.exec_cmd(\"rofi -show combi -show-icons\")") ]; } { _args = [ (mkLua "mainMod .. \" + R\"") (mkLua "hl.dsp.exec_cmd(\"quickshell ipc call spotlight toggle || rofi -show combi -show-icons\")") ]; }
{ _args = [ (mkLua "mainMod .. \" + G\"") (mkLua "hl.dsp.group.toggle()") ]; } { _args = [ (mkLua "mainMod .. \" + G\"") (mkLua "hl.dsp.group.toggle()") ]; }
{ _args = [ (mkLua "mainMod .. \" + F\"") (mkLua "hl.dsp.window.fullscreen({ fullscreen = 0 })") ]; } { _args = [ (mkLua "mainMod .. \" + F\"") (mkLua "hl.dsp.window.fullscreen({ fullscreen = 0 })") ]; }
@@ -221,7 +221,7 @@ in
{ _args = [ (mkLua "mainMod .. \" + mouse_up\"") (mkLua "hl.dsp.focus({ workspace = \"e-1\" })") ]; } { _args = [ (mkLua "mainMod .. \" + mouse_up\"") (mkLua "hl.dsp.focus({ workspace = \"e-1\" })") ]; }
# Lock shortcut # Lock shortcut
{ _args = [ (mkLua "mainMod .. \" + S\"") (mkLua "hl.dsp.exec_cmd(\"wlogout\")") ]; } { _args = [ (mkLua "mainMod .. \" + S\"") (mkLua "hl.dsp.exec_cmd(\"hyprlock\")") ]; }
# Quick access applications # Quick access applications
{ _args = [ (mkLua "mainMod .. \" + b\"") (mkLua "hl.dsp.exec_cmd(browser)") ]; } { _args = [ (mkLua "mainMod .. \" + b\"") (mkLua "hl.dsp.exec_cmd(browser)") ]; }

25
home/hypr/quickshell.nix Normal file
View File

@@ -0,0 +1,25 @@
{ pkgs, inputs, ... }:
let
quickshellPkg = if (inputs ? quickshell && inputs.quickshell ? packages && inputs.quickshell.packages ? ${pkgs.stdenv.hostPlatform.system})
then inputs.quickshell.packages.${pkgs.stdenv.hostPlatform.system}.default
else (pkgs.quickshell or pkgs.qt6.qtbase);
in
{
home.packages = with pkgs; [
quickshellPkg
brightnessctl
pamixer
playerctl
libnotify
grim
slurp
wl-clipboard
];
# Link Quickshell configuration into ~/.config/quickshell
xdg.configFile."quickshell" = {
source = ./quickshell;
recursive = true;
};
}

View File

@@ -0,0 +1,280 @@
pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Hyprland
import Quickshell.Io
QtObject {
id: root
// Modal / Overlay states
property bool spotlightVisible: false
property bool controlCenterVisible: false
property bool aboutMacVisible: false
property bool appleMenuVisible: false
property string activeDropdownMenu: ""
property bool volumePopupVisible: false
property bool wifiPopupVisible: false
property bool batteryPopupVisible: false
property bool calendarPopupVisible: false
// Active Window & Compositor info
property string activeWindowTitle: "Desktop"
property string activeWindowClass: "Finder"
property var runningApps: []
// Date & Time
property string timeString: "9:41 AM"
property string dateString: "Mon Oct 21"
property string fullDateString: "Monday, October 21, 2026"
// System Monitoring States
property int cpuPercent: 0
property int memPercent: 0
property string memUsedGb: "0.0"
property string memTotalGb: "0.0"
property int volume: 50
property bool volumeMuted: false
property int brightness: 100
property bool wifiConnected: true
property string wifiSsid: "Wi-Fi"
property string ipAddress: ""
property bool batteryPresent: false
property int batteryPercent: 100
property bool batteryCharging: false
property string batteryStatus: "Full"
// Media Player State (MPRIS)
property string mediaTitle: ""
property string mediaArtist: ""
property bool mediaPlaying: false
// Close all popups and dropdowns
function closeAllPopups() {
appleMenuVisible = false;
activeDropdownMenu = "";
volumePopupVisible = false;
wifiPopupVisible = false;
batteryPopupVisible = false;
calendarPopupVisible = false;
}
function toggleSpotlight() {
closeAllPopups();
spotlightVisible = !spotlightVisible;
}
function toggleControlCenter() {
closeAllPopups();
controlCenterVisible = !controlCenterVisible;
}
function toggleAboutMac() {
closeAllPopups();
aboutMacVisible = !aboutMacVisible;
}
// Hyprland raw event processing
readonly property Connections hyprConn: Connections {
target: Hyprland
function onRawEvent(event) {
if (!event) return;
if (event.startsWith("activewindow>>")) {
const data = event.substring(14);
const parts = data.split(",");
const title = parts[1] ? parts[1].trim() : (parts[0] ? parts[0].trim() : "");
const cls = parts[0] ? parts[0].trim() : "Finder";
root.activeWindowClass = cls && cls.length > 0 ? cls : "Finder";
root.activeWindowTitle = title && title.length > 0 ? title : root.activeWindowClass;
} else if (event.startsWith("activewindowv2>>")) {
// Update running clients
clientsProc.running = true;
} else if (event.startsWith("openwindow>>") || event.startsWith("closewindow>>")) {
clientsProc.running = true;
}
}
}
// Time Updater Timer
readonly property Timer clockTimer: Timer {
interval: 1000
running: true
repeat: true
triggeredOnStart: true
onTriggered: {
const now = new Date();
root.timeString = Qt.formatDateTime(now, "h:mm AP");
root.dateString = Qt.formatDateTime(now, "ddd MMM d");
root.fullDateString = Qt.formatDateTime(now, "dddd, MMMM d, yyyy");
}
}
// System Stats Poll Timer
readonly property Timer statsTimer: Timer {
interval: 3000
running: true
repeat: true
triggeredOnStart: true
onTriggered: {
cpuProc.running = true;
memProc.running = true;
batProc.running = true;
wifiProc.running = true;
audioProc.running = true;
brightProc.running = true;
mprisProc.running = true;
}
}
// Background Process Listeners
readonly property Process cpuProc: Process {
command: ["bash", "-c", "read -r c u n s i io ir st g gn < /proc/stat; t1=$((u+n+s+i+io+ir+st+g+gn)); i1=$((i+io)); sleep 0.15; read -r c u n s i io ir st g gn < /proc/stat; t2=$((u+n+s+i+io+ir+st+g+gn)); i2=$((i+io)); td=$((t2-t1)); id=$((i2-i1)); [ $td -gt 0 ] && echo $(( (td-id)*100/td )) || echo 0"]
stdout: StdioCollector {
onDataChanged: {
const val = parseInt(data.trim());
if (!isNaN(val)) root.cpuPercent = Math.max(0, Math.min(100, val));
}
}
}
readonly property Process memProc: Process {
command: ["bash", "-c", "t=$(grep MemTotal /proc/meminfo | awk '{print $2}'); a=$(grep MemAvailable /proc/meminfo | awk '{print $2}'); if [ -n \"$t\" ] && [ -n \"$a\" ] && [ \"$t\" -gt 0 ]; then u=$((t-a)); p=$((u*100/t)); ug=$(awk \"BEGIN {printf \\\"%.1f\\\", $u/1048576}\"); tg=$(awk \"BEGIN {printf \\\"%.1f\\\", $t/1048576}\"); echo \"$p $ug $tg\"; fi"]
stdout: StdioCollector {
onDataChanged: {
const parts = data.trim().split(" ");
if (parts.length >= 3) {
root.memPercent = parseInt(parts[0]) || 0;
root.memUsedGb = parts[1];
root.memTotalGb = parts[2];
}
}
}
}
readonly property Process batProc: Process {
command: ["bash", "-c", "b=$(find /sys/class/power_supply/ -name 'BAT*' 2>/dev/null | head -n 1); if [ -n \"$b\" ]; then cap=$(cat $b/capacity 2>/dev/null || echo 100); st=$(cat $b/status 2>/dev/null || echo Full); echo \"1 $cap $st\"; else echo \"0 100 AC\"; fi"]
stdout: StdioCollector {
onDataChanged: {
const parts = data.trim().split(" ");
if (parts.length >= 3) {
root.batteryPresent = parts[0] === "1";
root.batteryPercent = parseInt(parts[1]) || 100;
root.batteryStatus = parts[2];
root.batteryCharging = parts[2] === "Charging" || parts[2] === "Full";
}
}
}
}
readonly property Process wifiProc: Process {
command: ["bash", "-c", "ssid=\"\"; if command -v nmcli &>/dev/null; then ssid=$(nmcli -t -f active,ssid dev wifi 2>/dev/null | grep '^yes:' | cut -d':' -f2); fi; [ -z \"$ssid\" ] && [ -f /proc/net/wireless ] && ssid=$(iwgetid -r 2>/dev/null); ip=$(ip -4 route get 1.1.1.1 2>/dev/null | awk '{print $7; exit}'); echo \"${ssid:-Ethernet} ${ip:-Offline}\""]
stdout: StdioCollector {
onDataChanged: {
const str = data.trim();
const parts = str.split(" ");
if (parts.length >= 2) {
root.wifiSsid = parts[0];
root.ipAddress = parts[1];
root.wifiConnected = parts[1] !== "Offline";
}
}
}
}
readonly property Process audioProc: Process {
command: ["bash", "-c", "if command -v pactl &>/dev/null; then v=$(pactl get-sink-volume @DEFAULT_SINK@ 2>/dev/null | grep -Po '[0-9]+(?=%)' | head -n 1); m=$(pactl get-sink-mute @DEFAULT_SINK@ 2>/dev/null | grep -q yes && echo 1 || echo 0); echo \"${v:-50} $m\"; fi"]
stdout: StdioCollector {
onDataChanged: {
const parts = data.trim().split(" ");
if (parts.length >= 2) {
root.volume = parseInt(parts[0]) || 50;
root.volumeMuted = parts[1] === "1";
}
}
}
}
readonly property Process brightProc: Process {
command: ["bash", "-c", "if command -v brightnessctl &>/dev/null; then b=$(brightnessctl -m 2>/dev/null | cut -d, -f4 | tr -d '%'); echo \"${b:-100}\"; else echo 100; fi"]
stdout: StdioCollector {
onDataChanged: {
const val = parseInt(data.trim());
if (!isNaN(val)) root.brightness = val;
}
}
}
readonly property Process mprisProc: Process {
command: ["bash", "-c", "if command -v playerctl &>/dev/null; then t=$(playerctl metadata title 2>/dev/null); a=$(playerctl metadata artist 2>/dev/null); s=$(playerctl status 2>/dev/null); echo \"$s|$t|$a\"; fi"]
stdout: StdioCollector {
onDataChanged: {
const parts = data.trim().split("|");
if (parts.length >= 3) {
root.mediaPlaying = parts[0] === "Playing";
root.mediaTitle = parts[1] || "";
root.mediaArtist = parts[2] || "";
} else {
root.mediaPlaying = false;
root.mediaTitle = "";
root.mediaArtist = "";
}
}
}
}
readonly property Process clientsProc: Process {
command: ["bash", "-c", "if command -v hyprctl &>/dev/null; then hyprctl -j clients 2>/dev/null; else echo '[]'; fi"]
stdout: StdioCollector {
onDataChanged: {
try {
const parsed = JSON.parse(data.trim());
if (Array.isArray(parsed)) {
root.runningApps = parsed;
}
} catch(e) {}
}
}
}
// Helper functions to control system
function setVolume(val) {
root.volume = Math.max(0, Math.min(100, val));
Process.exec(["pactl", "set-sink-volume", "@DEFAULT_SINK@", `${root.volume}%`]);
}
function toggleVolumeMute() {
Process.exec(["pactl", "set-sink-mute", "@DEFAULT_SINK@", "toggle"]);
root.volumeMuted = !root.volumeMuted;
}
function setBrightness(val) {
root.brightness = Math.max(1, Math.min(100, val));
Process.exec(["brightnessctl", "set", `${root.brightness}%`]);
}
function mediaPlayPause() {
Process.exec(["playerctl", "play-pause"]);
mprisProc.running = true;
}
function mediaNext() {
Process.exec(["playerctl", "next"]);
mprisProc.running = true;
}
function mediaPrevious() {
Process.exec(["playerctl", "previous"]);
mprisProc.running = true;
}
function launchApp(execCmd) {
if (!execCmd) return;
Process.exec(["bash", "-c", `${execCmd} &`]);
closeAllPopups();
spotlightVisible = false;
}
}

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 170 170" width="100%" height="100%">
<path fill="#ffffff" d="M150.37 130.25c-2.45 5.66-5.35 10.87-8.71 15.66-4.58 6.53-8.33 11.05-11.22 13.56-4.48 4.12-9.28 6.23-14.42 6.35-3.69 0-8.14-1.05-13.32-3.18-5.19-2.12-9.97-3.17-14.34-3.17-4.58 0-9.49 1.05-14.75 3.17-5.26 2.13-9.5 3.24-12.74 3.35-4.35.13-9.16-1.9-14.42-6.08-3.7-3.04-7.69-7.75-11.96-14.12-6.53-9.78-11.75-21.2-15.66-34.25-3.9-13.06-5.86-25.2-5.86-36.42 0-14.35 3.69-26.4 11.08-36.17 7.39-9.78 16.74-14.77 28.05-14.99 4.35 0 9.49 1.25 15.42 3.75 5.94 2.5 9.78 3.75 11.53 3.75 1.52 0 5.58-1.29 12.18-3.87 6.6-2.58 11.89-3.75 15.88-3.52 11.52.44 20.98 4.7 28.38 12.79-10.43 6.31-15.54 15.11-15.33 26.41.22 8.91 3.69 16.52 10.42 22.82 6.74 6.31 14.78 9.9 24.13 10.77-2.17 6.74-4.89 13.7-8.15 20.87zM119.22 31.02c0-7.18 2.61-13.8 7.83-19.89 5.22-6.09 11.63-9.9 19.24-11.43.22 1.3.33 2.5.33 3.59 0 7.18-2.72 13.92-8.15 20.22-5.43 6.31-12.06 10.01-19.25 11.1-.33-1.09-.5-2.29-.5-3.59z"/>
</svg>

After

Width:  |  Height:  |  Size: 1003 B

View File

@@ -0,0 +1,20 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="100%" height="100%">
<defs>
<linearGradient id="appStoreBg" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#2DA9FF"/>
<stop offset="100%" stop-color="#0062E3"/>
</linearGradient>
<filter id="shadowAppStore" x="-10%" y="-10%" width="120%" height="120%">
<feDropShadow dx="0" dy="4" stdDeviation="4" flood-color="#000000" flood-opacity="0.35"/>
</filter>
</defs>
<rect x="10" y="10" width="108" height="108" rx="24" fill="url(#appStoreBg)" filter="url(#shadowAppStore)" stroke="#4BB4FF" stroke-width="1.5"/>
<!-- Apple App Store stylized 'A' using bars -->
<!-- Left Leg (Pencil/Ruler) -->
<line x1="38" y1="94" x2="64" y2="34" stroke="#FFFFFF" stroke-width="9" stroke-linecap="round"/>
<!-- Right Leg (Brush) -->
<line x1="90" y1="94" x2="64" y2="34" stroke="#FFFFFF" stroke-width="9" stroke-linecap="round"/>
<!-- Crossbar -->
<line x1="30" y1="74" x2="98" y2="74" stroke="#FFFFFF" stroke-width="9" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 16" width="100%" height="100%">
<!-- Outer shell -->
<rect x="1" y="1" width="22" height="14" rx="3.5" fill="none" stroke="#FFFFFF" stroke-width="1.8"/>
<!-- Anode terminal -->
<path d="M25 5.5 C25.8 5.5 26.5 6.2 26.5 7 V9 C26.5 9.8 25.8 10.5 25 10.5 Z" fill="#FFFFFF"/>
<!-- Fill bar inside -->
<rect x="3.5" y="3.5" width="15" height="9" rx="2" fill="#FFFFFF"/>
</svg>

After

Width:  |  Height:  |  Size: 439 B

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%">
<path fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M7 7l10 10-5 5V2l5 5L7 17"/>
</svg>

After

Width:  |  Height:  |  Size: 228 B

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%">
<circle cx="12" cy="12" r="5" fill="#FFFFFF"/>
<path stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" d="M12 1v2 M12 21v2 M4.22 4.22l1.42 1.42 M18.36 18.36l1.42 1.42 M1 12h2 M21 12h2 M4.22 19.78l1.42-1.42 M18.36 5.64l1.42-1.42"/>
</svg>

After

Width:  |  Height:  |  Size: 337 B

View File

@@ -0,0 +1,26 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="100%" height="100%">
<defs>
<linearGradient id="safBg" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#EBF4FB"/>
<stop offset="100%" stop-color="#C2D8EB"/>
</linearGradient>
<linearGradient id="safCompass" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#00C7FF"/>
<stop offset="100%" stop-color="#0062E3"/>
</linearGradient>
<filter id="shadowSaf" x="-10%" y="-10%" width="120%" height="120%">
<feDropShadow dx="0" dy="4" stdDeviation="4" flood-color="#000000" flood-opacity="0.35"/>
</filter>
</defs>
<rect x="10" y="10" width="108" height="108" rx="24" fill="url(#safBg)" filter="url(#shadowSaf)" stroke="#B0C4DE" stroke-width="1.5"/>
<circle cx="64" cy="64" r="44" fill="url(#safCompass)" stroke="#FFFFFF" stroke-width="2"/>
<!-- Dial ticks -->
<circle cx="64" cy="64" r="38" fill="none" stroke="#FFFFFF" stroke-width="1" stroke-dasharray="2 6" opacity="0.6"/>
<!-- Compass Needle Red/North -->
<polygon points="64,28 72,64 64,61 56,64" fill="#FF3B30"/>
<!-- Compass Needle White/South -->
<polygon points="64,100 72,64 64,67 56,64" fill="#FFFFFF"/>
<circle cx="64" cy="64" r="4" fill="#FFFFFF" stroke="#D0D0D0" stroke-width="1"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,40 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160" width="100%" height="100%">
<defs>
<clipPath id="circleClip">
<circle cx="80" cy="80" r="72"/>
</clipPath>
<linearGradient id="skyGrad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#1A385C"/>
<stop offset="50%" stop-color="#C27A59"/>
<stop offset="100%" stop-color="#FFD6A5"/>
</linearGradient>
<linearGradient id="seaGrad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#1E4566"/>
<stop offset="100%" stop-color="#0E2338"/>
</linearGradient>
<linearGradient id="islandGrad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#544943"/>
<stop offset="100%" stop-color="#241E1C"/>
</linearGradient>
<filter id="badgeShadow">
<feDropShadow dx="0" dy="6" stdDeviation="6" flood-color="#000000" flood-opacity="0.4"/>
</filter>
</defs>
<circle cx="80" cy="80" r="74" fill="none" stroke="#FFFFFF" stroke-width="3" filter="url(#badgeShadow)"/>
<g clip-path="url(#circleClip)">
<!-- Sky -->
<rect x="0" y="0" width="160" height="160" fill="url(#skyGrad)"/>
<!-- Sun glow -->
<circle cx="95" cy="80" r="28" fill="#FFF2DE" opacity="0.6"/>
<!-- Distant Mountains -->
<polygon points="10,105 50,75 90,105" fill="#755E57" opacity="0.7"/>
<polygon points="70,105 115,70 155,105" fill="#5E4843" opacity="0.8"/>
<!-- Santa Catalina Island Cliffs -->
<path d="M0 110 Q40 85 85 102 Q125 75 160 115 L160 160 L0 160 Z" fill="url(#islandGrad)"/>
<!-- Ocean / Waves -->
<path d="M0 120 C30 115 60 125 100 118 C130 112 150 122 160 120 L160 160 L0 160 Z" fill="url(#seaGrad)"/>
<path d="M0 135 C40 130 80 140 120 132 C140 128 155 134 160 135 L160 160 L0 160 Z" fill="#132B45" opacity="0.6"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,23 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="100%" height="100%">
<defs>
<linearGradient id="codeBg" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#1E293B"/>
<stop offset="100%" stop-color="#0F172A"/>
</linearGradient>
<linearGradient id="codeBrackets" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#38BDF8"/>
<stop offset="100%" stop-color="#818CF8"/>
</linearGradient>
<filter id="shadowCode" x="-10%" y="-10%" width="120%" height="120%">
<feDropShadow dx="0" dy="4" stdDeviation="4" flood-color="#000000" flood-opacity="0.35"/>
</filter>
</defs>
<rect x="10" y="10" width="108" height="108" rx="24" fill="url(#codeBg)" filter="url(#shadowCode)" stroke="#334155" stroke-width="1.5"/>
<!-- Left Bracket < -->
<path d="M46 42 L26 64 L46 86" fill="none" stroke="url(#codeBrackets)" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<!-- Right Bracket > -->
<path d="M82 42 L102 64 L82 86" fill="none" stroke="url(#codeBrackets)" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<!-- Slash / -->
<line x1="70" y1="36" x2="58" y2="92" stroke="#F43F5E" stroke-width="7" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%">
<!-- Top switch -->
<rect x="3" y="5" width="18" height="6" rx="3" fill="none" stroke="#FFFFFF" stroke-width="1.8"/>
<circle cx="16" cy="8" r="2.2" fill="#FFFFFF"/>
<!-- Bottom switch -->
<rect x="3" y="13" width="18" height="6" rx="3" fill="none" stroke="#FFFFFF" stroke-width="1.8"/>
<circle cx="8" cy="16" r="2.2" fill="#FFFFFF"/>
</svg>

After

Width:  |  Height:  |  Size: 441 B

View File

@@ -0,0 +1,37 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="100%" height="100%">
<defs>
<linearGradient id="finderBg" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#E8E8E8"/>
<stop offset="100%" stop-color="#B0B0B0"/>
</linearGradient>
<linearGradient id="faceBlue" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#47A3F3"/>
<stop offset="100%" stop-color="#1D72DB"/>
</linearGradient>
<linearGradient id="faceLightBlue" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#9AD7F8"/>
<stop offset="100%" stop-color="#56AEF7"/>
</linearGradient>
<filter id="shadow" x="-10%" y="-10%" width="120%" height="120%">
<feDropShadow dx="0" dy="4" stdDeviation="4" flood-color="#000000" flood-opacity="0.35"/>
</filter>
</defs>
<rect x="10" y="10" width="108" height="108" rx="24" fill="url(#finderBg)" filter="url(#shadow)" stroke="#A0A0A0" stroke-width="1.5"/>
<!-- Right half of face (Darker Blue) -->
<path d="M64 12 H94 C107.25 12 116 20.75 116 34 V94 C116 107.25 107.25 116 94 116 H64 Z" fill="url(#faceBlue)"/>
<!-- Left half of face (Lighter Blue) -->
<path d="M34 12 H64 V116 H34 C20.75 116 12 107.25 12 94 V34 C12 20.75 20.75 12 34 12 Z" fill="url(#faceLightBlue)"/>
<!-- Eyes -->
<ellipse cx="40" cy="52" rx="5" ry="9" fill="#1C2D42"/>
<ellipse cx="88" cy="52" rx="5" ry="9" fill="#1C2D42"/>
<!-- Nose (macOS Finder split curve) -->
<path d="M64 34 C64 34 65 62 61 68 C58 72 52 74 48 75" fill="none" stroke="#1C2D42" stroke-width="4.5" stroke-linecap="round"/>
<!-- Smile -->
<path d="M30 80 C36 102 92 102 98 80" fill="none" stroke="#1C2D42" stroke-width="5" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1,25 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="100%" height="100%">
<defs>
<linearGradient id="folderBack" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#4CA1F5"/>
<stop offset="100%" stop-color="#1B6DC7"/>
</linearGradient>
<linearGradient id="folderFront" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#80C8FC"/>
<stop offset="100%" stop-color="#3894EE"/>
</linearGradient>
<filter id="shadowFolder" x="-10%" y="-10%" width="120%" height="120%">
<feDropShadow dx="0" dy="4" stdDeviation="4" flood-color="#000000" flood-opacity="0.35"/>
</filter>
</defs>
<!-- Folder Back Tab -->
<path d="M16 28 C16 24 20 20 24 20 H50 L60 30 H104 C108 30 112 34 112 38 V96 C112 100 108 104 104 104 H24 C20 104 16 100 16 96 Z" fill="url(#folderBack)" filter="url(#shadowFolder)"/>
<!-- Folder Front Pocket -->
<path d="M12 44 C12 40 16 36 20 36 H108 C112 36 116 40 116 44 V98 C116 104 110 108 104 108 H24 C18 108 12 104 12 98 Z" fill="url(#folderFront)"/>
<!-- Download Downward Arrow Badge -->
<circle cx="64" cy="74" r="18" fill="#FFFFFF" opacity="0.9"/>
<path d="M64 62 V82 M54 74 L64 84 L74 74" fill="none" stroke="#1B6DC7" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,35 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="100%" height="100%">
<defs>
<linearGradient id="lpBg" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#485563"/>
<stop offset="100%" stop-color="#29323c"/>
</linearGradient>
<linearGradient id="rocketGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#FFFFFF"/>
<stop offset="100%" stop-color="#D0D4DC"/>
</linearGradient>
<linearGradient id="fireGrad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#FFCC00"/>
<stop offset="100%" stop-color="#FF3B30"/>
</linearGradient>
<filter id="shadowLp" x="-10%" y="-10%" width="120%" height="120%">
<feDropShadow dx="0" dy="4" stdDeviation="4" flood-color="#000000" flood-opacity="0.35"/>
</filter>
</defs>
<rect x="10" y="10" width="108" height="108" rx="24" fill="url(#lpBg)" filter="url(#shadowLp)" stroke="#5A6675" stroke-width="1.5"/>
<!-- Rocket Body -->
<path d="M88 28 C74 34 52 50 44 68 C40 76 40 84 42 88 C46 90 54 90 62 86 C80 78 96 56 102 42 C104 36 102 30 96 28 C93 27 90 27 88 28 Z" fill="url(#rocketGrad)"/>
<!-- Rocket Window -->
<circle cx="74" cy="54" r="7" fill="#0A84FF" stroke="#FFFFFF" stroke-width="2"/>
<!-- Rocket Wing Left -->
<path d="M48 76 C40 76 30 84 26 92 C34 94 44 90 48 84 Z" fill="#E02438"/>
<!-- Rocket Wing Right -->
<path d="M76 48 C76 40 84 30 92 26 C94 34 90 44 84 48 Z" fill="#E02438"/>
<!-- Fire Exhaust -->
<path d="M42 88 C36 94 32 104 34 108 C38 106 48 102 54 96 Z" fill="url(#fireGrad)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="100%" height="100%">
<defs>
<linearGradient id="musicBg" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#FF385C"/>
<stop offset="100%" stop-color="#E00034"/>
</linearGradient>
<filter id="shadowMusic" x="-10%" y="-10%" width="120%" height="120%">
<feDropShadow dx="0" dy="4" stdDeviation="4" flood-color="#000000" flood-opacity="0.35"/>
</filter>
</defs>
<rect x="10" y="10" width="108" height="108" rx="24" fill="url(#musicBg)" filter="url(#shadowMusic)" stroke="#FF6B8B" stroke-width="1.5"/>
<!-- Musical Eighth Notes -->
<!-- Stems and Beam -->
<path d="M48 76 V38 C48 34 50 32 54 32 H82 C86 32 88 34 88 38 V70" fill="none" stroke="#FFFFFF" stroke-width="6" stroke-linecap="round"/>
<!-- Beams -->
<polygon points="48,32 88,32 88,44 48,44" fill="#FFFFFF"/>
<!-- Note Heads -->
<ellipse cx="40" cy="80" rx="12" ry="8" transform="rotate(-20 40 80)" fill="#FFFFFF"/>
<ellipse cx="80" cy="74" rx="12" ry="8" transform="rotate(-20 80 74)" fill="#FFFFFF"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,44 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="100%" height="100%">
<defs>
<linearGradient id="prefBg" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#D8DBE2"/>
<stop offset="100%" stop-color="#8F96A3"/>
</linearGradient>
<linearGradient id="gearBig" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#7C8494"/>
<stop offset="100%" stop-color="#4A5260"/>
</linearGradient>
<linearGradient id="gearSmall" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#9CA3AF"/>
<stop offset="100%" stop-color="#5B6270"/>
</linearGradient>
<filter id="shadowPref" x="-10%" y="-10%" width="120%" height="120%">
<feDropShadow dx="0" dy="4" stdDeviation="4" flood-color="#000000" flood-opacity="0.35"/>
</filter>
</defs>
<rect x="10" y="10" width="108" height="108" rx="24" fill="url(#prefBg)" filter="url(#shadowPref)" stroke="#B0B6C2" stroke-width="1.5"/>
<!-- Big Gear -->
<g transform="translate(50, 50)">
<circle cx="0" cy="0" r="28" fill="url(#gearBig)"/>
<!-- Teeth -->
<path d="M-6 -34 H6 V-26 H-6 Z M-6 26 H6 V34 H-6 Z M-34 -6 V6 H-26 V-6 Z M26 -6 V6 H34 V-6 Z" fill="url(#gearBig)"/>
<path d="M-6 -34 H6 V-26 H-6 Z" transform="rotate(45)" fill="url(#gearBig)"/>
<path d="M-6 -34 H6 V-26 H-6 Z" transform="rotate(135)" fill="url(#gearBig)"/>
<path d="M-6 -34 H6 V-26 H-6 Z" transform="rotate(225)" fill="url(#gearBig)"/>
<path d="M-6 -34 H6 V-26 H-6 Z" transform="rotate(315)" fill="url(#gearBig)"/>
<circle cx="0" cy="0" r="12" fill="url(#prefBg)" stroke="#3A404D" stroke-width="1.5"/>
</g>
<!-- Small Gear -->
<g transform="translate(86, 86)">
<circle cx="0" cy="0" r="18" fill="url(#gearSmall)"/>
<!-- Teeth -->
<path d="M-4 -22 H4 V-16 H-4 Z M-4 16 H4 V22 H-4 Z M-22 -4 V4 H-16 V-4 Z M16 -4 V4 H22 V-4 Z" fill="url(#gearSmall)"/>
<path d="M-4 -22 H4 V-16 H-4 Z" transform="rotate(45)" fill="url(#gearSmall)"/>
<path d="M-4 -22 H4 V-16 H-4 Z" transform="rotate(135)" fill="url(#gearSmall)"/>
<path d="M-4 -22 H4 V-16 H-4 Z" transform="rotate(225)" fill="url(#gearSmall)"/>
<path d="M-4 -22 H4 V-16 H-4 Z" transform="rotate(315)" fill="url(#gearSmall)"/>
<circle cx="0" cy="0" r="8" fill="url(#prefBg)" stroke="#3A404D" stroke-width="1.5"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%">
<path fill="none" stroke="#FFFFFF" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" d="M10.5 18a7.5 7.5 0 1 1 0-15 7.5 7.5 0 0 1 0 15z M16 16l5 5"/>
</svg>

After

Width:  |  Height:  |  Size: 263 B

View File

@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="100%" height="100%">
<defs>
<linearGradient id="termBg" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#2D2D30"/>
<stop offset="100%" stop-color="#141416"/>
</linearGradient>
<filter id="shadowTerm" x="-10%" y="-10%" width="120%" height="120%">
<feDropShadow dx="0" dy="4" stdDeviation="4" flood-color="#000000" flood-opacity="0.35"/>
</filter>
</defs>
<rect x="10" y="10" width="108" height="108" rx="24" fill="url(#termBg)" filter="url(#shadowTerm)" stroke="#4A4A50" stroke-width="1.5"/>
<rect x="18" y="24" width="92" height="80" rx="10" fill="#0C0C0E" stroke="#2A2A2E" stroke-width="1"/>
<!-- macOS Terminal header dots -->
<circle cx="28" cy="32" r="3" fill="#FF5F56"/>
<circle cx="36" cy="32" r="3" fill="#FFBD2E"/>
<circle cx="44" cy="32" r="3" fill="#27C93F"/>
<!-- Terminal Prompt >_ -->
<path d="M28 54 L44 64 L28 74" fill="none" stroke="#30D158" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<line x1="50" y1="74" x2="68" y2="74" stroke="#FFFFFF" stroke-width="4" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,23 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="100%" height="100%">
<defs>
<linearGradient id="trashCan" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#E2E8F0"/>
<stop offset="100%" stop-color="#94A3B8"/>
</linearGradient>
<filter id="shadowTrash" x="-10%" y="-10%" width="120%" height="120%">
<feDropShadow dx="0" dy="4" stdDeviation="4" flood-color="#000000" flood-opacity="0.35"/>
</filter>
</defs>
<!-- Lid -->
<ellipse cx="64" cy="30" rx="36" ry="8" fill="#CBD5E1" stroke="#94A3B8" stroke-width="2"/>
<rect x="56" y="18" width="16" height="8" rx="4" fill="#94A3B8"/>
<!-- Can Body -->
<path d="M30 30 L40 106 C41 112 48 116 64 116 C80 116 87 112 88 106 L98 30 Z" fill="url(#trashCan)" stroke="#64748B" stroke-width="2"/>
<!-- Ribs / Vertical Mesh Lines -->
<line x1="48" y1="36" x2="52" y2="108" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" opacity="0.6"/>
<line x1="64" y1="36" x2="64" y2="110" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" opacity="0.6"/>
<line x1="80" y1="36" x2="76" y2="108" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" opacity="0.6"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,24 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="100%" height="100%">
<defs>
<linearGradient id="trashCanFull" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#E2E8F0"/>
<stop offset="100%" stop-color="#94A3B8"/>
</linearGradient>
<filter id="shadowTrashFull" x="-10%" y="-10%" width="120%" height="120%">
<feDropShadow dx="0" dy="4" stdDeviation="4" flood-color="#000000" flood-opacity="0.35"/>
</filter>
</defs>
<!-- Crumpled paper overflowing -->
<path d="M42 28 C38 18 52 14 60 20 C68 12 82 16 80 26 C88 24 92 34 84 38 C74 42 54 42 42 28 Z" fill="#F8FAFC" stroke="#CBD5E1" stroke-width="1.5"/>
<path d="M48 24 L56 16 L64 24 Z" fill="#E2E8F0"/>
<path d="M68 20 L76 14 L82 22 Z" fill="#E2E8F0"/>
<!-- Can Body -->
<path d="M30 36 L40 106 C41 112 48 116 64 116 C80 116 87 112 88 106 L98 36 Z" fill="url(#trashCanFull)" stroke="#64748B" stroke-width="2"/>
<!-- Ribs / Vertical Mesh Lines -->
<line x1="48" y1="42" x2="52" y2="108" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" opacity="0.6"/>
<line x1="64" y1="42" x2="64" y2="110" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" opacity="0.6"/>
<line x1="80" y1="42" x2="76" y2="108" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" opacity="0.6"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%">
<path fill="#FFFFFF" d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/>
</svg>

After

Width:  |  Height:  |  Size: 312 B

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="100%" height="100%">
<path fill="#FFFFFF" d="M12 18.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3z M4.93 12.93a10 10 0 0 1 14.14 0 1 1 0 0 0 1.42-1.42 12 12 0 0 0-16.98 0 1 1 0 0 0 1.42 1.42z M8.46 16.46a5 5 0 0 1 7.08 0 1 1 0 0 0 1.41-1.41 7 7 0 0 0-9.9 0 1 1 0 0 0 1.41 1.41z"/>
</svg>

After

Width:  |  Height:  |  Size: 349 B

View File

@@ -0,0 +1,260 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import "../theme"
import ".."
PanelWindow {
id: aboutWindow
visible: GlobalState.aboutMacVisible
anchors {
top: true
left: true
right: true
bottom: true
}
color: Qt.rgba(0, 0, 0, 0.35)
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.namespace: "quickshell-aboutmac"
WlrLayershell.keyboardFocus: visible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
// Dismiss when clicking outside modal
MouseArea {
anchors.fill: parent
onClicked: GlobalState.aboutMacVisible = false
}
// Centered Dialog
Rectangle {
id: dialogBox
anchors.centerIn: parent
width: 540
height: 330
radius: Theme.radiusModal
color: Theme.windowBg
border.color: Theme.windowBorder
border.width: 1
// Prevent clicking inside from dismissing
MouseArea {
anchors.fill: parent
onClicked: {}
}
ColumnLayout {
anchors.fill: parent
anchors.margins: 16
spacing: 12
// Top Traffic Lights Bar
RowLayout {
Layout.fillWidth: true
spacing: 8
// Red Close Dot
Rectangle {
width: 12
height: 12
radius: 6
color: closeMouse.containsMouse ? "#E0443E" : "#FF5F56"
border.color: "#E0443E"
border.width: 0.5
Text {
anchors.centerIn: parent
visible: closeMouse.containsMouse
text: "×"
font.pixelSize: 10
color: "#4A0002"
}
MouseArea {
id: closeMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: GlobalState.aboutMacVisible = false
}
}
// Yellow Minimize Dot
Rectangle {
width: 12
height: 12
radius: 6
color: "#FFBD2E"
border.color: "#DEA123"
border.width: 0.5
}
// Green Zoom Dot
Rectangle {
width: 12
height: 12
radius: 6
color: "#27C93F"
border.color: "#1AAB29"
border.width: 0.5
}
Item { Layout.fillWidth: true }
Text {
text: "Overview"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
color: Theme.textSecondary
}
Item { Layout.fillWidth: true }
}
// Main Specs Content
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 24
// Left: Catalina Island Badge
Image {
Layout.alignment: Qt.AlignVCenter
width: 130
height: 130
source: "../assets/catalina-badge.svg"
sourceSize: Qt.size(130, 130)
}
// Right: System Details
ColumnLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
spacing: 6
Text {
text: "macOS Catalina"
font.family: Theme.fontFamily
font.pixelSize: 22
font.weight: Font.Bold
color: "#FFFFFF"
}
Text {
text: "Version 10.15.7 (NixOS Edition)"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
// Specs Rows
SpecRow { label: "Host"; value: "Hades (AMD + NVIDIA RTX)" }
SpecRow { label: "Processor"; value: "AMD High-Performance Multi-Core" }
SpecRow { label: "Memory"; value: `${GlobalState.memTotalGb} GB RAM (${GlobalState.memUsedGb} GB in use)` }
SpecRow { label: "Graphics"; value: "NVIDIA GeForce RTX (Proprietary Driver)" }
SpecRow { label: "Compositor"; value: "Hyprland 0.55+ (Wayland)" }
SpecRow { label: "Operating System"; value: "NixOS 26.05 (x86_64-linux)" }
}
}
// Bottom Action Buttons
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignRight
spacing: 12
Rectangle {
implicitWidth: sysRepText.implicitWidth + 20
height: 24
radius: Theme.radiusSmall
color: repMouse.containsMouse ? Qt.rgba(1,1,1,0.2) : Qt.rgba(1,1,1,0.1)
border.color: Qt.rgba(1,1,1,0.15)
border.width: 1
Text {
id: sysRepText
anchors.centerIn: parent
text: "System Report..."
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
MouseArea {
id: repMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
GlobalState.aboutMacVisible = false;
GlobalState.launchApp("foot -e btop");
}
}
}
Rectangle {
implicitWidth: updText.implicitWidth + 20
height: 24
radius: Theme.radiusSmall
color: updMouse.containsMouse ? Qt.rgba(1,1,1,0.2) : Qt.rgba(1,1,1,0.1)
border.color: Qt.rgba(1,1,1,0.15)
border.width: 1
Text {
id: updText
anchors.centerIn: parent
text: "Software Update..."
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
MouseArea {
id: updMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
GlobalState.aboutMacVisible = false;
GlobalState.launchApp("foot -e zsh -c 'echo \"Checking NixOS system configuration...\"; sudo nixos-rebuild dry-activate --flake /home/anish/NixOS-Configs#hades; exec zsh'");
}
}
}
}
}
}
component SpecRow: RowLayout {
property string label: ""
property string value: ""
Layout.fillWidth: true
spacing: 10
Text {
text: label
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
color: Theme.textSecondary
Layout.preferredWidth: 105
}
Text {
text: value
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
Layout.fillWidth: true
elide: Text.ElideRight
}
}
}

View File

@@ -0,0 +1,147 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../theme"
import ".."
Rectangle {
id: root
property string menuName: ""
width: 200
implicitHeight: menuCol.implicitHeight + 12
radius: Theme.radiusMedium
color: Theme.menuDropdownBg
border.color: Theme.menuDropdownBorder
border.width: 1
ColumnLayout {
id: menuCol
anchors.fill: parent
anchors.margins: 6
spacing: 2
// FILE MENU
Repeater {
model: root.menuName === "File" ? [
{ text: "New Window", shortcut: "⌘N", cmd: "foot &" },
{ text: "New Incognito Window", shortcut: "⇧⌘N", cmd: "brave --incognito &" },
{ text: "Close Window", shortcut: "⌘W", cmd: "hyprctl dispatch killactive" },
{ text: "---", shortcut: "", cmd: "" },
{ text: "Take Screenshot", shortcut: "⇧⌘5", cmd: "grim -g \"$(slurp)\" ~/screenshot.png" }
] : []
delegate: MenuEntryDelegate {}
}
// EDIT MENU
Repeater {
model: root.menuName === "Edit" ? [
{ text: "Undo", shortcut: "⌘Z", cmd: "" },
{ text: "Redo", shortcut: "⇧⌘Z", cmd: "" },
{ text: "---", shortcut: "", cmd: "" },
{ text: "Cut", shortcut: "⌘X", cmd: "wl-copy" },
{ text: "Copy", shortcut: "⌘C", cmd: "wl-copy" },
{ text: "Paste", shortcut: "⌘V", cmd: "wl-paste" },
{ text: "Select All", shortcut: "⌘A", cmd: "" }
] : []
delegate: MenuEntryDelegate {}
}
// VIEW MENU
Repeater {
model: root.menuName === "View" ? [
{ text: "Toggle Fullscreen", shortcut: "⌃⌘F", cmd: "hyprctl dispatch fullscreen 0" },
{ text: "Toggle Floating", shortcut: "⌘V", cmd: "hyprctl dispatch togglefloating" },
{ text: "Toggle Group", shortcut: "⌘G", cmd: "hyprctl dispatch togglegroup" },
{ text: "---", shortcut: "", cmd: "" },
{ text: "Zoom In", shortcut: "⌘+", cmd: "" },
{ text: "Zoom Out", shortcut: "⌘-", cmd: "" }
] : []
delegate: MenuEntryDelegate {}
}
// WINDOW MENU
Repeater {
model: root.menuName === "Window" ? [
{ text: "Minimize Window", shortcut: "⌘M", cmd: "hyprctl dispatch movetoworkspacesilent special:scratch" },
{ text: "Tile Left", shortcut: "⌃⌥←", cmd: "hyprctl dispatch movewindow l" },
{ text: "Tile Right", shortcut: "⌃⌥→", cmd: "hyprctl dispatch movewindow r" },
{ text: "---", shortcut: "", cmd: "" },
{ text: "Show Scratchpad", shortcut: "⌘↩", cmd: "hyprctl dispatch togglespecialworkspace scratch" },
{ text: "Show Messaging", shortcut: "⌘M", cmd: "hyprctl dispatch togglespecialworkspace messaging" }
] : []
delegate: MenuEntryDelegate {}
}
// HELP MENU
Repeater {
model: root.menuName === "Help" ? [
{ text: "Hyprland Documentation", shortcut: "", cmd: "brave https://wiki.hyprland.org &" },
{ text: "NixOS Manual", shortcut: "", cmd: "brave https://nixos.org/manual/nixos/stable/ &" },
{ text: "---", shortcut: "", cmd: "" },
{ text: "About Antigravity", shortcut: "", cmd: "" }
] : []
delegate: MenuEntryDelegate {}
}
}
component MenuEntryDelegate: Item {
Layout.fillWidth: true
Layout.preferredHeight: modelData.text === "---" ? 7 : 22
Rectangle {
anchors.fill: parent
visible: modelData.text === "---"
color: "transparent"
Rectangle {
anchors.centerIn: parent
width: parent.width
height: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
}
Rectangle {
anchors.fill: parent
visible: modelData.text !== "---"
radius: Theme.radiusSmall
color: itemMouse.containsMouse ? Theme.menuHoverBlue : "transparent"
RowLayout {
anchors.fill: parent
anchors.leftMargin: 10
anchors.rightMargin: 10
spacing: 8
Text {
text: modelData.text
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
color: itemMouse.containsMouse ? Theme.menuTextHover : Theme.textPrimary
Layout.fillWidth: true
elide: Text.ElideRight
}
Text {
visible: modelData.shortcut !== ""
text: modelData.shortcut
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: itemMouse.containsMouse ? Theme.menuTextHover : Theme.textTertiary
}
}
MouseArea {
id: itemMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
GlobalState.activeDropdownMenu = "";
if (modelData.cmd) {
GlobalState.launchApp(modelData.cmd);
}
}
}
}
}
}

View File

@@ -0,0 +1,158 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../theme"
import ".."
Rectangle {
id: root
width: 220
implicitHeight: menuColumn.implicitHeight + 12
radius: Theme.radiusMedium
color: Theme.menuDropdownBg
border.color: Theme.menuDropdownBorder
border.width: 1
// Drop shadow
layer.enabled: true
ColumnLayout {
id: menuColumn
anchors.fill: parent
anchors.margins: 6
spacing: 2
// About This Mac
MenuItem {
text: "About This Mac"
onTriggered: {
GlobalState.appleMenuVisible = false;
GlobalState.toggleAboutMac();
}
}
MenuSeparator {}
MenuItem {
text: "System Preferences..."
onTriggered: {
GlobalState.launchApp("pavucontrol");
}
}
MenuItem {
text: "App Store..."
onTriggered: {
GlobalState.launchApp("foot -e zsh -c 'echo NixOS Packages; nix-env -qaP | head -n 50; exec zsh'");
}
}
MenuSeparator {}
MenuItem {
text: "Activity Monitor"
shortcut: "⌥⌘Esc"
onTriggered: {
GlobalState.launchApp("foot -e btop");
}
}
MenuSeparator {}
MenuItem {
text: "Sleep"
onTriggered: {
GlobalState.appleMenuVisible = false;
GlobalState.launchApp("systemctl suspend");
}
}
MenuItem {
text: "Restart..."
onTriggered: {
GlobalState.appleMenuVisible = false;
GlobalState.launchApp("systemctl reboot");
}
}
MenuItem {
text: "Shut Down..."
onTriggered: {
GlobalState.appleMenuVisible = false;
GlobalState.launchApp("systemctl poweroff");
}
}
MenuSeparator {}
MenuItem {
text: "Lock Screen"
shortcut: "⌃⌘Q"
onTriggered: {
GlobalState.appleMenuVisible = false;
GlobalState.launchApp("hyprlock");
}
}
MenuItem {
text: "Log Out anish..."
shortcut: "⇧⌘Q"
onTriggered: {
GlobalState.appleMenuVisible = false;
GlobalState.launchApp("hyprctl dispatch exit");
}
}
}
component MenuItem: Rectangle {
id: itemRoot
property string text: ""
property string shortcut: ""
signal triggered()
Layout.fillWidth: true
Layout.preferredHeight: 22
radius: Theme.radiusSmall
color: mouseArea.containsMouse ? Theme.menuHoverBlue : "transparent"
RowLayout {
anchors.fill: parent
anchors.leftMargin: 10
anchors.rightMargin: 10
spacing: 8
Text {
text: itemRoot.text
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
color: mouseArea.containsMouse ? Theme.menuTextHover : Theme.textPrimary
Layout.fillWidth: true
elide: Text.ElideRight
}
Text {
visible: itemRoot.shortcut !== ""
text: itemRoot.shortcut
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: mouseArea.containsMouse ? Theme.menuTextHover : Theme.textTertiary
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: itemRoot.triggered()
}
}
component MenuSeparator: Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
Layout.topMargin: 3
Layout.bottomMargin: 3
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
}

View File

@@ -0,0 +1,102 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../theme"
import ".."
Rectangle {
id: root
width: 240
implicitHeight: batCol.implicitHeight + 24
radius: Theme.radiusMedium
color: Theme.menuDropdownBg
border.color: Theme.menuDropdownBorder
border.width: 1
ColumnLayout {
id: batCol
anchors.fill: parent
anchors.margins: 12
spacing: 8
RowLayout {
Layout.fillWidth: true
Text {
text: "Battery"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: Font.DemiBold
color: Theme.textPrimary
Layout.fillWidth: true
}
Text {
text: `${GlobalState.batteryPercent}%`
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
color: GlobalState.batteryPercent <= 20 ? Theme.accentRed : Theme.accentGreen
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
ColumnLayout {
Layout.fillWidth: true
spacing: 3
Text {
text: GlobalState.batteryPresent
? (GlobalState.batteryCharging ? "Power Source: Power Adapter" : "Power Source: Battery")
: "Power Source: AC Connected"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
Text {
text: GlobalState.batteryPresent
? `Status: ${GlobalState.batteryStatus}`
: "Desktop Workstation Mode"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 24
radius: Theme.radiusSmall
color: batPrefMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.15) : Qt.rgba(1.0, 1.0, 1.0, 0.08)
Text {
anchors.centerIn: parent
text: "Energy Saver Preferences..."
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
MouseArea {
id: batPrefMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
GlobalState.batteryPopupVisible = false;
GlobalState.launchApp("foot -e btop");
}
}
}
}
}

View File

@@ -0,0 +1,94 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../theme"
import ".."
Rectangle {
id: root
width: 250
implicitHeight: calCol.implicitHeight + 24
radius: Theme.radiusMedium
color: Theme.menuDropdownBg
border.color: Theme.menuDropdownBorder
border.width: 1
ColumnLayout {
id: calCol
anchors.fill: parent
anchors.margins: 12
spacing: 10
Text {
text: GlobalState.fullDateString
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: Font.DemiBold
color: Theme.textPrimary
Layout.alignment: Qt.AlignHCenter
}
Text {
text: GlobalState.timeString
font.family: Theme.fontFamily
font.pixelSize: 22
font.weight: Font.Light
color: Theme.accentBlue
Layout.alignment: Qt.AlignHCenter
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
// Days grid header
RowLayout {
Layout.fillWidth: true
Repeater {
model: ["S", "M", "T", "W", "T", "F", "S"]
delegate: Text {
text: modelData
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
color: Theme.textTertiary
horizontalAlignment: Text.AlignHCenter
Layout.fillWidth: true
}
}
}
// Quick mini-calendar representation
GridLayout {
id: gridDays
columns: 7
Layout.fillWidth: true
rowSpacing: 4
columnSpacing: 4
readonly property var todayDate: new Date()
readonly property int currentDay: todayDate.getDate()
Repeater {
model: 31
delegate: Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 22
radius: 11
color: (index + 1) === gridDays.currentDay ? Theme.accentBlue : "transparent"
Text {
anchors.centerIn: parent
text: `${index + 1}`
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: (index + 1) === gridDays.currentDay ? Font.Bold : Font.Normal
color: (index + 1) === gridDays.currentDay ? "#FFFFFF" : Theme.textSecondary
}
}
}
}
}
}

View File

@@ -0,0 +1,638 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import "../theme"
import ".."
PanelWindow {
id: ccWindow
visible: GlobalState.controlCenterVisible
anchors {
top: true
right: true
bottom: true
}
margins {
top: Theme.menuBarHeight
}
implicitWidth: 360
color: "transparent"
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.namespace: "quickshell-controlcenter"
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
property int activeTab: 0 // 0 = Today, 1 = Notifications
// Sidebar Container
Rectangle {
id: sidebarPanel
anchors.fill: parent
color: Theme.windowBg
border.color: Theme.windowBorder
border.width: 1
ColumnLayout {
anchors.fill: parent
anchors.margins: 14
spacing: 12
// =================================================================
// TAB SWITCHER (Today | Notifications)
// =================================================================
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 30
radius: Theme.radiusMedium
color: Qt.rgba(0.0, 0.0, 0.0, 0.3)
RowLayout {
anchors.fill: parent
spacing: 0
// Today Tab Button
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
radius: Theme.radiusMedium
color: ccWindow.activeTab === 0 ? Qt.rgba(1.0, 1.0, 1.0, 0.18) : "transparent"
Text {
anchors.centerIn: parent
text: "Today"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: ccWindow.activeTab === 0 ? Font.DemiBold : Font.Normal
color: ccWindow.activeTab === 0 ? "#FFFFFF" : Theme.textTertiary
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: ccWindow.activeTab = 0
}
}
// Notifications Tab Button
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
radius: Theme.radiusMedium
color: ccWindow.activeTab === 1 ? Qt.rgba(1.0, 1.0, 1.0, 0.18) : "transparent"
Text {
anchors.centerIn: parent
text: "Notifications"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: ccWindow.activeTab === 1 ? Font.DemiBold : Font.Normal
color: ccWindow.activeTab === 1 ? "#FFFFFF" : Theme.textTertiary
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: ccWindow.activeTab = 1
}
}
}
}
// =================================================================
// TAB 1: TODAY VIEW
// =================================================================
ScrollView {
visible: ccWindow.activeTab === 0
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
ColumnLayout {
width: parent.width
spacing: 12
// 1. Large Date & Time Widget
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 70
radius: Theme.radiusLarge
color: Theme.cardBg
border.color: Theme.cardBorder
border.width: 1
ColumnLayout {
anchors.fill: parent
anchors.margins: 12
spacing: 2
Text {
text: GlobalState.fullDateString
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
color: Theme.accentBlue
}
Text {
text: GlobalState.timeString
font.family: Theme.fontFamily
font.pixelSize: 26
font.weight: Font.Light
color: "#FFFFFF"
}
}
}
// 2. Control Toggles (Wi-Fi, Bluetooth, DND, Night Shift)
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 120
radius: Theme.radiusLarge
color: Theme.cardBg
border.color: Theme.cardBorder
border.width: 1
GridLayout {
anchors.fill: parent
anchors.margins: 10
columns: 2
rowSpacing: 8
columnSpacing: 8
// Wi-Fi Toggle
ToggleCard {
iconSource: "../assets/wifi.svg"
title: "Wi-Fi"
subtitle: GlobalState.wifiSsid
isActive: GlobalState.wifiConnected
onClicked: GlobalState.launchApp("nm-connection-editor || foot -e nmtui")
}
// Bluetooth Toggle
ToggleCard {
iconSource: "../assets/bluetooth.svg"
title: "Bluetooth"
subtitle: "Active"
isActive: true
onClicked: GlobalState.launchApp("foot -e bluetoothctl")
}
// Do Not Disturb Toggle
ToggleCard {
iconSource: "../assets/preferences.svg"
title: "Do Not Disturb"
subtitle: "Off"
isActive: false
onClicked: {}
}
// Sound Mute Toggle
ToggleCard {
iconSource: "../assets/volume.svg"
title: "Sound"
subtitle: GlobalState.volumeMuted ? "Muted" : `${GlobalState.volume}%`
isActive: !GlobalState.volumeMuted
onClicked: GlobalState.toggleVolumeMute()
}
}
}
// 3. Brightness & Volume Sliders
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 110
radius: Theme.radiusLarge
color: Theme.cardBg
border.color: Theme.cardBorder
border.width: 1
ColumnLayout {
anchors.fill: parent
anchors.margins: 12
spacing: 10
// Display Brightness Slider
RowLayout {
Layout.fillWidth: true
spacing: 8
Image {
width: 16
height: 16
source: "../assets/brightness.svg"
sourceSize: Qt.size(16, 16)
}
Item {
Layout.fillWidth: true
height: 18
Rectangle {
anchors.fill: parent
radius: 9
color: Qt.rgba(1,1,1,0.18)
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: parent.width * (GlobalState.brightness / 100.0)
radius: 9
color: "#FFFFFF"
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
function update(m) {
const frac = Math.max(0.01, Math.min(1.0, m.x / width));
GlobalState.setBrightness(Math.round(frac * 100));
}
onPressed: (m) => update(m)
onPositionChanged: (m) => { if (pressed) update(m); }
}
}
}
// Sound Volume Slider
RowLayout {
Layout.fillWidth: true
spacing: 8
Image {
width: 16
height: 16
source: "../assets/volume.svg"
sourceSize: Qt.size(16, 16)
}
Item {
Layout.fillWidth: true
height: 18
Rectangle {
anchors.fill: parent
radius: 9
color: Qt.rgba(1,1,1,0.18)
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: parent.width * (GlobalState.volume / 100.0)
radius: 9
color: Theme.accentBlue
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
function update(m) {
const frac = Math.max(0.0, Math.min(1.0, m.x / width));
GlobalState.setVolume(Math.round(frac * 100));
}
onPressed: (m) => update(m)
onPositionChanged: (m) => { if (pressed) update(m); }
}
}
}
}
}
// 4. System Resources Monitor Widget
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 90
radius: Theme.radiusLarge
color: Theme.cardBg
border.color: Theme.cardBorder
border.width: 1
ColumnLayout {
anchors.fill: parent
anchors.margins: 12
spacing: 6
Text {
text: "System Performance"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
color: Theme.textSecondary
}
// CPU Bar
RowLayout {
Layout.fillWidth: true
spacing: 8
Text {
text: "CPU"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
Layout.preferredWidth: 32
}
Rectangle {
Layout.fillWidth: true
height: 6
radius: 3
color: Qt.rgba(1,1,1,0.15)
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: parent.width * (GlobalState.cpuPercent / 100.0)
radius: 3
color: GlobalState.cpuPercent > 80 ? Theme.accentRed : Theme.accentGreen
}
}
Text {
text: `${GlobalState.cpuPercent}%`
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
Layout.preferredWidth: 36
horizontalAlignment: Text.AlignRight
}
}
// Memory Bar
RowLayout {
Layout.fillWidth: true
spacing: 8
Text {
text: "RAM"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
Layout.preferredWidth: 32
}
Rectangle {
Layout.fillWidth: true
height: 6
radius: 3
color: Qt.rgba(1,1,1,0.15)
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: parent.width * (GlobalState.memPercent / 100.0)
radius: 3
color: Theme.accentBlue
}
}
Text {
text: `${GlobalState.memUsedGb}G`
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
Layout.preferredWidth: 36
horizontalAlignment: Text.AlignRight
}
}
}
}
// 5. Now Playing Media Widget
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 80
radius: Theme.radiusLarge
color: Theme.cardBg
border.color: Theme.cardBorder
border.width: 1
RowLayout {
anchors.fill: parent
anchors.margins: 12
spacing: 10
Image {
width: 36
height: 36
source: "../assets/music.svg"
sourceSize: Qt.size(36, 36)
}
ColumnLayout {
Layout.fillWidth: true
spacing: 2
Text {
text: GlobalState.mediaTitle || "No Media Playing"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: Font.Medium
color: "#FFFFFF"
elide: Text.ElideRight
Layout.fillWidth: true
}
Text {
text: GlobalState.mediaArtist || "Apple Music"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textTertiary
elide: Text.ElideRight
Layout.fillWidth: true
}
}
// Playback controls
RowLayout {
spacing: 4
Rectangle {
width: 24
height: 24
radius: 12
color: Qt.rgba(1,1,1,0.1)
Text { anchors.centerIn: parent; text: "⏮"; color: "#FFFFFF"; font.pixelSize: 10 }
MouseArea { anchors.fill: parent; cursorShape: Qt.PointingHandCursor; onClicked: GlobalState.mediaPrevious() }
}
Rectangle {
width: 28
height: 28
radius: 14
color: Theme.accentBlue
Text { anchors.centerIn: parent; text: GlobalState.mediaPlaying ? "⏸" : "▶"; color: "#FFFFFF"; font.pixelSize: 11 }
MouseArea { anchors.fill: parent; cursorShape: Qt.PointingHandCursor; onClicked: GlobalState.mediaPlayPause() }
}
Rectangle {
width: 24
height: 24
radius: 12
color: Qt.rgba(1,1,1,0.1)
Text { anchors.centerIn: parent; text: "⏭"; color: "#FFFFFF"; font.pixelSize: 10 }
MouseArea { anchors.fill: parent; cursorShape: Qt.PointingHandCursor; onClicked: GlobalState.mediaNext() }
}
}
}
}
}
}
// =================================================================
// TAB 2: NOTIFICATIONS VIEW
// =================================================================
ColumnLayout {
visible: ccWindow.activeTab === 1
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 12
RowLayout {
Layout.fillWidth: true
Text {
text: "Notifications"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.DemiBold
color: "#FFFFFF"
Layout.fillWidth: true
}
Rectangle {
implicitWidth: clearText.implicitWidth + 12
height: 22
radius: Theme.radiusSmall
color: Qt.rgba(1,1,1,0.12)
Text {
id: clearText
anchors.centerIn: parent
text: "Clear All"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {}
}
}
}
// Placeholder / Active notifications card
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 70
radius: Theme.radiusLarge
color: Theme.cardBg
border.color: Theme.cardBorder
border.width: 1
RowLayout {
anchors.fill: parent
anchors.margins: 12
spacing: 10
Image {
width: 28
height: 28
source: "../assets/apple.svg"
sourceSize: Qt.size(28, 28)
}
ColumnLayout {
Layout.fillWidth: true
spacing: 2
Text {
text: "macOS Catalina on Hyprland"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: Font.Medium
color: "#FFFFFF"
}
Text {
text: "Quickshell desktop loaded successfully."
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
}
}
}
}
Item {
Layout.fillHeight: true
}
}
}
}
// Toggle Card Component
component ToggleCard: Rectangle {
id: cardRoot
property string iconSource: ""
property string title: ""
property string subtitle: ""
property bool isActive: false
signal clicked()
Layout.fillWidth: true
Layout.preferredHeight: 46
radius: Theme.radiusMedium
color: cardMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.22) : Qt.rgba(1.0, 1.0, 1.0, 0.12)
RowLayout {
anchors.fill: parent
anchors.margins: 8
spacing: 8
Rectangle {
width: 28
height: 28
radius: 14
color: cardRoot.isActive ? Theme.accentBlue : Qt.rgba(1,1,1,0.2)
Image {
anchors.centerIn: parent
width: 14
height: 14
source: cardRoot.iconSource
sourceSize: Qt.size(14, 14)
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: 1
Text {
text: cardRoot.title
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: "#FFFFFF"
elide: Text.ElideRight
}
Text {
text: cardRoot.subtitle
font.family: Theme.fontFamily
font.pixelSize: 10
color: Theme.textTertiary
elide: Text.ElideRight
}
}
}
MouseArea {
id: cardMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: cardRoot.clicked()
}
}
}

View File

@@ -0,0 +1,338 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import Quickshell.Hyprland
import "../theme"
import ".."
PanelWindow {
id: dockWindow
property var modelData
screen: modelData
anchors {
bottom: true
}
margins {
bottom: 6
}
// Adjust width to fit content
implicitWidth: dockTray.implicitWidth + 32
implicitHeight: 90
color: "transparent"
WlrLayershell.layer: WlrLayer.Top
WlrLayershell.namespace: "quickshell-dock"
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
// Reserve 70px exclusive zone so windows don't overlap the dock
exclusiveZone: 70
// Tooltip overlay container
Item {
id: tooltipContainer
anchors.fill: parent
z: 100
}
// 2.5D Frosted Glass Dock Tray
Rectangle {
id: dockTray
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
implicitWidth: dockLayout.implicitWidth + 24
height: 68
radius: Theme.radiusDock
color: Theme.dockBg
border.color: Theme.dockBorder
border.width: 1
// Top glossy reflection edge line (Catalina shelf characteristic)
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.leftMargin: 12
anchors.rightMargin: 12
height: 1
color: Theme.dockHighlight
opacity: 0.8
}
// Inner items layout
RowLayout {
id: dockLayout
anchors.centerIn: parent
spacing: 6
// =================================================================
// 1. PINNED APPS
// =================================================================
DockItem {
id: finderItem
name: "Finder"
iconSource: "../assets/finder.svg"
execCmd: "foot -e sh -c 'cd ~; lf || yazi || ls -la; exec zsh'"
appClass: "foot"
isPinned: true
}
DockItem {
name: "Launchpad"
iconSource: "../assets/launchpad.svg"
execCmd: ""
isPinned: true
onCustomClicked: GlobalState.toggleSpotlight()
}
DockItem {
name: "Brave Browser"
iconSource: "../assets/browser.svg"
execCmd: "brave"
appClass: "brave-browser"
isPinned: true
}
DockItem {
name: "Terminal"
iconSource: "../assets/terminal.svg"
execCmd: "foot"
appClass: "foot"
isPinned: true
}
DockItem {
name: "Neovim"
iconSource: "../assets/code.svg"
execCmd: "foot -e nvim"
appClass: "nvim"
isPinned: true
}
DockItem {
name: "System Preferences"
iconSource: "../assets/preferences.svg"
execCmd: "pavucontrol"
appClass: "pavucontrol"
isPinned: true
}
DockItem {
name: "App Store"
iconSource: "../assets/appstore.svg"
execCmd: "foot -e zsh -c 'echo NixOS Packages; nix-env -qaP | head -n 50; exec zsh'"
appClass: ""
isPinned: true
}
DockItem {
name: "Music"
iconSource: "../assets/music.svg"
execCmd: ""
appClass: ""
isPinned: true
onCustomClicked: GlobalState.mediaPlayPause()
}
// =================================================================
// 2. DYNAMIC RUNNING APPS (Not pinned)
// =================================================================
Repeater {
model: {
const pinnedClasses = ["foot", "brave-browser", "pavucontrol", "nvim"];
const list = [];
const seen = {};
if (Array.isArray(GlobalState.runningApps)) {
for (let i = 0; i < GlobalState.runningApps.length; i++) {
const client = GlobalState.runningApps[i];
const cls = (client.class || "").toLowerCase();
if (cls && !pinnedClasses.includes(cls) && !seen[cls]) {
seen[cls] = true;
list.push({
name: client.title || client.class || "App",
cls: client.class,
address: client.address
});
}
}
}
return list;
}
delegate: DockItem {
required property var modelData
name: modelData.name
iconSource: "../assets/code.svg"
appClass: modelData.cls
isPinned: false
onCustomClicked: {
if (modelData.address) {
Hyprland.dispatch(`focuswindow address:${modelData.address}`);
}
}
}
}
// =================================================================
// 3. DOCK SEPARATOR DIVIDER
// =================================================================
Rectangle {
Layout.preferredWidth: 1
Layout.preferredHeight: 44
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: 4
Layout.rightMargin: 4
color: Qt.rgba(1.0, 1.0, 1.0, 0.22)
}
// =================================================================
// 4. DOWNLOADS FOLDER & TRASH
// =================================================================
DockItem {
name: "Downloads"
iconSource: "../assets/folder-downloads.svg"
execCmd: "foot -e sh -c 'cd ~/Downloads; ls -la; exec zsh'"
isPinned: true
}
DockItem {
name: "Trash"
iconSource: "../assets/trash-empty.svg"
execCmd: "foot -e sh -c 'cd ~/.local/share/Trash/files 2>/dev/null || cd ~; ls -la; exec zsh'"
isPinned: true
}
}
}
// Reusable Dock Item Component
component DockItem: Item {
id: itemRoot
property string name: ""
property string iconSource: ""
property string execCmd: ""
property string appClass: ""
property bool isPinned: true
signal customClicked()
// Check if app is running
readonly property bool isRunning: {
if (!itemRoot.appClass) return false;
const target = itemRoot.appClass.toLowerCase();
if (GlobalState.activeWindowClass.toLowerCase().includes(target)) return true;
if (Array.isArray(GlobalState.runningApps)) {
for (let i = 0; i < GlobalState.runningApps.length; i++) {
const c = GlobalState.runningApps[i];
if ((c.class || "").toLowerCase().includes(target)) return true;
}
}
return false;
}
implicitWidth: 50
implicitHeight: 64
Layout.alignment: Qt.AlignBottom
// Container with scale & bounce transform
Item {
id: iconWrapper
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 8
width: 48
height: 48
scale: itemArea.containsMouse ? 1.28 : 1.0
y: itemArea.containsMouse ? -8 : 0
Behavior on scale {
NumberAnimation { duration: 180; easing.type: Easing.OutCubic }
}
Behavior on y {
NumberAnimation { duration: 180; easing.type: Easing.OutCubic }
}
// Icon Image
Image {
anchors.centerIn: parent
width: 46
height: 46
source: itemRoot.iconSource
sourceSize: Qt.size(92, 92)
smooth: true
mipmap: true
}
// Click Bounce Sequential Animation
SequentialAnimation {
id: bounceAnim
NumberAnimation { target: iconWrapper; property: "y"; to: -24; duration: 150; easing.type: Easing.OutQuad }
NumberAnimation { target: iconWrapper; property: "y"; to: -4; duration: 130; easing.type: Easing.InQuad }
NumberAnimation { target: iconWrapper; property: "y"; to: -14; duration: 100; easing.type: Easing.OutQuad }
NumberAnimation { target: iconWrapper; property: "y"; to: 0; duration: 100; easing.type: Easing.InQuad }
}
}
// Active App Running Indicator Dot (White glowing pill)
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 2
width: 4
height: 4
radius: 2
color: Theme.dockDot
visible: itemRoot.isRunning
}
// Hover Tooltip Badge (macOS Catalina Style Black Pill)
Rectangle {
id: tooltipPill
visible: itemArea.containsMouse
opacity: itemArea.containsMouse ? 1.0 : 0.0
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.top
anchors.bottomMargin: 6
implicitWidth: tooltipText.implicitWidth + 16
height: 24
radius: 6
color: Qt.rgba(0.08, 0.08, 0.10, 0.92)
border.color: Qt.rgba(1.0, 1.0, 1.0, 0.18)
border.width: 1
Behavior on opacity {
NumberAnimation { duration: 120 }
}
Text {
id: tooltipText
anchors.centerIn: parent
text: itemRoot.name
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: "#FFFFFF"
}
}
// Mouse interaction
MouseArea {
id: itemArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
bounceAnim.start();
if (itemRoot.execCmd !== "") {
GlobalState.launchApp(itemRoot.execCmd);
} else {
itemRoot.customClicked();
}
}
}
}
}

View File

@@ -0,0 +1,507 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import Quickshell.Hyprland
import Quickshell.Services.SystemTray
import "../theme"
import ".."
PanelWindow {
id: menuBarWindow
property var modelData
screen: modelData
anchors {
top: true
left: true
right: true
}
// Set implicitHeight to accommodate bar + open popups without clipping
implicitHeight: (GlobalState.appleMenuVisible || GlobalState.activeDropdownMenu !== "" ||
GlobalState.volumePopupVisible || GlobalState.wifiPopupVisible ||
GlobalState.batteryPopupVisible || GlobalState.calendarPopupVisible) ? 420 : Theme.menuBarHeight
color: "transparent"
WlrLayershell.layer: WlrLayer.Top
WlrLayershell.namespace: "quickshell-menubar"
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
// Set exclusive zone only for the 26px bar
exclusiveZone: Theme.menuBarHeight
// Background Bar (26px)
Rectangle {
id: barRect
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: Theme.menuBarHeight
color: Theme.menuBarBg
border.color: Theme.menuBarBorder
border.width: 0
// Bottom hairline border
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 1
color: Theme.menuBarBorder
}
RowLayout {
anchors.fill: parent
anchors.leftMargin: 12
anchors.rightMargin: 12
spacing: 0
// =================================================================
// LEFT SIDE: Apple Menu + App Title + Standard Menus
// =================================================================
RowLayout {
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
spacing: 2
// Apple Logo Button
Rectangle {
id: appleBtn
width: 28
height: 20
radius: Theme.radiusSmall
color: (GlobalState.appleMenuVisible || appleMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.18) : "transparent"
Image {
anchors.centerIn: parent
width: 14
height: 14
source: "../assets/apple.svg"
sourceSize: Qt.size(14, 14)
}
MouseArea {
id: appleMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const wasOpen = GlobalState.appleMenuVisible;
GlobalState.closeAllPopups();
GlobalState.appleMenuVisible = !wasOpen;
}
}
}
// Active App Title (Bold)
Rectangle {
id: appTitleBtn
implicitWidth: appTitleText.implicitWidth + 16
height: 20
radius: Theme.radiusSmall
color: titleMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
Text {
id: appTitleText
anchors.centerIn: parent
text: GlobalState.activeWindowClass || "Finder"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeMenuBar
font.weight: Font.Bold
color: Theme.textPrimary
}
MouseArea {
id: titleMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const wasOpen = (GlobalState.activeDropdownMenu === "File");
GlobalState.closeAllPopups();
GlobalState.activeDropdownMenu = wasOpen ? "" : "File";
}
}
}
// Standard Menus: File, Edit, View, Window, Help
Repeater {
model: ["File", "Edit", "View", "Window", "Help"]
delegate: Rectangle {
id: menuBtn
implicitWidth: menuText.implicitWidth + 14
height: 20
radius: Theme.radiusSmall
color: (GlobalState.activeDropdownMenu === modelData || menuMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
Text {
id: menuText
anchors.centerIn: parent
text: modelData
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeMenuBar
font.weight: Font.Normal
color: Theme.textPrimary
}
MouseArea {
id: menuMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: {
// If a menu is already open, hovering switches to this one
if (GlobalState.activeDropdownMenu !== "") {
GlobalState.activeDropdownMenu = modelData;
}
}
onClicked: {
const wasOpen = (GlobalState.activeDropdownMenu === modelData);
GlobalState.closeAllPopups();
GlobalState.activeDropdownMenu = wasOpen ? "" : modelData;
}
}
}
}
}
// Spacer
Item {
Layout.fillWidth: true
}
// =================================================================
// RIGHT SIDE: Tray + Media + Volume + Wifi + Battery + Spotlight + Control Center + Clock
// =================================================================
RowLayout {
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
spacing: 4
// System Tray Icons
Repeater {
model: SystemTray.items
delegate: Rectangle {
required property SystemTrayItem modelData
width: 22
height: 20
radius: Theme.radiusSmall
color: trayMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
Image {
anchors.centerIn: parent
width: 15
height: 15
source: modelData.icon || ""
sourceSize: Qt.size(15, 15)
}
MouseArea {
id: trayMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: modelData.activate()
}
}
}
// Media Indicator (visible if playing)
Rectangle {
visible: GlobalState.mediaPlaying
implicitWidth: mediaRow.implicitWidth + 12
height: 20
radius: Theme.radiusSmall
color: mediaMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
RowLayout {
id: mediaRow
anchors.centerIn: parent
spacing: 4
Image {
width: 13
height: 13
source: "../assets/music.svg"
sourceSize: Qt.size(13, 13)
}
Text {
text: GlobalState.mediaTitle ? `${GlobalState.mediaTitle.substring(0, 18)}...` : "Playing"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
}
}
MouseArea {
id: mediaMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: GlobalState.mediaPlayPause()
}
}
// Volume Item
Rectangle {
id: volBtn
width: 26
height: 20
radius: Theme.radiusSmall
color: (GlobalState.volumePopupVisible || volMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
Image {
anchors.centerIn: parent
width: 14
height: 14
source: "../assets/volume.svg"
sourceSize: Qt.size(14, 14)
}
MouseArea {
id: volMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const wasOpen = GlobalState.volumePopupVisible;
GlobalState.closeAllPopups();
GlobalState.volumePopupVisible = !wasOpen;
}
}
}
// Wi-Fi Item
Rectangle {
id: wifiBtn
width: 26
height: 20
radius: Theme.radiusSmall
color: (GlobalState.wifiPopupVisible || wifiMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
Image {
anchors.centerIn: parent
width: 14
height: 14
source: "../assets/wifi.svg"
sourceSize: Qt.size(14, 14)
}
MouseArea {
id: wifiMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const wasOpen = GlobalState.wifiPopupVisible;
GlobalState.closeAllPopups();
GlobalState.wifiPopupVisible = !wasOpen;
}
}
}
// Battery Item
Rectangle {
id: batBtn
implicitWidth: batRow.implicitWidth + 8
height: 20
radius: Theme.radiusSmall
color: (GlobalState.batteryPopupVisible || batMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
RowLayout {
id: batRow
anchors.centerIn: parent
spacing: 4
Text {
visible: GlobalState.batteryPresent
text: `${GlobalState.batteryPercent}%`
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
Image {
width: 18
height: 12
source: "../assets/battery.svg"
sourceSize: Qt.size(18, 12)
}
}
MouseArea {
id: batMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const wasOpen = GlobalState.batteryPopupVisible;
GlobalState.closeAllPopups();
GlobalState.batteryPopupVisible = !wasOpen;
}
}
}
// Spotlight Search Button
Rectangle {
id: spotBtn
width: 26
height: 20
radius: Theme.radiusSmall
color: (GlobalState.spotlightVisible || spotMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
Image {
anchors.centerIn: parent
width: 14
height: 14
source: "../assets/spotlight.svg"
sourceSize: Qt.size(14, 14)
}
MouseArea {
id: spotMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: GlobalState.toggleSpotlight()
}
}
// Control Center / Notification Center Toggle Button
Rectangle {
id: ccBtn
width: 26
height: 20
radius: Theme.radiusSmall
color: (GlobalState.controlCenterVisible || ccMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
Image {
anchors.centerIn: parent
width: 14
height: 14
source: "../assets/controlcenter.svg"
sourceSize: Qt.size(14, 14)
}
MouseArea {
id: ccMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: GlobalState.toggleControlCenter()
}
}
// Date & Time (Clock)
Rectangle {
id: clockBtn
implicitWidth: clockRow.implicitWidth + 10
height: 20
radius: Theme.radiusSmall
color: (GlobalState.calendarPopupVisible || clockMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
RowLayout {
id: clockRow
anchors.centerIn: parent
spacing: 6
Text {
text: GlobalState.dateString
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeMenuBar
color: Theme.textSecondary
}
Text {
text: GlobalState.timeString
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeMenuBar
font.weight: Font.Medium
color: Theme.textPrimary
}
}
MouseArea {
id: clockMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const wasOpen = GlobalState.calendarPopupVisible;
GlobalState.closeAllPopups();
GlobalState.calendarPopupVisible = !wasOpen;
}
}
}
}
}
}
// =========================================================================
// DROPDOWNS & POPUPS
// =========================================================================
// 1. Apple Menu Dropdown
AppleMenu {
id: appleDropdown
visible: GlobalState.appleMenuVisible
x: 8
y: Theme.menuBarHeight + 2
}
// 2. Application Menus Dropdown (File, Edit, View, Window, Help)
AppMenuDropdown {
id: appMenuDropdown
visible: GlobalState.activeDropdownMenu !== ""
menuName: GlobalState.activeDropdownMenu
x: 60
y: Theme.menuBarHeight + 2
}
// 3. Volume Popup
VolumePopup {
id: volumeDropdown
visible: GlobalState.volumePopupVisible
anchors.top: barRect.bottom
anchors.topMargin: 2
anchors.right: parent.right
anchors.rightMargin: 190
}
// 4. Wi-Fi Popup
WifiPopup {
id: wifiDropdown
visible: GlobalState.wifiPopupVisible
anchors.top: barRect.bottom
anchors.topMargin: 2
anchors.right: parent.right
anchors.rightMargin: 160
}
// 5. Battery Popup
BatteryPopup {
id: batteryDropdown
visible: GlobalState.batteryPopupVisible
anchors.top: barRect.bottom
anchors.topMargin: 2
anchors.right: parent.right
anchors.rightMargin: 110
}
// 6. Calendar Popup
CalendarPopup {
id: calDropdown
visible: GlobalState.calendarPopupVisible
anchors.top: barRect.bottom
anchors.topMargin: 2
anchors.right: parent.right
anchors.rightMargin: 10
}
}

View File

@@ -0,0 +1,340 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import Quickshell.Io
import "../theme"
import ".."
PanelWindow {
id: spotWindow
visible: GlobalState.spotlightVisible
anchors {
top: true
left: true
right: true
bottom: true
}
color: Qt.rgba(0, 0, 0, 0.35)
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.namespace: "quickshell-spotlight"
WlrLayershell.keyboardFocus: visible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
// Dismiss when clicking outside modal
MouseArea {
anchors.fill: parent
onClicked: GlobalState.spotlightVisible = false
}
// App Database Loader Process
readonly property Process appScanProc: Process {
command: ["bash", "-c", "dirs=(\"/run/current-system/sw/share/applications\" \"$HOME/.nix-profile/share/applications\" \"$HOME/.local/share/applications\"); echo '['; first=1; for d in \"${dirs[@]}\"; do [ -d \"$d\" ] && for f in \"$d\"/*.desktop; do [ -e \"$f\" ] || continue; grep -q \"^NoDisplay=true\" \"$f\" 2>/dev/null && continue; n=$(grep -m 1 \"^Name=\" \"$f\" 2>/dev/null | cut -d= -f2-); e=$(grep -m 1 \"^Exec=\" \"$f\" 2>/dev/null | cut -d= -f2- | sed -E 's/%[fFuUdDnNickvm]//g'); if [ -n \"$n\" ] && [ -n \"$e\" ]; then [ $first -eq 0 ] && echo ','; first=0; echo \"{\\\"name\\\":\\\"$n\\\",\\\"exec\\\":\\\"$e\\\"}\"; fi; done; done; echo ']'"]
stdout: StdioCollector {
onDataChanged: {
try {
const parsed = JSON.parse(data.trim());
if (Array.isArray(parsed)) {
spotWindow.allApps = parsed;
}
} catch(e) {}
}
}
}
property var allApps: [
{ name: "Brave Browser", exec: "brave", comment: "Web Browser", icon: "browser" },
{ name: "Foot Terminal", exec: "foot", comment: "Terminal Emulator", icon: "terminal" },
{ name: "Neovim", exec: "foot -e nvim", comment: "Code Editor", icon: "code" },
{ name: "Activity Monitor (Btop)", exec: "foot -e btop", comment: "System Resources", icon: "preferences" },
{ name: "Volume & Sound (Pavucontrol)", exec: "pavucontrol", comment: "Audio Settings", icon: "preferences" },
{ name: "Lock Screen", exec: "hyprlock", comment: "Lock Session", icon: "preferences" },
{ name: "System Reboot", exec: "systemctl reboot", comment: "Reboot NixOS", icon: "preferences" },
{ name: "Shut Down", exec: "systemctl poweroff", comment: "Power Off", icon: "preferences" }
]
property int selectedIndex: 0
onVisibleChanged: {
if (visible) {
appScanProc.running = true;
searchInput.text = "";
selectedIndex = 0;
searchInput.forceActiveFocus();
}
}
// Centered Spotlight Search Modal
Rectangle {
id: modalBox
anchors.horizontalCenter: parent.horizontalCenter
y: 140
width: 640
implicitHeight: searchBarRow.height + (resultsListView.count > 0 || mathResultText !== "" ? 340 : 0)
radius: Theme.radiusModal
color: Theme.windowBg
border.color: Theme.windowBorder
border.width: 1
Behavior on implicitHeight {
NumberAnimation { duration: 180; easing.type: Easing.OutQuad }
}
// Prevent clicking inside from closing modal
MouseArea {
anchors.fill: parent
onClicked: {}
}
ColumnLayout {
anchors.fill: parent
anchors.margins: 14
spacing: 12
// Top Search Bar
RowLayout {
id: searchBarRow
Layout.fillWidth: true
Layout.preferredHeight: 44
spacing: 12
Image {
width: 24
height: 24
source: "../assets/spotlight.svg"
sourceSize: Qt.size(24, 24)
}
TextInput {
id: searchInput
Layout.fillWidth: true
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSpotlight
font.weight: Font.Light
color: Theme.textPrimary
focus: true
clip: true
Text {
anchors.fill: parent
visible: searchInput.text === ""
text: "Spotlight Search"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSpotlight
font.weight: Font.Light
color: Theme.textTertiary
}
Keys.onEscapePressed: GlobalState.spotlightVisible = false
Keys.onDownPressed: {
if (resultsListView.count > 0) {
spotWindow.selectedIndex = Math.min(resultsListView.count - 1, spotWindow.selectedIndex + 1);
}
}
Keys.onUpPressed: {
if (resultsListView.count > 0) {
spotWindow.selectedIndex = Math.max(0, spotWindow.selectedIndex - 1);
}
}
Keys.onReturnPressed: {
if (filteredModel.count > 0 && spotWindow.selectedIndex < filteredModel.count) {
const item = filteredModel.get(spotWindow.selectedIndex);
GlobalState.launchApp(item.exec);
}
}
}
// Clear button
Rectangle {
visible: searchInput.text !== ""
width: 20
height: 20
radius: 10
color: Qt.rgba(1.0, 1.0, 1.0, 0.2)
Text {
anchors.centerIn: parent
text: "✕"
font.pixelSize: 11
color: Theme.textPrimary
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: searchInput.text = ""
}
}
}
// Math Calculation Result Banner (if valid formula)
Rectangle {
visible: mathResultText !== ""
Layout.fillWidth: true
Layout.preferredHeight: 36
radius: Theme.radiusSmall
color: Qt.rgba(0.04, 0.52, 1.0, 0.2)
border.color: Theme.accentBlue
border.width: 1
RowLayout {
anchors.fill: parent
anchors.margins: 8
spacing: 8
Text {
text: "="
font.family: Theme.fontFamily
font.pixelSize: 16
font.weight: Font.Bold
color: Theme.accentBlue
}
Text {
text: mathResultText
font.family: Theme.fontFamily
font.pixelSize: 16
font.weight: Font.DemiBold
color: "#FFFFFF"
Layout.fillWidth: true
}
}
}
// Divider Line
Rectangle {
visible: resultsListView.count > 0
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
// Search Results List View
ListView {
id: resultsListView
visible: count > 0
Layout.fillWidth: true
Layout.preferredHeight: Math.min(270, count * 42)
clip: true
spacing: 2
model: filteredModel
delegate: Rectangle {
id: itemDelegate
required property int index
required property string name
required property string exec
required property string comment
width: resultsListView.width
height: 40
radius: Theme.radiusSmall
color: spotWindow.selectedIndex === index ? Theme.menuHoverBlue : "transparent"
RowLayout {
anchors.fill: parent
anchors.leftMargin: 10
anchors.rightMargin: 10
spacing: 10
Image {
width: 22
height: 22
source: "../assets/terminal.svg"
sourceSize: Qt.size(22, 22)
}
ColumnLayout {
Layout.fillWidth: true
spacing: 1
Text {
text: itemDelegate.name
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: Font.Medium
color: "#FFFFFF"
elide: Text.ElideRight
Layout.fillWidth: true
}
Text {
text: itemDelegate.comment || itemDelegate.exec
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: spotWindow.selectedIndex === itemDelegate.index
? Qt.rgba(1,1,1,0.85) : Theme.textTertiary
elide: Text.ElideRight
Layout.fillWidth: true
}
}
Text {
text: "↩"
font.pixelSize: 14
color: spotWindow.selectedIndex === itemDelegate.index
? "#FFFFFF" : "transparent"
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: spotWindow.selectedIndex = itemDelegate.index
onClicked: GlobalState.launchApp(itemDelegate.exec)
}
}
}
}
}
// Math calculation evaluator property
readonly property string mathResultText: {
const query = searchInput.text.trim();
if (/^[0-9+\-*/^().\s%]+$/.test(query) && /[0-9]/.test(query) && /[+\-*/^%]/.test(query)) {
try {
// Safe evaluation of arithmetic
const res = Function(`"use strict"; return (${query.replace(/\^/g, "**")})`)();
if (typeof res === "number" && !isNaN(res) && isFinite(res)) {
return `${res}`;
}
} catch(e) {}
}
return "";
}
// Filtered ListModel updated on text change
ListModel {
id: filteredModel
}
function updateFilter() {
filteredModel.clear();
const query = searchInput.text.toLowerCase().trim();
let count = 0;
for (let i = 0; i < allApps.length && count < 12; i++) {
const app = allApps[i];
if (!app.name) continue;
if (query === "" || app.name.toLowerCase().includes(query) || (app.exec && app.exec.toLowerCase().includes(query))) {
filteredModel.append({
name: app.name,
exec: app.exec || "",
comment: app.comment || ""
});
count++;
}
}
}
Connections {
target: searchInput
function onTextChanged() {
spotWindow.selectedIndex = 0;
updateFilter();
}
}
Component.onCompleted: updateFilter()
}

View File

@@ -0,0 +1,148 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../theme"
import ".."
Rectangle {
id: root
width: 240
height: 110
radius: Theme.radiusMedium
color: Theme.menuDropdownBg
border.color: Theme.menuDropdownBorder
border.width: 1
ColumnLayout {
anchors.fill: parent
anchors.margins: 12
spacing: 8
RowLayout {
Layout.fillWidth: true
Text {
text: "Sound"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: Font.DemiBold
color: Theme.textPrimary
Layout.fillWidth: true
}
Text {
text: `${GlobalState.volume}%`
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
}
}
// Custom Catalina Volume Slider
Item {
Layout.fillWidth: true
Layout.preferredHeight: 24
Rectangle {
id: track
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
height: 6
radius: 3
color: Qt.rgba(1.0, 1.0, 1.0, 0.2)
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: track.width * (GlobalState.volume / 100.0)
radius: 3
color: Theme.accentBlue
}
}
Rectangle {
id: thumb
x: Math.max(0, Math.min(track.width - width, (track.width * (GlobalState.volume / 100.0)) - width / 2))
anchors.verticalCenter: parent.verticalCenter
width: 16
height: 16
radius: 8
color: "#FFFFFF"
border.color: Qt.rgba(0, 0, 0, 0.2)
border.width: 1
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
preventStealing: true
function updateFromMouse(mouse) {
const frac = Math.max(0.0, Math.min(1.0, mouse.x / width));
GlobalState.setVolume(Math.round(frac * 100));
}
onPressed: (mouse) => updateFromMouse(mouse)
onPositionChanged: (mouse) => {
if (pressed) updateFromMouse(mouse);
}
}
}
// Bottom Controls
RowLayout {
Layout.fillWidth: true
spacing: 8
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 24
radius: Theme.radiusSmall
color: muteMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.15) : Qt.rgba(1.0, 1.0, 1.0, 0.08)
Text {
anchors.centerIn: parent
text: GlobalState.volumeMuted ? "Unmute" : "Mute"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
MouseArea {
id: muteMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: GlobalState.toggleVolumeMute()
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 24
radius: Theme.radiusSmall
color: prefMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.15) : Qt.rgba(1.0, 1.0, 1.0, 0.08)
Text {
anchors.centerIn: parent
text: "Sound Preferences..."
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
MouseArea {
id: prefMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
GlobalState.volumePopupVisible = false;
GlobalState.launchApp("pavucontrol");
}
}
}
}
}
}

View File

@@ -0,0 +1,102 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../theme"
import ".."
Rectangle {
id: root
width: 240
implicitHeight: wifiCol.implicitHeight + 24
radius: Theme.radiusMedium
color: Theme.menuDropdownBg
border.color: Theme.menuDropdownBorder
border.width: 1
ColumnLayout {
id: wifiCol
anchors.fill: parent
anchors.margins: 12
spacing: 8
RowLayout {
Layout.fillWidth: true
Text {
text: "Wi-Fi"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: Font.DemiBold
color: Theme.textPrimary
Layout.fillWidth: true
}
Text {
text: GlobalState.wifiConnected ? "On" : "Off"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: GlobalState.wifiConnected ? Theme.accentGreen : Theme.textTertiary
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
// Active network info
ColumnLayout {
Layout.fillWidth: true
spacing: 3
Text {
text: GlobalState.wifiConnected ? `Connected to: ${GlobalState.wifiSsid}` : "No Network Connected"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.textPrimary
elide: Text.ElideRight
Layout.fillWidth: true
}
Text {
visible: GlobalState.ipAddress !== "" && GlobalState.ipAddress !== "Offline"
text: `IP: ${GlobalState.ipAddress}`
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 24
radius: Theme.radiusSmall
color: netMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.15) : Qt.rgba(1.0, 1.0, 1.0, 0.08)
Text {
anchors.centerIn: parent
text: "Network Preferences..."
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
MouseArea {
id: netMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
GlobalState.wifiPopupVisible = false;
GlobalState.launchApp("nm-connection-editor || foot -e nmtui");
}
}
}
}
}

View File

@@ -0,0 +1 @@
singleton GlobalState 1.0 GlobalState.qml

View File

@@ -0,0 +1,66 @@
#!/usr/bin/env bash
# Scans .desktop files and outputs JSON array of apps
dirs=(
"/run/current-system/sw/share/applications"
"$HOME/.nix-profile/share/applications"
"$HOME/.local/share/applications"
"/usr/share/applications"
)
declare -A seen
apps="["
first=true
# Add default curated Mac/system apps first
curated=(
'{"name":"Finder","exec":"foot -e sh -c \"cd ~; lf || yazi || ls -la; exec zsh\"","icon":"finder","comment":"File Manager"}'
'{"name":"Terminal","exec":"foot","icon":"terminal","comment":"Command Line Interface"}'
'{"name":"Brave Browser","exec":"brave","icon":"browser","comment":"Web Browser"}'
'{"name":"Neovim","exec":"foot -e nvim","icon":"code","comment":"Text & Code Editor"}'
'{"name":"System Preferences","exec":"pavucontrol","icon":"preferences","comment":"Audio & System Settings"}'
'{"name":"Activity Monitor","exec":"foot -e btop","icon":"preferences","comment":"Resource Monitor"}'
'{"name":"Lock Screen","exec":"hyprlock","icon":"preferences","comment":"Lock current session"}'
'{"name":"Restart System","exec":"systemctl reboot","icon":"preferences","comment":"Reboot NixOS"}'
'{"name":"Shut Down","exec":"systemctl poweroff","icon":"preferences","comment":"Power off computer"}'
)
for app in "${curated[@]}"; do
if [ "$first" = true ]; then
apps="$apps$app"
first=false
else
apps="$apps,$app"
fi
done
for dir in "${dirs[@]}"; do
if [ -d "$dir" ]; then
for f in "$dir"/*.desktop; do
[ -e "$f" ] || continue
# Check NoDisplay
if grep -q "^NoDisplay=true" "$f" 2>/dev/null; then
continue
fi
name=$(grep -m 1 "^Name=" "$f" 2>/dev/null | cut -d= -f2- | tr -d '\r\n')
exec_cmd=$(grep -m 1 "^Exec=" "$f" 2>/dev/null | cut -d= -f2- | sed -E 's/%[fFuUdDnNickvm]//g' | tr -d '\r\n')
icon=$(grep -m 1 "^Icon=" "$f" 2>/dev/null | cut -d= -f2- | tr -d '\r\n')
comment=$(grep -m 1 "^Comment=" "$f" 2>/dev/null | cut -d= -f2- | tr -d '\r\n')
if [ -n "$name" ] && [ -n "$exec_cmd" ] && [ -z "${seen[$name]}" ]; then
seen[$name]=1
# Escape quotes
name_esc=$(echo "$name" | sed 's/"/\\"/g')
exec_esc=$(echo "$exec_cmd" | sed 's/"/\\"/g')
icon_esc=$(echo "$icon" | sed 's/"/\\"/g')
comment_esc=$(echo "$comment" | sed 's/"/\\"/g')
entry="{\"name\":\"$name_esc\",\"exec\":\"$exec_esc\",\"icon\":\"$icon_esc\",\"comment\":\"$comment_esc\"}"
apps="$apps,$entry"
fi
done
fi
done
apps="$apps]"
echo "$apps"

View File

@@ -0,0 +1,20 @@
#!/usr/bin/env bash
# Read audio volume & mute state
volume=50
muted=false
if command -v pactl &>/dev/null; then
vol_str=$(pactl get-sink-volume @DEFAULT_SINK@ 2>/dev/null | grep -Po '[0-9]+(?=%)' | head -n 1)
if [ -n "$vol_str" ]; then
volume=$vol_str
fi
mute_str=$(pactl get-sink-mute @DEFAULT_SINK@ 2>/dev/null)
if echo "$mute_str" | grep -q "yes"; then
muted=true
fi
elif command -v pamixer &>/dev/null; then
volume=$(pamixer --get-volume 2>/dev/null || echo 50)
muted=$(pamixer --get-mute 2>/dev/null || echo false)
fi
echo "{\"volume\": $volume, \"muted\": $muted}"

View File

@@ -0,0 +1,16 @@
#!/usr/bin/env bash
# Read battery state
bat_path=$(find /sys/class/power_supply/ -name "BAT*" 2>/dev/null | head -n 1)
if [ -n "$bat_path" ] && [ -d "$bat_path" ]; then
capacity=$(cat "$bat_path/capacity" 2>/dev/null || echo 100)
status=$(cat "$bat_path/status" 2>/dev/null || echo "Full")
is_charging=false
if [ "$status" = "Charging" ] || [ "$status" = "Full" ]; then
is_charging=true
fi
echo "{\"present\": true, \"percent\": $capacity, \"status\": \"$status\", \"charging\": $is_charging}"
else
# Desktop without battery
echo "{\"present\": false, \"percent\": 100, \"status\": \"AC\", \"charging\": true}"
fi

View File

@@ -0,0 +1,12 @@
#!/usr/bin/env bash
# Read brightness
percent=100
if command -v brightnessctl &>/dev/null; then
percent=$(brightnessctl -m 2>/dev/null | cut -d, -f4 | tr -d '%' | head -n 1)
if [ -z "$percent" ]; then
percent=100
fi
fi
echo "{\"brightness\": ${percent:-100}}"

View File

@@ -0,0 +1,20 @@
#!/usr/bin/env bash
# Read /proc/stat CPU utilization
read -r cpu u n s i io ir st g gn < /proc/stat
total1=$((u + n + s + i + io + ir + st + g + gn))
idle1=$((i + io))
sleep 0.2
read -r cpu u n s i io ir st g gn < /proc/stat
total2=$((u + n + s + i + io + ir + st + g + gn))
idle2=$((i + io))
total_diff=$((total2 - total1))
idle_diff=$((idle2 - idle1))
if [ "$total_diff" -gt 0 ]; then
cpu_usage=$(( (total_diff - idle_diff) * 100 / total_diff ))
else
cpu_usage=0
fi
echo "$cpu_usage"

View File

@@ -0,0 +1,14 @@
#!/usr/bin/env bash
# Read memory usage from /proc/meminfo
mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
mem_avail=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
if [ -n "$mem_total" ] && [ -n "$mem_avail" ] && [ "$mem_total" -gt 0 ]; then
mem_used=$((mem_total - mem_avail))
mem_percent=$((mem_used * 100 / mem_total))
used_gb=$(awk "BEGIN {printf \"%.1f\", $mem_used/1048576}")
total_gb=$(awk "BEGIN {printf \"%.1f\", $mem_total/1048576}")
echo "{\"percent\": $mem_percent, \"used_gb\": \"$used_gb\", \"total_gb\": \"$total_gb\"}"
else
echo "{\"percent\": 0, \"used_gb\": \"0\", \"total_gb\": \"0\"}"
fi

View File

@@ -0,0 +1,30 @@
#!/usr/bin/env bash
# Read WiFi status
ssid=""
ip=""
if command -v nmcli &>/dev/null; then
active_line=$(nmcli -t -f active,ssid,signal dev wifi 2>/dev/null | grep '^yes' | head -n 1)
if [ -n "$active_line" ]; then
ssid=$(echo "$active_line" | cut -d':' -f2)
signal=$(echo "$active_line" | cut -d':' -f3)
fi
fi
if [ -z "$ssid" ]; then
# Fallback to iwgetid or /proc/net/wireless
if command -v iwgetid &>/dev/null; then
ssid=$(iwgetid -r 2>/dev/null)
fi
fi
# Get default IPv4
ip=$(ip -4 route get 1.1.1.1 2>/dev/null | awk '{print $7; exit}')
if [ -n "$ssid" ]; then
echo "{\"connected\": true, \"ssid\": \"$ssid\", \"ip\": \"${ip:-N/A}\"}"
elif [ -n "$ip" ]; then
echo "{\"connected\": true, \"ssid\": \"Ethernet\", \"ip\": \"$ip\"}"
else
echo "{\"connected\": false, \"ssid\": \"Not Connected\", \"ip\": \"None\"}"
fi

View File

@@ -0,0 +1,79 @@
import QtQuick
import Quickshell
import Quickshell.Io
import "theme"
import "components"
import "."
Scope {
id: root
// =========================================================================
// IPC HANDLERS (Allows controlling shell via `qs ipc call <target> <method>`)
// =========================================================================
IpcHandler {
target: "spotlight"
function toggle() {
GlobalState.toggleSpotlight();
}
function open() {
GlobalState.spotlightVisible = true;
}
function close() {
GlobalState.spotlightVisible = false;
}
}
IpcHandler {
target: "controlCenter"
function toggle() {
GlobalState.toggleControlCenter();
}
function open() {
GlobalState.controlCenterVisible = true;
}
function close() {
GlobalState.controlCenterVisible = false;
}
}
IpcHandler {
target: "aboutMac"
function toggle() {
GlobalState.toggleAboutMac();
}
}
// =========================================================================
// MULTI-MONITOR BARS & DOCKS
// =========================================================================
// 1. macOS Catalina Top Menu Bar (Spawned per monitor)
Variants {
model: Quickshell.screens
MenuBar {}
}
// 2. macOS Catalina Floating Dock (Spawned per monitor)
Variants {
model: Quickshell.screens
Dock {}
}
// =========================================================================
// GLOBAL MODAL OVERLAYS
// =========================================================================
// 3. Spotlight Search Overlay
Spotlight {
id: spotlightOverlay
}
// 4. Control Center & Notification Center Sidebar
ControlCenter {
id: controlCenterSidebar
}
// 5. About This Mac Dialog
AboutMac {
id: aboutMacDialog
}
}

View File

@@ -0,0 +1,57 @@
pragma Singleton
import QtQuick
QtObject {
// macOS Catalina Color Palette
readonly property color menuBarBg: Qt.rgba(0.12, 0.12, 0.14, 0.88)
readonly property color menuBarBorder: Qt.rgba(1.0, 1.0, 1.0, 0.12)
readonly property color dockBg: Qt.rgba(0.15, 0.16, 0.18, 0.72)
readonly property color dockBorder: Qt.rgba(1.0, 1.0, 1.0, 0.22)
readonly property color dockHighlight: Qt.rgba(1.0, 1.0, 1.0, 0.35)
readonly property color dockShadow: Qt.rgba(0.0, 0.0, 0.0, 0.45)
readonly property color dockDot: Qt.rgba(1.0, 1.0, 1.0, 0.95)
readonly property color windowBg: Qt.rgba(0.14, 0.14, 0.16, 0.94)
readonly property color windowBorder: Qt.rgba(1.0, 1.0, 1.0, 0.15)
readonly property color cardBg: Qt.rgba(0.22, 0.22, 0.26, 0.65)
readonly property color cardBorder: Qt.rgba(1.0, 1.0, 1.0, 0.10)
readonly property color menuDropdownBg: Qt.rgba(0.16, 0.16, 0.18, 0.96)
readonly property color menuDropdownBorder: Qt.rgba(1.0, 1.0, 1.0, 0.18)
readonly property color menuHoverBlue: "#0062E3"
readonly property color menuTextHover: "#FFFFFF"
readonly property color accentBlue: "#0A84FF"
readonly property color accentGreen: "#30D158"
readonly property color accentRed: "#FF453A"
readonly property color accentYellow: "#FFD60A"
readonly property color accentOrange: "#FF9F0A"
readonly property color textPrimary: "#FFFFFF"
readonly property color textSecondary: Qt.rgba(1.0, 1.0, 1.0, 0.72)
readonly property color textTertiary: Qt.rgba(1.0, 1.0, 1.0, 0.45)
readonly property color textDisabled: Qt.rgba(1.0, 1.0, 1.0, 0.25)
// Typography
readonly property string fontFamily: "SF Pro Display, SF Pro Text, Helvetica Neue, Cantarell, Liberation Sans, sans-serif"
readonly property int fontSizeMenuBar: 13
readonly property int fontSizeSmall: 11
readonly property int fontSizeNormal: 13
readonly property int fontSizeLarge: 15
readonly property int fontSizeTitle: 19
readonly property int fontSizeSpotlight: 20
// Geometry & Radii
readonly property int menuBarHeight: 26
readonly property int radiusSmall: 4
readonly property int radiusMedium: 8
readonly property int radiusLarge: 14
readonly property int radiusDock: 18
readonly property int radiusModal: 16
// Animation Durations
readonly property int animFast: 120
readonly property int animNormal: 220
readonly property int animSmooth: 320
}

View File

@@ -0,0 +1 @@
singleton Theme 1.0 Theme.qml

View File

@@ -1,230 +0,0 @@
{ pkgs, ... }:
{
programs.waybar = {
enable = true;
settings = {
mainBar = {
layer = "top";
modules-left = [ "custom/symbol" "cpu" "memory" "keyboard-state" "tray" ];
modules-center = [ "hyprland/workspaces" ];
modules-right = [ "idle_inhibitor" "backlight" "pulseaudio" "group/networks" "battery" "clock" ];
pulseaudio = {
tooltip = false;
scroll-step = 5;
format = "{icon} {volume}%";
format-muted = "󰝟 {volume}%";
on-click-right = "pactl set-sink-mute @DEFAULT_SINK@ toggle";
on-click = "pavucontrol";
format-icons = {
default = [
""
""
""
];
};
};
idle_inhibitor = {
format = "{icon}";
format-icons = {
activated = "";
deactivated = "";
};
};
"custom/network-symbol" = {
format = " ";
tooltip = false;
on-click = "nm-connection-editor";
};
"group/networks" = {
orientation = "inherit";
drawer = {
children-class = "drawer-network";
};
modules = [
"custom/network-symbol"
"network"
];
};
network = {
tooltip = false;
format-wifi = "{ipaddr} ({essid})";
format-ethernet = "{ipaddr}";
};
keyboard-state = {
numlock = true;
capslock = true;
format = {
numlock = "N {icon}";
capslock = "C {icon}";
};
format-icons = {
locked = " ";
unlocked = " ";
};
};
backlight = {
tooltip = false;
format = " {}%";
interval = 1;
on-scroll-up = "brightnessctl set +5%";
on-scroll-down = "brightnessctl set 5%-";
};
battery = {
states = {
good = 95;
warning = 30;
critical = 20;
};
format = "{icon} {capacity}%";
format-charging = " {capacity}%";
format-plugged = " {capacity}%";
format-alt = "{time} {icon}";
format-icons = [
""
""
""
""
""
];
};
tray = {
icon-size = 18;
spacing = 10;
};
clock = {
format = "{:%I:%M %p | %m/%d/%Y}";
};
cpu = {
interval = 15;
format = " {}%";
max-length = 10;
};
memory = {
interval = 30;
format = " {}%";
max-length = 10;
};
"custom/symbol" = {
format = " 󰣇 ";
tooltip = false;
};
"group/workspaces" = {
orientation = "inherit";
drawer = {
children-class = "drawer-workspace";
};
modules = [
"custom/symbol"
"hyprland/workspaces"
];
};
"hyprland/workspaces" = {
disable-scroll = true;
active-only = true;
format = "{name} [ {windows} ]";
window-rewrite-default = "";
format-window-separator = " ";
window-rewrite = {
"class<alacritty>" = "";
"class<foot>" = "";
"class<zathura>" = "";
"class<steam>" = "";
"class<Brave-browser>" = "";
"class<WebCord>" = "";
"class<Signal>" = "";
"class<zoom>" = "";
};
};
};
};
style = ''
* {
font-family: "SF Pro Display", "Font Awesome 6 Free", "JetBrainsMono Nerd Font";
font-size: 16px;
min-height: 10px;
color: #c0caf5;
background: transparent;
}
window#waybar {
background: rgba(255, 255, 255, 0.2);
border-radius: 5px;
}
#keyboard-state,
#pulseaudio,
#backlight,
#clock,
#memory,
#cpu,
#battery,
#custom-symbol,
#custom-network-symbol,
#privacy,
#tray,
#idle_inhibitor,
#workspaces button,
#workspaces button.active {
margin: 5px;
border-radius: 3px;
transition: none;
border-bottom: 3px solid #c0caf5;
}
#keyboard-state:hover,
#pulseaudio:hover,
#backlight:hover,
#clock:hover,
#memory:hover,
#cpu:hover,
#custom-symbol:hover,
#custom-network-symbol:hover,
#privacy:hover,
#tray:hover,
#idle_inhibitor:hover,
#workspaces button:hover {
border-bottom: 3px solid #0dd2e7;
}
#battery.charging,
#battery.plugged {
color: #c3e88d;
border-bottom: 3px solid #c3e88d;
}
#battery.critical:not(.charging) {
color: #ff757f;
border-bottom: 3px solid #ff757f;
}
#workspaces button.active,
#workspaces button.focus {
outline: none;
color: #0dd2e7;
text-shadow: none;
}
'';
};
home.packages = with pkgs; [
pavucontrol
networkmanagerapplet
];
}

88
home/scripts/herdr-picker.sh Executable file
View File

@@ -0,0 +1,88 @@
#!/usr/bin/env bash
# Prevent nested execution if already inside Herdr, tmux, zellij, or running non-interactively
if [ -n "$HERDR" ] || [ -n "$HERDR_SESSION" ] || [ -n "$TMUX" ] || [ -n "$ZELLIJ" ] || [ ! -t 0 ]; then
exec zsh "$@"
fi
# Function to start raw shell
start_plain_shell() {
exec zsh "$@"
}
# If herdr binary is not found, launch zsh directly without producing noisy stdout
if ! command -v herdr &>/dev/null; then
start_plain_shell "$@"
fi
# Fetch active herdr sessions
active_sessions=()
raw_output=$(herdr session list 2>/dev/null)
if [ $? -eq 0 ] && [ -n "$raw_output" ]; then
while IFS= read -r line; do
# Extract first word as session name
sname=$(echo "$line" | awk '{print $1}' | tr -d '*:')
if [ -n "$sname" ] && [ "$sname" != "NAME" ] && [ "$sname" != "Sessions:" ] && [ "$sname" != "No" ]; then
active_sessions+=("$sname")
fi
done <<< "$raw_output"
fi
# Prepare menu options
menu_items=()
menu_items+=("✨ [Create New Session]")
menu_items+=("⚡ [Default Session]")
for s in "${active_sessions[@]}"; do
if [ "$s" != "default" ]; then
menu_items+=("📦 $s")
fi
done
menu_items+=("🐚 [Skip - Plain Shell]")
# Interactive session selector using fzf
if command -v fzf &>/dev/null; then
selected=$(printf '%s\n' "${menu_items[@]}" | fzf \
--height=45% \
--layout=reverse \
--border=rounded \
--prompt="󱓞 Herdr Session > " \
--header="Select Herdr session to attach / create | Esc for plain shell" \
--header-first)
else
echo "=========================================="
echo " HERDR SESSION PICKER "
echo "=========================================="
PS3="Choose an option: "
select selected in "${menu_items[@]}"; do
[ -n "$selected" ] && break
done
fi
case "$selected" in
"✨ [Create New Session]")
echo ""
read -r -p "Enter session name (press Enter for auto-generated name): " s_name
if [ -z "$s_name" ]; then
s_name="workspace-$(date +%m%d-%H%M)"
fi
export HERDR_SESSION="$s_name"
exec herdr session attach "$s_name" 2>/dev/null || exec herdr session new "$s_name" 2>/dev/null || exec herdr "$s_name"
;;
"⚡ [Default Session]")
export HERDR_SESSION="default"
exec herdr
;;
"🐚 [Skip - Plain Shell]"|"")
start_plain_shell "$@"
;;
📦\ *)
s_name="${selected#📦 }"
export HERDR_SESSION="$s_name"
exec herdr session attach "$s_name" 2>/dev/null || exec herdr "$s_name"
;;
*)
start_plain_shell "$@"
;;
esac

View File

@@ -0,0 +1,54 @@
# macOS Catalina Dark Aesthetic Starship Theme (Single-Line)
add_newline = false
scan_timeout = 10
format = "$os$directory$git_branch$git_status$nix_shell$rust$c$python$cmd_duration$character"
[os]
disabled = false
style = "bold #f2f2f7"
symbols = { NixOS = " " }
[directory]
truncation_length = 3
truncate_to_repo = true
style = "bold #0a84ff"
format = "[$path]($style) "
[git_branch]
symbol = " "
style = "bold #bf5af2"
format = "on [$symbol$branch]($style) "
[git_status]
style = "bold #ff453a"
format = "([$all_status$ahead_behind]($style) )"
[nix_shell]
symbol = " "
style = "bold #64d2ff"
format = "via [$symbol$state]($style) "
[rust]
symbol = " "
style = "bold #ff9f0a"
format = "[$symbol($version )]($style)"
[c]
symbol = " "
style = "bold #5e5ce6"
format = "[$symbol($version )]($style)"
[python]
symbol = " "
style = "bold #ffd60a"
format = "[$symbol($version )]($style)"
[cmd_duration]
min_time = 2000
style = "bold #ffd60a"
format = "took [$duration]($style) "
[character]
success_symbol = "[➜](bold #30d158) "
error_symbol = "[➜](bold #ff453a) "

View File

@@ -37,6 +37,12 @@
]; ];
}; };
programs.starship = {
enable = true;
enableZshIntegration = true;
settings = builtins.fromTOML (builtins.readFile ./starship/starship.toml);
};
programs.zsh = { programs.zsh = {
enable = true; enable = true;
enableCompletion = true; enableCompletion = true;
@@ -65,11 +71,6 @@
}; };
plugins = [ plugins = [
{
name = "powerlevel10k";
src = pkgs.zsh-powerlevel10k;
file = "share/zsh-powerlevel10k/powerlevel10k.zsh-theme";
}
{ {
name = "fzf-tab"; name = "fzf-tab";
src = pkgs.zsh-fzf-tab; src = pkgs.zsh-fzf-tab;
@@ -113,141 +114,16 @@
"rebuild-test" = "rebuild test"; "rebuild-test" = "rebuild test";
"rebuild-boot" = "rebuild boot"; "rebuild-boot" = "rebuild boot";
"rebuild-build" = "rebuild build"; "rebuild-build" = "rebuild build";
# Herdr multiplexer aliases
hs = "herdr-picker";
ha = "herdr session attach";
hl = "herdr session list";
hn = "herdr session new";
hk = "herdr session stop";
}; };
initContent = lib.mkMerge [ initContent = builtins.readFile ./zsh/init.zsh;
(lib.mkBefore ''
# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
if [[ -r "''${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-''${(%):-%n}.zsh" ]]; then
source "''${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-''${(%):-%n}.zsh"
fi
'')
(lib.mkAfter ''
# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
# Path configuration
export PATH="$HOME/.local/bin:$HOME/bin:$HOME/.cargo/bin:$PNPM_HOME:$PATH"
if [ -d "$HOME/Tools/xilinx/Vivado/2023.1/bin" ]; then
export PATH="$HOME/Tools/xilinx/Vivado/2023.1/bin:$PATH"
fi
# Miniconda / conda profile hook if installed
if [ -f /opt/miniconda3/etc/profile.d/conda.sh ]; then
source /opt/miniconda3/etc/profile.d/conda.sh
fi
# Environment modules support if available
if (( ''${+functions[module]} )) || [ -f /etc/modules/init/zsh ]; then
[ -f /etc/modules/init/zsh ] && source /etc/modules/init/zsh
module use --append "$HOME/.config/modulefiles" 2>/dev/null || true
fi
# Auto-tmux configuration
use_auto_tmux () {
! ([ -z "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ] || $(pgrep -x "i3" > /dev/null || pgrep -x "sway" > /dev/null || pgrep -x "Hyprland" > /dev/null))
}
if use_auto_tmux; then
export ZSH_TMUX_AUTOSTART=true
export ZSH_TMUX_AUTOCONNECT=false
export ZSH_TMUX_AUTOQUIT=true
else
export ZSH_TMUX_AUTOSTART=false
export ZSH_TMUX_AUTOCONNECT=false
export ZSH_TMUX_AUTOQUIT=false
fi
if [[ -n "$TMUX" ]]; then
tmux-window-name() {
if [ -n "$TMUX_PLUGIN_MANAGER_PATH" ] && [ -f "$TMUX_PLUGIN_MANAGER_PATH/tmux-window-name/scripts/rename_session_windows.py" ]; then
("$TMUX_PLUGIN_MANAGER_PATH/tmux-window-name/scripts/rename_session_windows.py" &)
fi
}
autoload -Uz add-zsh-hook
add-zsh-hook chpwd tmux-window-name
fi
# Custom helper functions
rebuild () {
local action="''${1:-switch}"
shift 2>/dev/null || true
local config_dir="''${FLAKE_CONFIG:-$HOME/NixOS-Configs}"
local host="hades"
local target="$config_dir#$host"
case "$action" in
switch|test|boot)
echo "==> Running: sudo nixos-rebuild $action --flake $target $*"
sudo nixos-rebuild "$action" --flake "$target" "$@"
;;
build|dry-build|dry-run|dry-activate)
local act="$action"
[[ "$action" == "dry-run" ]] && act="dry-build"
echo "==> Running: nixos-rebuild $act --flake $target $*"
nixos-rebuild "$act" --flake "$target" "$@"
;;
help|-h|--help)
echo "Usage: rebuild [switch|test|boot|build|dry-build] [extra nixos-rebuild options]"
echo ""
echo "Commands:"
echo " switch Build, activate, and make default boot entry (default)"
echo " test Build and activate without creating a boot entry"
echo " boot Build and make default boot entry without activating"
echo " build Build system to ./result without activating or sudo"
echo " dry-build Show what would be built/fetched"
;;
*)
echo "==> Running: sudo nixos-rebuild $action --flake $target $*"
sudo nixos-rebuild "$action" --flake "$target" "$@"
;;
esac
}
perlmutter_pass () {
echo -n 'bw master password: '
read -s MASTER_PASS
echo
echo -n 'Copying passkey...'
echo "$(echo "$MASTER_PASS" | bw get password iris.nersc.gov 2>/dev/null)$(echo "$MASTER_PASS" | bw get totp iris.nersc.gov 2>/dev/null)" | wl-copy
echo 'Done.'
}
compiler_explorer () {
docker run -d -p 10240:10240 --name compiler-explorer madduci/docker-compiler-explorer
}
airplay_server () {
uxplay -p 10000 -nh -n "$(hostname)" -restrict -allow 88:66:5A:76:32:F5 -allow C4:AC:AA:76:B7:80
}
zathura_md () {
cat "$1" | pandoc -f markdown -t pdf | zathura -
}
fooocus () {
if [ -f "$HOME/Tools/Fooocus/entry_with_update.py" ]; then
"$HOME/.conda/envs/fooocus/bin/python" "$HOME/Tools/Fooocus/entry_with_update.py"
else
echo "Fooocus not found at $HOME/Tools/Fooocus"
fi
}
# Per-host / system local overrides fallback
if [ -f "$HOME/.config/zsh/$(hostname)/env.sh" ]; then
source "$HOME/.config/zsh/$(hostname)/env.sh"
elif [ -f "$HOME/.zshrc.local" ]; then
source "$HOME/.zshrc.local"
fi
# Fetch / Banner on interactive terminal start
if [[ -o interactive ]] && [ -z "$TMUX" ] && command -v pfetch >/dev/null 2>&1; then
pfetch
fi
'')
];
}; };
home.packages = with pkgs; [ home.packages = with pkgs; [

120
home/zsh/init.zsh Normal file
View File

@@ -0,0 +1,120 @@
# Path configuration
export PATH="$HOME/.local/bin:$HOME/bin:$HOME/.cargo/bin:$PNPM_HOME:$PATH"
if [ -d "$HOME/Tools/xilinx/Vivado/2023.1/bin" ]; then
export PATH="$HOME/Tools/xilinx/Vivado/2023.1/bin:$PATH"
fi
# Miniconda / conda profile hook if installed
if [ -f /opt/miniconda3/etc/profile.d/conda.sh ]; then
source /opt/miniconda3/etc/profile.d/conda.sh
fi
# Environment modules support if available
if (( ${+functions[module]} )) || [ -f /etc/modules/init/zsh ]; then
[ -f /etc/modules/init/zsh ] && source /etc/modules/init/zsh
module use --append "$HOME/.config/modulefiles" 2>/dev/null || true
fi
# Auto-tmux configuration
use_auto_tmux () {
! ([ -z "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ] || $(pgrep -x "i3" > /dev/null || pgrep -x "sway" > /dev/null || pgrep -x "Hyprland" > /dev/null))
}
if use_auto_tmux; then
export ZSH_TMUX_AUTOSTART=true
export ZSH_TMUX_AUTOCONNECT=false
export ZSH_TMUX_AUTOQUIT=true
else
export ZSH_TMUX_AUTOSTART=false
export ZSH_TMUX_AUTOCONNECT=false
export ZSH_TMUX_AUTOQUIT=false
fi
if [[ -n "$TMUX" ]]; then
tmux-window-name() {
if [ -n "$TMUX_PLUGIN_MANAGER_PATH" ] && [ -f "$TMUX_PLUGIN_MANAGER_PATH/tmux-window-name/scripts/rename_session_windows.py" ]; then
("$TMUX_PLUGIN_MANAGER_PATH/tmux-window-name/scripts/rename_session_windows.py" &)
fi
}
autoload -Uz add-zsh-hook
add-zsh-hook chpwd tmux-window-name
fi
# Custom helper functions
rebuild () {
local action="${1:-switch}"
shift 2>/dev/null || true
local config_dir="${FLAKE_CONFIG:-$HOME/NixOS-Configs}"
local host="hades"
local target="$config_dir#$host"
case "$action" in
switch|test|boot)
echo "==> Running: sudo nixos-rebuild $action --flake $target $*"
sudo nixos-rebuild "$action" --flake "$target" "$@"
;;
build|dry-build|dry-run|dry-activate)
local act="$action"
[[ "$action" == "dry-run" ]] && act="dry-build"
echo "==> Running: nixos-rebuild $act --flake $target $*"
nixos-rebuild "$act" --flake "$target" "$@"
;;
help|-h|--help)
echo "Usage: rebuild [switch|test|boot|build|dry-build] [extra nixos-rebuild options]"
echo ""
echo "Commands:"
echo " switch Build, activate, and make default boot entry (default)"
echo " test Build and activate without creating a boot entry"
echo " boot Build and make default boot entry without activating"
echo " build Build system to ./result without activating or sudo"
echo " dry-build Show what would be built/fetched"
;;
*)
echo "==> Running: sudo nixos-rebuild $action --flake $target $*"
sudo nixos-rebuild "$action" --flake "$target" "$@"
;;
esac
}
perlmutter_pass () {
echo -n 'bw master password: '
read -s MASTER_PASS
echo
echo -n 'Copying passkey...'
echo "$(echo "$MASTER_PASS" | bw get password iris.nersc.gov 2>/dev/null)$(echo "$MASTER_PASS" | bw get totp iris.nersc.gov 2>/dev/null)" | wl-copy
echo 'Done.'
}
compiler_explorer () {
docker run -d -p 10240:10240 --name compiler-explorer madduci/docker-compiler-explorer
}
airplay_server () {
uxplay -p 10000 -nh -n "$(hostname)" -restrict -allow 88:66:5A:76:32:F5 -allow C4:AC:AA:76:B7:80
}
zathura_md () {
cat "$1" | pandoc -f markdown -t pdf | zathura -
}
fooocus () {
if [ -f "$HOME/Tools/Fooocus/entry_with_update.py" ]; then
"$HOME/.conda/envs/fooocus/bin/python" "$HOME/Tools/Fooocus/entry_with_update.py"
else
echo "Fooocus not found at $HOME/Tools/Fooocus"
fi
}
# Per-host / system local overrides fallback
if [ -f "$HOME/.config/zsh/$(hostname)/env.sh" ]; then
source "$HOME/.config/zsh/$(hostname)/env.sh"
elif [ -f "$HOME/.zshrc.local" ]; then
source "$HOME/.zshrc.local"
fi
# Fetch / Banner on interactive terminal start
if [[ -o interactive ]] && [ -z "$TMUX" ] && command -v pfetch >/dev/null 2>&1; then
pfetch
fi

View File

@@ -27,7 +27,7 @@
lsof lsof
valgrind valgrind
heaptrack heaptrack
linuxPackages.perf perf
flamegraph flamegraph
# Decompilers, Disassemblers & Binary Analysis # Decompilers, Disassemblers & Binary Analysis