-
Notifications
You must be signed in to change notification settings - Fork 9
share #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds sharing functionality and URL scheme support to Kaset. Users can now share songs, playlists, albums, and artists via the native macOS share sheet, and open songs directly using the kaset:// URL scheme. The PR also removes the ErrorPresenter service and its documentation.
- Implements native macOS sharing for all content types using NSSharingServicePicker
- Adds custom URL scheme (
kaset://) for opening songs from external sources - Removes ErrorPresenter service and documentation
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| Views/macOS/SharedViews/ShareContextMenu.swift | New file providing context menu items for sharing content via NSSharingServicePicker |
| Core/Services/ShareService.swift | Defines Shareable protocol and implements it for Song, Playlist, Album, and Artist with YouTube Music URL generation |
| Core/Services/URLHandler.swift | Parses YouTube Music URLs and custom kaset:// scheme URLs to extract content identifiers |
| App/KasetApp.swift | Integrates URL handling with .onOpenURL modifier to play songs from custom scheme |
| App/Info.plist | Registers kaset:// custom URL scheme with the system |
| Tests/KasetTests/URLHandlerTests.swift | Comprehensive test suite for URL parsing functionality |
| Tests/KasetTests/ShareableTests.swift | Test suite for Shareable protocol implementations |
| Views/macOS/TopSongsView.swift | Adds share context menu item for songs |
| Views/macOS/SearchView.swift | Adds share context menu items for songs, albums, artists, and playlists |
| Views/macOS/QueueView.swift | Adds share context menu item for songs in queue |
| Views/macOS/PlaylistDetailView.swift | Adds share context menu item for playlist tracks |
| Views/macOS/LikedMusicView.swift | Adds share context menu item for liked songs |
| Views/macOS/HomeView.swift | Adds share context menu items for all home section items |
| Views/macOS/ArtistDetailView.swift | Adds share context menu item for artist songs |
| Views/macOS/SharedViews/FavoritesSection.swift | Adds share context menu item for favorite items |
| README.md | Documents new sharing and URL scheme features |
| docs/architecture.md | Removes ErrorPresenter documentation |
| Tests/KasetTests/SwiftTestingHelpers/Tags.swift | Updates service tag documentation to remove ErrorPresenter reference |
| Core/Utilities/DiagnosticsLogger.swift | Adds new logger for app lifecycle and URL handling events |
| Kaset.xcodeproj/project.pbxproj | Updates Xcode project with new files and removes ErrorPresenter |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Divider() | ||
|
|
||
| FavoritesContextMenu.menuItem(for: album, manager: self.favoritesManager) | ||
|
|
Copilot
AI
Dec 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing Divider before ShareContextMenu. For consistency with other menu items in this file (see song and playlist cases), there should be a Divider separating the FavoritesContextMenu from the ShareContextMenu.
| Divider() |
| Divider() | ||
|
|
||
| FavoritesContextMenu.menuItem(for: artist, manager: self.favoritesManager) | ||
|
|
Copilot
AI
Dec 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing Divider before ShareContextMenu. For consistency with other menu items in this file (see song and playlist cases), there should be a Divider separating the FavoritesContextMenu from the ShareContextMenu.
| Divider() |
|
|
||
| FavoritesContextMenu.menuItem(for: album, manager: self.favoritesManager) | ||
|
|
||
| ShareContextMenu.menuItem(for: album) |
Copilot
AI
Dec 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing Divider before ShareContextMenu. For consistency with other menu items in this view (see song and playlist cases), there should be a Divider separating the FavoritesContextMenu from the ShareContextMenu.
|
|
||
| FavoritesContextMenu.menuItem(for: artist, manager: self.favoritesManager) | ||
|
|
||
| ShareContextMenu.menuItem(for: artist) |
Copilot
AI
Dec 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing Divider before ShareContextMenu. For consistency with other menu items in this view (see song and playlist cases), there should be a Divider separating the FavoritesContextMenu from the ShareContextMenu.
| guard let keyWindow = NSApp.keyWindow else { return } | ||
| let windowPoint = keyWindow.convertPoint(fromScreen: mouseLocation) | ||
| let rect = NSRect(origin: windowPoint, size: CGSize(width: 1, height: 1)) | ||
| picker.show(relativeTo: rect, of: keyWindow.contentView!, preferredEdge: .minY) |
Copilot
AI
Dec 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forced unwrapping with the ! operator could cause a crash if contentView is nil. While this is unlikely in typical scenarios, it's better to use optional binding or a guard statement to handle this case safely, especially since the code already checks for window existence.
| let windowPoint = window.convertPoint(fromScreen: mouseLocation) | ||
|
|
||
| // Find the view at this point, or use contentView as fallback | ||
| let targetView = window.contentView?.hitTest(windowPoint) ?? window.contentView! |
Copilot
AI
Dec 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forced unwrapping with the ! operator could cause a crash if contentView is nil. Consider using optional binding or a guard statement with an early return to handle this case safely.
No description provided.