|
|
@@ -22,38 +22,50 @@ typealias GIDImage = NSImage
|
|
|
|
|
|
import Combine
|
|
|
import SwiftUI
|
|
|
-import GoogleSignIn
|
|
|
+@preconcurrency import GoogleSignIn
|
|
|
|
|
|
/// An observable class for loading the current user's profile image.
|
|
|
-final class UserProfileImageLoader: ObservableObject {
|
|
|
+@MainActor final class UserProfileImageLoader: ObservableObject {
|
|
|
private let userProfile: GIDProfileData
|
|
|
- private let imageLoaderQueue = DispatchQueue(label: "com.google.days-until-birthday")
|
|
|
+ private var imageLoadingTask: Task<Void, Never>?
|
|
|
/// A `UIImage` property containing the current user's profile image.
|
|
|
/// - note: This will default to a placeholder, and updates will be published to subscribers.
|
|
|
@Published var image = GIDImage(named: "PlaceholderAvatar")!
|
|
|
|
|
|
/// Creates an instance of this loader with provided user profile.
|
|
|
/// - note: The instance will asynchronously fetch the image data upon creation.
|
|
|
- init(userProfile: GIDProfileData) {
|
|
|
- self.userProfile = userProfile
|
|
|
- guard userProfile.hasImage else {
|
|
|
- return
|
|
|
+ init(userProfile: GIDProfileData) {
|
|
|
+ self.userProfile = userProfile
|
|
|
+ guard userProfile.hasImage else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ imageLoadingTask = Task {
|
|
|
+ await loadProfileImage()
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- imageLoaderQueue.async {
|
|
|
- #if os(iOS)
|
|
|
- let dimension = 45 * UIScreen.main.scale
|
|
|
- #elseif os(macOS)
|
|
|
- let dimension = 120
|
|
|
- #endif
|
|
|
- guard let url = userProfile.imageURL(withDimension: UInt(dimension)),
|
|
|
- let data = try? Data(contentsOf: url),
|
|
|
- let image = GIDImage(data: data) else {
|
|
|
- return
|
|
|
- }
|
|
|
- DispatchQueue.main.async {
|
|
|
- self.image = image
|
|
|
- }
|
|
|
+ private func loadProfileImage() async {
|
|
|
+ #if os(iOS)
|
|
|
+ let dimension = 45 * UIScreen.main.scale
|
|
|
+ #elseif os(macOS)
|
|
|
+ let dimension = 120
|
|
|
+ #endif
|
|
|
+
|
|
|
+ guard let url = userProfile.imageURL(withDimension: UInt(dimension)) else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ do {
|
|
|
+ let (imageData, _) = try await URLSession.shared.data(from: url)
|
|
|
+ if let image = GIDImage(data: imageData) {
|
|
|
+ self.image = image
|
|
|
+ }
|
|
|
+ } catch {
|
|
|
+ print("Image download failed:", error)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ deinit {
|
|
|
+ imageLoadingTask?.cancel()
|
|
|
}
|
|
|
- }
|
|
|
}
|