-
Notifications
You must be signed in to change notification settings - Fork 28
perf: optimize network, caching, and SwiftUI rendering #57
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
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -14,8 +14,16 @@ actor ImageCache { | |||||||||||||||||
| /// Maximum disk cache size in bytes (200MB). | ||||||||||||||||||
| private static let maxDiskCacheSize: Int64 = 200 * 1024 * 1024 | ||||||||||||||||||
|
|
||||||||||||||||||
| /// Priority levels for image loading to ensure visible images load first. | ||||||||||||||||||
| enum Priority: Sendable { | ||||||||||||||||||
| case high // Visible on screen | ||||||||||||||||||
| case low // Prefetch for upcoming content | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
|
||||||||||||||||||
| /// Priority levels for image loading to ensure visible images load first. | |
| enum Priority: Sendable { | |
| case high // Visible on screen | |
| case low // Prefetch for upcoming content | |
| } |
Outdated
Copilot
AI
Jan 7, 2026
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.
Mutating a dictionary while iterating over it can lead to undefined behavior. The code removes values from activePrefetchTasks while iterating, which is unsafe. Consider using removeAll() after the loop, or iterate over a copy of the keys.
| for (id, task) in self.activePrefetchTasks { | |
| task.cancel() | |
| self.activePrefetchTasks.removeValue(forKey: id) | |
| } | |
| for (_, task) in self.activePrefetchTasks { | |
| task.cancel() | |
| } | |
| self.activePrefetchTasks.removeAll() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ struct CachedAsyncImage<Content: View, Placeholder: View>: View { | |
|
|
||
| @State private var image: NSImage? | ||
| @State private var isLoaded = false | ||
| @State private var loadTask: Task<Void, Never>? | ||
|
|
||
| /// Whether to animate the image appearance. | ||
| private var shouldAnimate: Bool { | ||
|
|
@@ -30,10 +31,30 @@ struct CachedAsyncImage<Content: View, Placeholder: View>: View { | |
| self.placeholder() | ||
| } | ||
| } | ||
| .onChange(of: self.url) { oldUrl, newUrl in | ||
| // Cancel previous load when URL changes | ||
| if oldUrl != newUrl { | ||
| self.loadTask?.cancel() | ||
| self.image = nil | ||
| self.isLoaded = false | ||
| } | ||
| } | ||
|
||
| .task(id: self.url) { | ||
| guard let url else { return } | ||
| self.image = await ImageCache.shared.image(for: url, targetSize: self.targetSize) | ||
| self.isLoaded = true | ||
| // Cancel any previous load task | ||
| self.loadTask?.cancel() | ||
|
|
||
| let task = Task { | ||
| let loadedImage = await ImageCache.shared.image(for: url, targetSize: self.targetSize) | ||
| guard !Task.isCancelled else { return } | ||
| self.image = loadedImage | ||
| self.isLoaded = true | ||
| } | ||
| self.loadTask = task | ||
| await task.value | ||
| } | ||
| .onDisappear { | ||
| self.loadTask?.cancel() | ||
| } | ||
| } | ||
| } | ||
|
|
||
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.
HTTP pipelining (httpShouldUsePipelining) is deprecated and largely unsupported by modern servers, including YouTube Music's API. Most HTTP/1.1 servers don't support pipelining due to security and performance concerns, and HTTP/2 makes it obsolete with multiplexing. This setting will likely have no effect and could potentially cause issues with some proxy configurations. Consider removing this setting or documenting that it may not have the intended effect.