diff --git a/Package.resolved b/Package.resolved index dd1d5f0..ca17838 100644 --- a/Package.resolved +++ b/Package.resolved @@ -8,6 +8,15 @@ "revision" : "9df754fe4ca4c5abdf3376e4e9ec33b3485bf180", "version" : "11.2.1" } + }, + { + "identity" : "swiftui-support", + "kind" : "remoteSourceControl", + "location" : "https://github.com/FluidGroup/swiftui-support.git", + "state" : { + "revision" : "6a3e98c1a13fa4dc7eb82f6800c790665daae65c", + "version" : "0.1.0" + } } ], "version" : 2 diff --git a/Package.swift b/Package.swift index 0f89bff..d066c97 100644 --- a/Package.swift +++ b/Package.swift @@ -27,12 +27,13 @@ let package = Package( ) ], dependencies: [ - .package(url: "https://github.com/kean/Nuke.git", from: "11.2.1") + .package(url: "https://github.com/kean/Nuke.git", from: "11.2.1"), + .package(url: "https://github.com/FluidGroup/swiftui-support.git", from: "0.1.0") ], targets: [ .target( name: "AsyncMultiplexImage", - dependencies: [] + dependencies: [.product(name: "SwiftUISupport", package: "swiftui-support")] ), .target( name: "AsyncMultiplexImage-Nuke", diff --git a/Sources/AsyncMultiplexImage/AsyncMultiplexImage.swift b/Sources/AsyncMultiplexImage/AsyncMultiplexImage.swift index 4cbc8ff..e1c618f 100644 --- a/Sources/AsyncMultiplexImage/AsyncMultiplexImage.swift +++ b/Sources/AsyncMultiplexImage/AsyncMultiplexImage.swift @@ -1,15 +1,26 @@ import Foundation import SwiftUI import os.log +import SwiftUISupport enum Log { - static func debug(_ log: OSLog, _ object: @autoclosure () -> Any) { - os_log(.debug, log: log, "%@", "\(object())") + static func debug( + file: StaticString = #file, + line: UInt = #line, + _ log: OSLog, + _ object: @autoclosure () -> Any + ) { + os_log(.default, log: log, "%{public}@\n%{public}@:%{public}@", "\(object())", "\(file)", "\(line.description)") } - static func error(_ log: OSLog, _ object: @autoclosure () -> Any) { - os_log(.error, log: log, "%@", "\(object())") + static func error( + file: StaticString = #file, + line: UInt = #line, + _ log: OSLog, + _ object: @autoclosure () -> Any + ) { + os_log(.error, log: log, "%{public}@\n%{public}@:%{public}@", "\(object())", "\(file)", "\(line.description)") } } @@ -25,8 +36,8 @@ extension OSLog { #endif } - static let `default`: OSLog = makeOSLogInDebug { OSLog.init(subsystem: "app", category: "default") } - static let view: OSLog = makeOSLogInDebug { OSLog.init(subsystem: "app", category: "View") } + static let generic: OSLog = makeOSLogInDebug { OSLog.init(subsystem: "app.muukii", category: "default") } + static let view: OSLog = makeOSLogInDebug { OSLog.init(subsystem: "app.muukii", category: "View") } } @MainActor @@ -57,8 +68,24 @@ public struct AsyncMultiplexImageCandidate: Hashable { public struct AsyncMultiplexImage: View { - private let candidates: [AsyncMultiplexImageCandidate] - private let content: _AsyncMultiplexImage + private var candidates: [AsyncMultiplexImageCandidate] = [] + + @State private var internalView: _AsyncMultiplexImage? + + private let urlsProvider: (CGSize) -> [URL] + private let downloader: Downloader + private let content: (AsyncMultiplexImagePhase) -> Content + + public init( + urlsProvider: @escaping (CGSize) -> [URL], + downloader: Downloader, + @ViewBuilder content: @escaping (AsyncMultiplexImagePhase) -> Content + ) { + + self.urlsProvider = urlsProvider + self.downloader = downloader + self.content = content + } /// Primitive initializer public init( @@ -67,14 +94,7 @@ public struct AsyncMultiplexImage Content ) { - self.candidates = urls.enumerated().map { i, e in AsyncMultiplexImageCandidate(index: i, urlRequest: .init(url: e)) } - - self.content = .init( - candidates: candidates, - downloader: downloader, - content: content - ) - + self.init(urlsProvider: { _ in urls }, downloader: downloader, content: content) } // TODO: tmp @@ -101,8 +121,19 @@ public struct AsyncMultiplexImage AsyncThrowingStream { - Log.debug(.default, "Load: \(candidates.map { $0.urlRequest })") + Log.debug(.`generic`, "Load: \(candidates.map { $0.urlRequest })") return .init { continuation in @@ -212,7 +243,7 @@ actor ResultContainer { progressImagesTask?.cancel() - Log.debug(.default, "Loaded ideal") + Log.debug(.`generic`, "Loaded ideal") lastCandidate = idealCandidate continuation.yield(result) @@ -239,15 +270,15 @@ actor ResultContainer { do { guard Task.isCancelled == false else { - Log.debug(.default, "Cancelled progress images") + Log.debug(.`generic`, "Cancelled progress images") return } - Log.debug(.default, "Load progress image => \(candidate.index)") + Log.debug(.`generic`, "Load progress image => \(candidate.index)") let result = try await downloader.download(candidate: candidate) guard Task.isCancelled == false else { - Log.debug(.default, "Cancelled progress images") + Log.debug(.`generic`, "Cancelled progress images") return } @@ -261,7 +292,7 @@ actor ResultContainer { let yieldResult = continuation.yield(result) - Log.debug(.default, "Loaded progress image => \(candidate.index), \(yieldResult)") + Log.debug(.`generic`, "Loaded progress image => \(candidate.index), \(yieldResult)") } catch { }