@@ -244,6 +244,118 @@ Manages user-curated Favorites section on Home view:
244244- ` Views/macOS/SharedViews/FavoritesSection.swift ` — Horizontal scrolling UI
245245- ` Views/macOS/SharedViews/FavoritesContextMenu.swift ` — Shared context menu items
246246
247+ ### NotificationService
248+
249+ ** File** : ` Core/Services/Notification/NotificationService.swift `
250+
251+ Posts local notifications when the current track changes:
252+
253+ - Observes ` PlayerService.currentTrack ` for changes
254+ - Posts silent alerts with track title and artist
255+ - Respects user preference via ` SettingsManager.showNowPlayingNotifications `
256+ - Requests notification authorization on init
257+
258+ ** Usage** : Instantiated in ` MainWindow ` and kept alive for app lifetime.
259+
260+ ### NetworkMonitor
261+
262+ ** File** : ` Core/Services/NetworkMonitor.swift `
263+
264+ Monitors network connectivity using ` NWPathMonitor ` :
265+
266+ | Property | Type | Description |
267+ | ----------| ------| -------------|
268+ | ` isConnected ` | ` Bool ` | Whether network is available |
269+ | ` isExpensive ` | ` Bool ` | Cellular or hotspot connection |
270+ | ` isConstrained ` | ` Bool ` | Low Data Mode enabled |
271+ | ` interfaceType ` | ` InterfaceType ` | WiFi, cellular, wired, etc. |
272+ | ` statusDescription ` | ` String ` | Human-readable status |
273+
274+ ** Note** : Uses ` DispatchQueue ` for ` NWPathMonitor ` callbacks (no async/await API from Apple).
275+
276+ ### SettingsManager
277+
278+ ** File** : ` Core/Services/SettingsManager.swift `
279+
280+ Manages user preferences persisted via ` UserDefaults ` :
281+
282+ | Setting | Type | Default | Description |
283+ | ---------| ------| ---------| -------------|
284+ | ` showNowPlayingNotifications ` | ` Bool ` | ` true ` | Track change notifications |
285+ | ` defaultLaunchPage ` | ` LaunchPage ` | ` .home ` | Initial page on app launch |
286+ | ` hapticFeedbackEnabled ` | ` Bool ` | ` true ` | Force Touch feedback |
287+ | ` rememberPlaybackSettings ` | ` Bool ` | ` true ` | Persist shuffle/repeat state |
288+
289+ ** LaunchPage Options** : Home, Explore, Charts, Moods & Genres, New Releases, Liked Music, Playlists, Last Used
290+
291+ ### ShareService
292+
293+ ** File** : ` Core/Services/ShareService.swift `
294+
295+ Provides share sheet functionality via the ` Shareable ` protocol:
296+
297+ ``` swift
298+ protocol Shareable {
299+ var shareTitle: String { get }
300+ var shareSubtitle: String ? { get }
301+ var shareURL: URL? { get }
302+ }
303+ ```
304+
305+ ** Conforming Types** : ` Song ` , ` Playlist ` , ` Album ` , ` Artist `
306+
307+ ** Share Text Format** : "Title by Artist" or just "Title" for artists.
308+
309+ ### SongLikeStatusManager
310+
311+ ** File** : ` Core/Services/SongLikeStatusManager.swift `
312+
313+ Caches and syncs like/dislike status for songs:
314+
315+ | Method | Description |
316+ | --------| -------------|
317+ | ` status(for:) ` | Get cached status for video ID or Song |
318+ | ` isLiked(_:) ` | Check if song is liked |
319+ | ` setStatus(_:for:) ` | Update cache (optimistic update) |
320+ | ` rate(_:status:) ` | Sync rating with YouTube Music API |
321+
322+ ** Optimistic Updates** : Updates cache immediately, rolls back on API failure.
323+
324+ ### URLHandler
325+
326+ ** File** : ` Core/Services/URLHandler.swift `
327+
328+ Parses YouTube Music and custom ` kaset:// ` URLs:
329+
330+ | URL Pattern | ParsedContent |
331+ | -------------| ---------------|
332+ | ` music.youtube.com/watch?v=xxx ` | ` .song(videoId:) ` |
333+ | ` music.youtube.com/playlist?list=xxx ` | ` .playlist(id:) ` |
334+ | ` music.youtube.com/browse/MPRExxx ` | ` .album(id:) ` |
335+ | ` music.youtube.com/channel/UCxxx ` | ` .artist(id:) ` |
336+ | ` kaset://play?v=xxx ` | ` .song(videoId:) ` |
337+ | ` kaset://playlist?list=xxx ` | ` .playlist(id:) ` |
338+ | ` kaset://album?id=xxx ` | ` .album(id:) ` |
339+ | ` kaset://artist?id=xxx ` | ` .artist(id:) ` |
340+
341+ ** Usage** : Called from ` KasetApp.onOpenURL ` to handle deep links.
342+
343+ ### UpdaterService
344+
345+ ** File** : ` Core/Services/UpdaterService.swift `
346+
347+ Manages application updates via Sparkle framework:
348+
349+ | Property | Type | Description |
350+ | ----------| ------| -------------|
351+ | ` automaticChecksEnabled ` | ` Bool ` | Auto-check on launch |
352+ | ` canCheckForUpdates ` | ` Bool ` | Whether check is allowed now |
353+
354+ ** Key Methods** :
355+ - ` checkForUpdates() ` — Manually trigger update check
356+
357+ See [ ADR-0007: Sparkle Auto-Updates] ( adr/0007-sparkle-auto-updates.md ) for design details.
358+
247359### AppDelegate
248360
249361** File** : ` App/AppDelegate.swift `
@@ -418,10 +530,97 @@ DiagnosticsLogger.player.info("Loading video: \(videoId)")
418530DiagnosticsLogger.auth .error (" Cookie extraction failed" )
419531```
420532
421- ** Categories** : ` .player ` , ` .auth ` , ` .api ` , ` .webKit ` , ` .haptic `
533+ ** Categories** : ` .player ` , ` .auth ` , ` .api ` , ` .webKit ` , ` .haptic ` , ` .notification `
422534
423535** Levels** : ` .debug ` , ` .info ` , ` .warning ` , ` .error `
424536
537+ ## Utilities
538+
539+ The ` Core/Utilities/ ` folder contains shared helper components.
540+
541+ ### ImageCache
542+
543+ ** File** : ` Core/Utilities/ImageCache.swift `
544+
545+ Thread-safe actor with memory and disk caching:
546+
547+ | Feature | Description |
548+ | ---------| -------------|
549+ | Memory cache | 200 items, 50MB limit via ` NSCache ` |
550+ | Disk cache | 200MB limit with LRU eviction |
551+ | Downsampling | Images resized to display size before caching |
552+ | Prefetch | Structured cancellation for SwiftUI ` .task ` lifecycle |
553+
554+ ** Key Methods** :
555+ - ` image(for:targetSize:) ` — Fetch and cache image
556+ - ` prefetch(urls:targetSize:maxConcurrent:) ` — Batch prefetch for lists
557+
558+ ### ColorExtractor
559+
560+ ** File** : ` Core/Utilities/ColorExtractor.swift `
561+
562+ Extracts dominant colors from album art for dynamic theming:
563+
564+ - Uses ` CIAreaAverage ` filter for color extraction
565+ - Caches extracted colors to avoid repeated processing
566+ - Used by ` AccentBackground ` for gradient overlays
567+
568+ ### AnimationConfiguration
569+
570+ ** File** : ` Core/Utilities/AnimationConfiguration.swift `
571+
572+ Standardized animation timing for consistent motion design:
573+
574+ | Animation | Duration | Curve | Used For |
575+ | -----------| ----------| -------| ----------|
576+ | ` .standard ` | 0.25s | ` .easeInOut ` | General transitions |
577+ | ` .quick ` | 0.15s | ` .easeOut ` | Button feedback |
578+ | ` .slow ` | 0.4s | ` .easeInOut ` | Panel reveals |
579+
580+ ### AccessibilityIdentifiers
581+
582+ ** File** : ` Core/Utilities/AccessibilityIdentifiers.swift `
583+
584+ Centralized UI test identifiers organized by feature:
585+
586+ ``` swift
587+ enum AccessibilityID {
588+ enum Player { static let playButton = " player.playButton" }
589+ enum Queue { static let container = " queue.container" }
590+ // ...
591+ }
592+ ```
593+
594+ ** Benefits** : Prevents string duplication, enables IDE autocomplete in tests.
595+
596+ ### IntelligenceModifier
597+
598+ ** File** : ` Core/Utilities/IntelligenceModifier.swift `
599+
600+ SwiftUI modifier to hide AI features when unavailable:
601+
602+ ``` swift
603+ .requiresIntelligence () // Hides view if Apple Intelligence unavailable
604+ ```
605+
606+ Checks ` FoundationModelsService.shared.isAvailable ` and applies opacity/disabled state.
607+
608+ ### RetryPolicy
609+
610+ ** File** : ` Core/Utilities/RetryPolicy.swift `
611+
612+ Exponential backoff for network retries:
613+
614+ ``` swift
615+ try await RetryPolicy.execute (
616+ maxAttempts : 3 ,
617+ initialDelay : .seconds (1 ),
618+ shouldRetry : { ($0 as? YTMusicError)? .isRetryable ?? false }
619+ ) {
620+ try await client.fetchData ()
621+ }
622+ ```
623+
425624## Performance Guidelines
426625
427626This section documents performance patterns and optimizations used throughout the codebase.
@@ -625,6 +824,41 @@ User Input (natural language)
625824| ` AIErrorHandler ` | ` Core/Services/AI/ ` | User-friendly error messages |
626825| ` RequiresIntelligenceModifier ` | ` Core/Utilities/ ` | Hide AI features when unavailable |
627826
827+ ### AI Tools
828+
829+ Tools ground AI responses in real data from the YouTube Music catalog, preventing hallucination.
830+
831+ ** MusicSearchTool** (` Core/Services/AI/Tools/MusicSearchTool.swift ` )
832+
833+ Searches the YouTube Music catalog for songs, artists, and albums:
834+
835+ ``` swift
836+ @Generable
837+ struct MusicSearchResult {
838+ let songs: [SongResult]
839+ let artists: [ArtistResult]
840+ let albums: [AlbumResult]
841+ }
842+ ```
843+
844+ ** QueueTool** (` Core/Services/AI/Tools/QueueTool.swift ` )
845+
846+ Provides access to the current playback queue for AI-driven queue management:
847+
848+ - Returns current queue contents
849+ - Used by ` QueueIntent ` for natural language queue manipulation
850+ - Enables commands like "remove duplicates" or "play upbeat songs next"
851+
852+ ### @Generable Models
853+
854+ Type-safe structured outputs for AI responses:
855+
856+ | Model | File | Purpose |
857+ | -------| ------| ---------|
858+ | ` MusicIntent ` | ` Core/Models/AI/MusicIntent.swift ` | Parsed user commands (play, pause, search, etc.) |
859+ | ` LyricsSummary ` | ` Core/Models/AI/LyricsSummary.swift ` | Lyrics explanation with themes and mood |
860+ | ` PlaylistChanges ` | ` Core/Models/AI/PlaylistChanges.swift ` | Queue refinement operations |
861+
628862### AI Features
629863
630864| Feature | Trigger | Model Used |
@@ -642,6 +876,85 @@ User Input (natural language)
6428764 . ** Graceful Degradation** : Use ` .requiresIntelligence() ` modifier to hide unavailable features.
6438775 . ** Error Handling** : Use ` AIErrorHandler ` for user-friendly messages.
644878
879+ ## UI Components
880+
881+ This section documents key SwiftUI views and their integration patterns.
882+
883+ ### QueueView
884+
885+ ** File** : ` Views/macOS/QueueView.swift `
886+
887+ Right sidebar panel displaying the playback queue:
888+
889+ - Shows "Up Next" header with shuffle/clear actions
890+ - Displays queue items with drag-to-reorder support
891+ - AI-powered "Refine" button for natural language queue editing
892+ - Uses ` .glassEffect(.regular.interactive()) ` with ` .glassEffectTransition(.materialize) `
893+
894+ ** Integration** : Toggled via ` PlayerService.showQueue ` , placed outside ` NavigationSplitView ` in ` MainWindow ` .
895+
896+ ### LyricsView
897+
898+ ** File** : ` Views/macOS/LyricsView.swift `
899+
900+ Right sidebar panel displaying song lyrics:
901+
902+ - Fetches lyrics via ` YTMusicClient.getLyrics(videoId:) `
903+ - "Explain" button triggers AI-powered ` LyricsSummary ` generation
904+ - Scrollable text with synchronized highlighting (when available)
905+ - Width: 280px, animated show/hide
906+
907+ ** Integration** : Toggled via ` PlayerService.showLyrics ` , persists across all navigation states.
908+
909+ ### CommandBarView
910+
911+ ** File** : ` Views/macOS/CommandBarView.swift `
912+
913+ Spotlight-style command palette triggered by ⌘K:
914+
915+ - Natural language input parsed via ` MusicIntent `
916+ - Shows suggestions and action previews
917+ - Supports commands: play, pause, skip, search, queue management
918+ - Floating overlay with glass effect
919+
920+ ** Trigger** : ` @Environment(\.showCommandBar) ` environment key.
921+
922+ ### ToastView
923+
924+ ** File** : ` Views/macOS/ToastView.swift `
925+
926+ Temporary notification overlay for user feedback:
927+
928+ | Toast Type | Duration | Purpose |
929+ | ------------| ----------| ---------|
930+ | Success | 2s | Action completed (e.g., "Added to library") |
931+ | Error | 3s | Action failed with message |
932+ | Info | 2s | Informational feedback |
933+
934+ ** Usage** : Managed via environment or direct state binding.
935+
936+ ### SharedViews
937+
938+ ** Directory** : ` Views/macOS/SharedViews/ `
939+
940+ Reusable components used across the app:
941+
942+ | Component | Purpose |
943+ | -----------| ---------|
944+ | ` ErrorView ` | Standardized error display with retry button |
945+ | ` LoadingView ` | Skeleton loading states |
946+ | ` SkeletonView ` | Shimmer placeholder for loading content |
947+ | ` EqualizerView ` | Animated bars for "now playing" indicator |
948+ | ` HomeSectionItemCard ` | Card component for carousel items |
949+ | ` InteractiveCardStyle ` | Hover/press effects for cards |
950+ | ` NavigationDestinationsModifier ` | Centralized navigation destination handling |
951+ | ` ShareContextMenu ` | Context menu for sharing content |
952+ | ` StartRadioContextMenu ` | Context menu for starting radio/mix |
953+ | ` FavoritesSection ` | Horizontal scrolling favorites row |
954+ | ` FavoritesContextMenu ` | Context menu for favorites management |
955+ | ` SongActionsHelper ` | Common song action handlers |
956+ | ` AnimationModifiers ` | Reusable animation view modifiers |
957+
645958### PlayerBar
646959
647960** File** : ` Views/macOS/PlayerBar.swift `
0 commit comments