1#!/usr/bin/env bash
2set -euo pipefail
3ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
4source "$ROOT/lib.sh"
5
6#══════════════════════════════════════════════════════════════
7# STATE: macOS System Defaults
8#══════════════════════════════════════════════════════════════
9
10#──────────────────────────────────────────────────────────────
11# Keyboard & Input
12#──────────────────────────────────────────────────────────────
13KEYBOARD_DEFAULTS=(
14 "NSGlobalDomain:NSAutomaticSpellingCorrectionEnabled:bool:false"
15 "NSGlobalDomain:NSAutomaticTextCompletionEnabled:bool:false"
16 "NSGlobalDomain:NSAutomaticInlinePredictionEnabled:bool:false"
17 "NSGlobalDomain:KeyRepeat:int:2"
18 "NSGlobalDomain:InitialKeyRepeat:int:15"
19 "NSGlobalDomain:ApplePressAndHoldEnabled:bool:false"
20 "NSGlobalDomain:NSAutomaticQuoteSubstitutionEnabled:bool:false"
21 "NSGlobalDomain:NSAutomaticDashSubstitutionEnabled:bool:false"
22 "NSGlobalDomain:NSAutomaticCapitalizationEnabled:bool:false"
23 "NSGlobalDomain:NSAutomaticPeriodSubstitutionEnabled:bool:false"
24)
25
26#──────────────────────────────────────────────────────────────
27# Dock
28#──────────────────────────────────────────────────────────────
29DOCK_DEFAULTS=(
30 "com.apple.dock:autohide:bool:true"
31 "com.apple.dock:magnification:bool:true"
32 "com.apple.dock:largesize:float:64"
33 "com.apple.dock:tilesize:int:48"
34 "com.apple.dock:orientation:string:left"
35 "com.apple.dock:autohide-delay:float:0"
36 "com.apple.dock:autohide-time-modifier:float:0.15"
37 "com.apple.dock:mru-spaces:bool:false"
38 "com.apple.dock:show-recents:bool:false"
39 "com.apple.dock:appswitcher-all-displays:bool:true"
40)
41
42#──────────────────────────────────────────────────────────────
43# Trackpad
44#──────────────────────────────────────────────────────────────
45TRACKPAD_DEFAULTS=(
46 "com.apple.driver.AppleBluetoothMultitouch.trackpad:Clicking:bool:true"
47 "com.apple.AppleMultitouchTrackpad:Clicking:bool:true"
48 "NSGlobalDomain:com.apple.mouse.tapBehavior:int:1"
49 "com.apple.driver.AppleBluetoothMultitouch.trackpad:TrackpadRightClick:int:1"
50 "com.apple.AppleMultitouchTrackpad:TrackpadRightClick:int:1"
51)
52
53#──────────────────────────────────────────────────────────────
54# Finder
55#──────────────────────────────────────────────────────────────
56FINDER_DEFAULTS=(
57 "com.apple.finder:AppleShowAllFiles:bool:true"
58 "com.apple.systempreferences:AppleShowAllFiles:bool:true"
59 "NSGlobalDomain:AppleShowAllExtensions:bool:true"
60 "com.apple.finder:ShowPathbar:bool:true"
61 "com.apple.finder:ShowStatusBar:bool:true"
62 "com.apple.finder:_FXSortFoldersFirst:bool:true"
63 "com.apple.finder:_FXSortFoldersFirstOnDesktop:bool:true"
64 "com.apple.finder:FXPreferredViewStyle:string:Nlsv"
65 "com.apple.finder:FXDefaultSearchScope:string:SCcf"
66 "com.apple.desktopservices:DSDontWriteNetworkStores:bool:true"
67 "com.apple.desktopservices:DSDontWriteUSBStores:bool:true"
68 "com.apple.finder:FXEnableExtensionChangeWarning:bool:false"
69)
70
71#──────────────────────────────────────────────────────────────
72# Window Manager
73#──────────────────────────────────────────────────────────────
74WINDOW_MANAGER_DEFAULTS=(
75 "com.apple.WindowManager:StandardHideWidgets:bool:true"
76 "com.apple.WindowManager:StageManagerHideWidgets:bool:true"
77 "com.apple.WindowManager:EnableStandardClickToShowDesktop:bool:false"
78)
79
80#──────────────────────────────────────────────────────────────
81# Lock Screen
82#──────────────────────────────────────────────────────────────
83# Message displayed on lock screen (e.g., "If found, contact: Name - Phone/Email")
84# Leave empty to disable lock screen message
85LOCKSCREEN_MESSAGE="PROPERTY OF TORBEN HAACK.\nIF FOUND CONTACT 128n@ipv4.8shield.net"
86
87#──────────────────────────────────────────────────────────────
88# Special Actions (non-defaults commands)
89#──────────────────────────────────────────────────────────────
90SPOTLIGHT_SHORTCUTS_TO_DISABLE=(64 65)
91ENABLE_TOUCHID_SUDO=true
92UNHIDE_USER_LIBRARY=true
93
94#──────────────────────────────────────────────────────────────
95# Symlinks
96#──────────────────────────────────────────────────────────────
97SYMLINKS=(
98 "$HOME/Library/CloudStorage/ProtonDrive-*:$HOME/ProtonDrive"
99)
100
101#══════════════════════════════════════════════════════════════
102# LOGIC: Idempotent application of defaults
103#══════════════════════════════════════════════════════════════
104
105apply_defaults() {
106 local -n array=$1
107 for entry in "${array[@]}"; do
108 IFS=':' read -r domain key type value <<< "$entry"
109 defaults write "$domain" "$key" "-$type" "$value"
110 done
111}
112
113log "Applying macOS defaults"
114
115apply_defaults KEYBOARD_DEFAULTS
116apply_defaults DOCK_DEFAULTS
117apply_defaults TRACKPAD_DEFAULTS
118apply_defaults FINDER_DEFAULTS
119apply_defaults WINDOW_MANAGER_DEFAULTS
120
121# Unhide ~/Library
122if [[ "$UNHIDE_USER_LIBRARY" == "true" ]]; then
123 chflags nohidden ~/Library
124fi
125
126# Disable Spotlight shortcuts
127for id in "${SPOTLIGHT_SHORTCUTS_TO_DISABLE[@]}"; do
128 /usr/libexec/PlistBuddy -c \
129 "Set :AppleSymbolicHotKeys:$id:enabled false" \
130 ~/Library/Preferences/com.apple.symbolichotkeys.plist >/dev/null 2>&1 || true
131done
132
133# Create symlinks
134for entry in "${SYMLINKS[@]}"; do
135 IFS=':' read -r source target <<< "$entry"
136
137 # Expand glob pattern
138 shopt -s nullglob
139 expanded_sources=($source)
140 shopt -u nullglob
141
142 if [[ ${#expanded_sources[@]} -eq 0 ]]; then
143 log "Skipping symlink (source not found): $source"
144 continue
145 fi
146
147 actual_source="${expanded_sources[0]}"
148
149 # Check if symlink already correct
150 if [[ -L "$target" ]]; then
151 current=$(readlink "$target")
152 if [[ "$current" == "$actual_source" ]]; then
153 log "Symlink already correct: $target"
154 continue
155 fi
156 rm "$target"
157 elif [[ -e "$target" ]]; then
158 warn "Target exists but not a symlink: $target (skipping)"
159 continue
160 fi
161
162 log "Creating symlink: $target -> $actual_source"
163 ln -s "$actual_source" "$target"
164done
165
166# Enable TouchID for sudo
167if [[ "$ENABLE_TOUCHID_SUDO" == "true" ]]; then
168 if [[ -f /etc/pam.d/sudo_local.template ]]; then
169 log "Enabling TouchID for sudo"
170 sudo cp -f /etc/pam.d/sudo_local.template /etc/pam.d/sudo_local
171 sudo sed -i '' 's/^[[:space:]]*#\([[:space:]]*auth[[:space:]]\+sufficient[[:space:]]\+pam_tid\.so.*\)$/\1/' /etc/pam.d/sudo_local
172 else
173 warn "sudo_local.template not found - cannot enable TouchID for sudo"
174 fi
175fi
176
177# Set lock screen message
178if [[ -n "$LOCKSCREEN_MESSAGE" ]]; then
179 current=$(sudo defaults read /Library/Preferences/com.apple.loginwindow LoginwindowText 2>/dev/null || echo "")
180 if [[ "$current" != "$LOCKSCREEN_MESSAGE" ]]; then
181 log "Setting lock screen message"
182 sudo defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "$LOCKSCREEN_MESSAGE"
183 else
184 log "Lock screen message already set"
185 fi
186else
187 # Remove lock screen message if variable is empty
188 if sudo defaults read /Library/Preferences/com.apple.loginwindow LoginwindowText >/dev/null 2>&1; then
189 log "Removing lock screen message"
190 sudo defaults delete /Library/Preferences/com.apple.loginwindow LoginwindowText
191 fi
192fi
193
194reload_services
195log "macOS defaults applied"