Repository navigation
v4.0.1
What's Changed
- add new banner by @Sandip124 in #86
- Add CodeQL analysis workflow configuration by @Sandip124 in #90
- Expr/avalonia by @Sandip124 in #91
What's New
Battery Monitoring
- Instant charger detection — event-driven architecture using WMI events (Windows) and Darwin notifications (macOS) for immediate plug/unplug response,
with lightweight polling as fallback - Smarter notification rules — full battery alerts only fire when charger is plugged in; unplugging above threshold no longer triggers spurious
notifications - Clear time estimates — "45m to full charge" (charging) / "3h 20m of battery remaining" (discharging) instead of ambiguous "45m remaining"
- Contextual status messages — replaced generic jokes with battery-aware fallbacks like "Charging — estimating time to full..." when OS can't provide
an estimate
Sound System
- Custom sounds library — import your own .wav, .mp3, .m4a, .ogg, .flac, or .aac files; they're copied to the app's data directory and persist across
sessions - Editor's Choice sounds — 6 curated music clips bundled with the app (Rock N Roll, Admonition, Snowy Glow, Legacy)
- Full playback for custom sounds — imported and bundled sounds play once in full instead of being clipped; built-in tones still loop
- Delete imported sounds — remove custom sounds from the library via the X button in the sound picker
DND / Focus Mode
- macOS Tahoe support — DND detection works on macOS 16 via Control Center accessibility fallback
- DND indicator in UI — banner shows between battery info and quick settings when Focus mode is active
- Near real-time monitoring — Darwin notification polling every 5s (zero-cost memory read) with 2-minute fallback
Logging
- Structured logs at every key point: power line changes, battery level changes, notification publish/suppress/deliver decisions, DND suppression state
Code Quality
- Centralized hardcoded paths into Constants.AppName, Constants.AppDataDirectory, Constants.AppTempDirectory
- Centralized asset URIs into AssetUris (Logo48, Logo128, LogoIco, ForAsset, ForSound)
- Sealed 15 non-derived classes for performance
- Refactored high-complexity methods: UpdateCheckIcons, CheckBatteryAndPowerStatus, IsMacDoNotDisturbActive
- Added 1-second regex timeouts across all Regex calls (ReDoS prevention)
- Subprocess commands resolved to absolute paths via Constants.ResolveCommand() (avoids PATH injection)
- Debouncer: exception handling in timer callback + race condition fix (invoke inside lock)
- AppSettings: error paths now call Reset() instead of Save() to properly restore defaults
- Removed dead code: unused logger, no-op event unsubscription, stale IDE mappings
CI/CD
- Fixed signtool not found — locates it from Windows SDK path
- Secrets passed via env: blocks (not expanded in run: blocks)
- Graceful skip when signing secrets aren't configured
- Certificate/keychain cleanup via try/finally and trap EXIT
- Binary validation before signing (fail fast with clear error)
- Post-sign verification (codesign --verify --deep --strict)
- Timestamp URL upgraded to HTTPS
- Version read from csproj via MSBuild (no hardcoded fallback)
- Velopack CLI pinned to 0.0.1298
- Linux builds disabled in CI
- bump-version.sh fixed for macOS (grep/sed compatibility)
Security
- Settings encryption documented accurately: DPAPI on Windows, AES-256-GCM on macOS/Linux
- CustomSoundsLibrary.Import(): extension allowlist, 50MB limit, symlink rejection, atomic write, collision handling
Full Changelog: v3.1.1...v4.0.0