Skip to content

Commit 3accf86

Browse files
committed
cleanup
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
1 parent e2d61ea commit 3accf86

12 files changed

+31
-86
lines changed

Core/Models/Artist.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ struct Artist: Identifiable, Codable, Hashable, Sendable {
1313
self.name = name
1414
self.thumbnailURL = thumbnailURL
1515
}
16+
17+
/// Whether this artist has a valid navigable ID (not a generated UUID).
18+
/// YouTube Music artist IDs are channel IDs like "UCxxxxxxx" and don't contain hyphens.
19+
var hasNavigableId: Bool {
20+
!self.id.isEmpty && !self.id.contains("-")
21+
}
1622
}
1723

1824
extension Artist {

Core/Services/AI/FoundationModelsService.swift

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,6 @@ import FoundationModels
33
import Observation
44
import os
55

6-
// MARK: - AISessionType
7-
8-
/// Defines the type of AI session to create, each optimized for specific use cases.
9-
///
10-
/// Session types help organize the code and provide semantic meaning,
11-
/// but note that Apple's Foundation Models framework does not expose
12-
/// temperature control in macOS 26. All sessions use the system default.
13-
@available(macOS 26.0, *)
14-
enum AISessionType: String, CaseIterable, Sendable {
15-
/// Quick command parsing (play, skip, queue, etc.)
16-
/// Best for predictable structured output.
17-
case command
18-
19-
/// Creative analysis (lyrics explanation, recommendations)
20-
/// Best for more insightful, varied responses.
21-
case analysis
22-
23-
/// Multi-turn conversation (future use)
24-
/// Best for natural dialogue.
25-
case conversational
26-
27-
/// Human-readable description for logging and debugging.
28-
var description: String {
29-
switch self {
30-
case .command:
31-
"Command parsing (structured output)"
32-
case .analysis:
33-
"Creative analysis (insightful responses)"
34-
case .conversational:
35-
"Conversational (multi-turn dialogue)"
36-
}
37-
}
38-
}
39-
406
// MARK: - FoundationModelsService
417

428
/// Service for managing Apple Foundation Models integration.
@@ -208,26 +174,6 @@ final class FoundationModelsService {
208174
)
209175
}
210176

211-
// MARK: - Legacy Session Creation (Deprecated)
212-
213-
/// Creates a new language model session for a given task.
214-
/// - Parameter instructions: System instructions for the session.
215-
/// - Returns: A configured LanguageModelSession, or nil if unavailable.
216-
@available(*, deprecated, message: "Use createAnalysisSession or createCommandSession for better optimization")
217-
func createSession(instructions: String) -> LanguageModelSession? {
218-
self.createAnalysisSession(instructions: instructions)
219-
}
220-
221-
/// Creates a session with tool access for grounded responses.
222-
/// - Parameters:
223-
/// - instructions: System instructions for the session.
224-
/// - tools: Tools the model can use during generation.
225-
/// - Returns: A configured LanguageModelSession with tools, or nil if unavailable.
226-
@available(*, deprecated, message: "Use createCommandSession for tool-based sessions")
227-
func createSession(instructions: String, tools: [any Tool]) -> LanguageModelSession? {
228-
self.createCommandSession(instructions: instructions, tools: tools)
229-
}
230-
231177
/// Clears any cached session state.
232178
/// This can help if the model gets into a bad state.
233179
func clearContext() {

Core/ViewModels/ArtistDetailViewModel.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ final class ArtistDetailViewModel {
1515
/// Whether a subscription operation is in progress.
1616
private(set) var isSubscribing: Bool = false
1717

18+
/// Error message from subscription toggle (nil if no error).
19+
private(set) var subscriptionError: String?
20+
1821
/// Whether to show all songs instead of limited preview.
1922
var showAllSongs: Bool = false
2023

@@ -94,6 +97,7 @@ final class ArtistDetailViewModel {
9497
}
9598

9699
self.isSubscribing = true
100+
self.subscriptionError = nil
97101
defer { isSubscribing = false }
98102

99103
do {
@@ -107,6 +111,7 @@ final class ArtistDetailViewModel {
107111
self.logger.info("Subscribed to artist: \(detail.name)")
108112
}
109113
} catch {
114+
self.subscriptionError = "Failed to update subscription. Please try again."
110115
self.logger.error("Failed to toggle subscription: \(error.localizedDescription)")
111116
}
112117
}

Tests/KasetTests/FoundationModelsServiceTests.swift

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -126,28 +126,3 @@ struct FoundationModelsServiceTests {
126126
service.clearContext()
127127
}
128128
}
129-
130-
// MARK: - AISessionTypeExtendedTests
131-
132-
@available(macOS 26.0, *)
133-
@Suite("AISessionType Extended", .tags(.api))
134-
struct AISessionTypeExtendedTests {
135-
@Test(
136-
"All session types have descriptions",
137-
arguments: [
138-
AISessionType.command,
139-
AISessionType.analysis,
140-
AISessionType.conversational,
141-
]
142-
)
143-
func allSessionTypesHaveDescriptions(type: AISessionType) {
144-
let description = type.description
145-
#expect(!description.isEmpty)
146-
}
147-
148-
@Test("AISessionType is CaseIterable")
149-
func sessionTypeIsCaseIterable() {
150-
let allCases = AISessionType.allCases
151-
#expect(allCases.count == 3)
152-
}
153-
}

