96 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
//
 | 
						|
//  ImageLoader.swift
 | 
						|
//  WatchRunner Watch App
 | 
						|
//
 | 
						|
//  Created by LittleSheep on 2025/10/29.
 | 
						|
//
 | 
						|
 | 
						|
import SwiftUI
 | 
						|
import Kingfisher
 | 
						|
import KingfisherWebP
 | 
						|
import Combine
 | 
						|
 | 
						|
// MARK: - Image Loader
 | 
						|
 | 
						|
@MainActor
 | 
						|
class ImageLoader: ObservableObject {
 | 
						|
    @Published var image: Image?
 | 
						|
    @Published var errorMessage: String?
 | 
						|
    @Published var isLoading = false
 | 
						|
 | 
						|
    private var currentTask: DownloadTask?
 | 
						|
 | 
						|
    init() {}
 | 
						|
 | 
						|
    deinit {
 | 
						|
        currentTask?.cancel()
 | 
						|
    }
 | 
						|
 | 
						|
    func loadImage(from initialUrl: URL, token: String) async {
 | 
						|
        isLoading = true
 | 
						|
        errorMessage = nil
 | 
						|
        image = nil
 | 
						|
 | 
						|
        // Create request modifier for authorization
 | 
						|
        let modifier = AnyModifier { request in
 | 
						|
            var r = request
 | 
						|
            r.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
 | 
						|
            r.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
 | 
						|
            return r
 | 
						|
        }
 | 
						|
 | 
						|
        // Use WebP processor as default since the app seems to handle WebP images
 | 
						|
        let processor = WebPProcessor.default
 | 
						|
 | 
						|
        // Use KingfisherManager to retrieve image with caching
 | 
						|
        currentTask = KingfisherManager.shared.retrieveImage(
 | 
						|
            with: initialUrl,
 | 
						|
            options: [
 | 
						|
                .requestModifier(modifier),
 | 
						|
                .processor(processor),
 | 
						|
                .cacheOriginalImage, // Cache the original image data
 | 
						|
                .loadDiskFileSynchronously // Load from disk cache synchronously if available
 | 
						|
            ]
 | 
						|
        ) { [weak self] result in
 | 
						|
            guard let self = self else { return }
 | 
						|
 | 
						|
            Task { @MainActor in
 | 
						|
                switch result {
 | 
						|
                case .success(let value):
 | 
						|
                    self.image = Image(uiImage: value.image)
 | 
						|
                    self.isLoading = false
 | 
						|
                case .failure(_):
 | 
						|
                    // If WebP processor fails (likely due to format), try with default processor
 | 
						|
                    let defaultProcessor = DefaultImageProcessor.default
 | 
						|
                    self.currentTask = KingfisherManager.shared.retrieveImage(
 | 
						|
                        with: initialUrl,
 | 
						|
                        options: [
 | 
						|
                            .requestModifier(modifier),
 | 
						|
                            .processor(defaultProcessor),
 | 
						|
                            .cacheOriginalImage,
 | 
						|
                            .loadDiskFileSynchronously
 | 
						|
                        ]
 | 
						|
                    ) { [weak self] fallbackResult in
 | 
						|
                        guard let self = self else { return }
 | 
						|
 | 
						|
                        Task { @MainActor in
 | 
						|
                            switch fallbackResult {
 | 
						|
                            case .success(let value):
 | 
						|
                                self.image = Image(uiImage: value.image)
 | 
						|
                            case .failure(let fallbackError):
 | 
						|
                                self.errorMessage = fallbackError.localizedDescription
 | 
						|
                                print("[watchOS] Image loading failed: \(fallbackError.localizedDescription)")
 | 
						|
                            }
 | 
						|
                            self.isLoading = false
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    func cancel() {
 | 
						|
        currentTask?.cancel()
 | 
						|
    }
 | 
						|
}
 |