feat(desktop-ui): implement a desktop ui for appfaders#5
Merged
Conversation
Extract shared types and functionality from AppFaders into a dedicated library target for reuse by desktop UI and future TUI implementations.
Move DriverBridge, DriverError, AppAudioMonitor, TrackedApp, and HelperProtocol from AppFaders to AppFadersCore shared library. Update Package.swift to add AppFadersCore dependency and update test imports.
Replace CLI entry point with proper macOS menu bar application architecture: - AppFadersApp: @main entry using NSApplication.run() pattern for proper delegate lifecycle management - AppDelegate: NSApplicationDelegate with .accessory activation policy, AudioOrchestrator integration, and graceful termination handling - MenuBarController: NSStatusItem stub with SF Symbol icon (slider.vertical.3) This establishes the foundation for the NSPanel-based volume control UI.
Add left-click panel toggle and right-click context menu to the menu bar status item. The context menu provides "Open" and "Quit" options. Panel show/hide methods are placeholders that log actions until the panel UI is implemented in subsequent tasks.
- Configure NSPanel as floating, non-activating panel with borderless style - Add PlaceholderPanelView with basic styling and dark/light mode support - Wire panel show/hide to MenuBarController toggle methods
Position panel below menu bar status item with screen bounds checking. Add event monitors to dismiss panel on click outside or Escape key press.
- Custom SwiftUI slider matching Pencil design specs. - Large (300px) and small (200px) variants with DragGesture control. - Asset catalog provides light/dark mode colors for all UI components.
- SF Symbol icons: speaker.wave.2.fill / speaker.slash.fill - asset catalog colors for automatic light/dark mode adaptation.
- Panel chrome with title, settings icon placeholder, version label, and quit button. - Uses asset catalog colors for light/dark mode.
- header row with "MASTER OUTPUT" label and percentage display. - slider row with large VolumeSlider and MuteButton.
- added volume control row with icon, name/percentage display, small VolumeSlider, and MuteButton. - added memberwise init for AppVolumeState to support previews.
- combines HeaderView, dividers, MasterVolumeView, app rows, and FooterView. - added panel styling - uses @bindable for AppState with async volume bindings.
- asset catalog wasn't working and I don't have patience to keep debugging right now.
…ix panel visibility Asset catalogs aren't compiled by SPM's .process() directive, causing runtime "No color named" errors. Replace with AppColors enum using programmatic light/dark mode support. - Remove Colors.xcassets and Resources directory - Update all views to use AppColors instead of Color(bundle:) - Set hidesOnDeactivate=false on NSPanel (required for menu bar apps) - Wire PanelView to MenuBarController with AppState - Remove unused PlaceholderPanelView
- added filtering for AppAudioMonitor with .regular to make list sensible.
- moved list population from async start() to init() so list pops faster.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Phase 3 of AppFaders - the desktop UI implementation. Transforms the app from a CLI prototype into a proper macOS menu bar application with a floating panel for volume control.
Changes Made
New Targets
AppFadersCore- shared library with TrackedApp, DriverBridge, AppAudioMonitor, HostProtocolApp Shell
AppFadersApp.swift+AppDelegate.swift- proper macOS app lifecycle with.accessoryactivation policyMenuBarController.swift- NSStatusItem + NSPanel management, click-outside/escape dismissState Management
AppState.swift-@Observablestate container for SwiftUI, per-app + master volume controlDeviceManager.swift- system volume control via CAAudioHardwareUI Components
VolumeSlider.swift- custom slider with filled track, large/small variantsMuteButton.swift- speaker/muted icon toggleHeaderView.swift/FooterView.swift- panel chromeMasterVolumeView.swift- system volume sectionAppRowView.swift- per-app volume row with iconPanelView.swift- root composition with scrollable app listTheme
AppColors.swift- programmatic light/dark mode colors (asset catalog with SPM was giving me a headache, so I gave up for now)Filtering
NSRunningApplication.activationPolicy == .regular(matches BackgroundMusic approach)Tests
AppStateTests.swift- unit tests for AppVolumeStateDocs
future-integration-tests.md- recommendations for protocol-based mocking to enable AppState testingTesting Notes
swift buildthen.build/debug/AppFadersto test