Tests/KasetTests/PlayerServiceTests.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ struct PlayerServiceTests {
99
var playerService: PlayerService
1010

1111
init() {
12+
// Reset UserDefaults to ensure clean initial state for tests
13+
UserDefaults.standard.removeObject(forKey: "playerVolume")
14+
UserDefaults.standard.removeObject(forKey: "playerVolumeBeforeMute")
1215
self.playerService = PlayerService()
1316
}
1417

Tests/KasetTests/SearchResponseTests.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,12 @@ struct SearchResponseTests {
8282
#expect(item.subtitle == "Album Artist")
8383
}
8484

85-
@Test("Artist result item subtitle")
85+
@Test("Artist result item subtitle is nil")
8686
func artistResultItemSubtitle() {
8787
let artist = Artist(id: "1", name: "Artist Name")
8888
let item = SearchResultItem.artist(artist)
89-
#expect(item.subtitle == "Artist")
89+
// Artist subtitle is nil because resultType already shows "Artist"
90+
#expect(item.subtitle == nil)
9091
}
9192

9293
@Test("Playlist result item subtitle")

Views/macOS/CommandBarView.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ struct CommandBarView: View {
7171
.foregroundStyle(.secondary)
7272
}
7373
.buttonStyle(.plain)
74+
.accessibilityLabel("Clear input")
7475
}
7576
}
7677
.padding(.horizontal, 16)

Views/macOS/LikedMusicView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ struct LikedMusicView: View {
276276
Divider()
277277

278278
// Go to Artist - show first artist with valid ID
279-
if let artist = song.artists.first(where: { !$0.id.isEmpty && $0.id != UUID().uuidString }) {
279+
if let artist = song.artists.first(where: { $0.hasNavigableId }) {
280280
NavigationLink(value: artist) {
281281
Label("Go to Artist", systemImage: "person")
282282
}

Views/macOS/LyricsView.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ struct LyricsView: View {
8787
.buttonStyle(.plain)
8888
.foregroundStyle(self.showExplanation ? .purple : .secondary)
8989
.help("Explain lyrics with AI")
90+
.accessibilityLabel(self.showExplanation ? "Hide lyrics explanation" : "Explain lyrics with AI")
9091
.requiresIntelligence()
9192
.disabled(self.isExplaining)
9293
}

Views/macOS/PlaylistDetailView.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ struct PlaylistDetailView: View {
329329
Divider()
330330

331331
// Go to Artist - show first artist with valid ID
332-
if let artist = track.artists.first(where: { !$0.id.isEmpty && $0.id != UUID().uuidString }) {
332+
if let artist = track.artists.first(where: { $0.hasNavigableId }) {
333333
NavigationLink(value: artist) {
334334
Label("Go to Artist", systemImage: "person")
335335
}
@@ -487,6 +487,7 @@ private struct RefinePlaylistSheet: View {
487487
.foregroundStyle(.secondary)
488488
}
489489
.buttonStyle(.plain)
490+
.accessibilityLabel("Close")
490491
}
491492
.padding()
492493

0 commit comments

Comments
 (0)