Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f33d701

Browse files
update
1 parent 439aba5 commit f33d701

File tree

3 files changed

+40
-53
lines changed

3 files changed

+40
-53
lines changed

‎Package.resolved‎

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Package.swift‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@ let package = Package(
1414
],
1515
dependencies: [
1616
// Dependencies declare other packages that this package depends on.
17-
.package(url: "https://github.com/swiftuiux/async-http-client.git", from: "1.5.0")
17+
.package(url: "https://github.com/swiftuiux/async-http-client.git", from: "1.5.0"),
18+
.package(url: "https://github.com/swiftuiux/async-task.git", from: "1.2.3")
1819
],
1920
targets: [
2021
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
2122
// Targets can depend on other targets in this package, and on products in packages this package depends on.
2223
.target(
2324
name: "openai-async-image-swiftui",
24-
dependencies: ["async-http-client"]),
25+
dependencies: ["async-http-client","async-task"]),
2526
.testTarget(
2627
name: "openai-async-image-swiftuiTests",
2728
dependencies: ["openai-async-image-swiftui"]),

‎Sources/openai-async-image-swiftui/OpenAIAsyncImage.swift‎

Lines changed: 28 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,23 @@
66
//
77

88
import SwiftUI
9+
import async_task
910

1011
fileprivate typealias ImageSize = OpenAIImageSize
12+
fileprivate typealias TaskModel = Async.SingleTask<Image, AsyncImageErrors>
1113

1214
/// Async image component to load and show OpenAI image from OpenAI image API
1315
@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
1416
public struct OpenAIAsyncImage<Content: View, T: IOpenAILoader>: View {
1517

18+
@StateObject private var taskModel = TaskModel(errorMapper: errorMapper)
19+
1620
/// Custom view builder template type alias
1721
public typealias ImageProcess = (ImageState) -> Content
1822

1923
/// Default loader, injected from environment
2024
@Environment(\.openAIDefaultLoader) var defaultLoader : OpenAIDefaultLoader
21-
22-
// MARK: - Private properties
23-
24-
/// State variable to hold the OpenAI image
25-
@State private var image: Image?
26-
27-
/// State variable to hold any errors encountered during loading
28-
@State private var error: Error?
29-
30-
/// State variable to hold the current task responsible for loading the image
31-
@State private var task : Task<Void, Never>?
32-
25+
3326
// MARK: - Config
3427

3528
/// A binding to the text prompt describing the desired image. The maximum length is 1000 characters
@@ -85,15 +78,13 @@ public struct OpenAIAsyncImage<Content: View, T: IOpenAILoader>: View {
8578
}
8679
}
8780
.onChange(of: prompt){ _ in
88-
cancelTask()
89-
clear()
90-
task = getTask()
81+
start()
9182
}
9283
.onAppear {
93-
task =getTask()
84+
start()
9485
}
9586
.onDisappear{
96-
cancelTask()
87+
cancel()
9788
}
9889
}
9990

@@ -102,8 +93,8 @@ public struct OpenAIAsyncImage<Content: View, T: IOpenAILoader>: View {
10293
/// - Returns: The current image state status
10394
private func getState () -> ImageState{
10495

105-
if let image { return .loaded(image) }
106-
else if let error { return .loadError(error)}
96+
if let image = taskModel.value { return .loaded(image) }
97+
else if let error = taskModel.error { return .loadError(error)}
10798

10899
return .loading
109100
}
@@ -139,42 +130,19 @@ public struct OpenAIAsyncImage<Content: View, T: IOpenAILoader>: View {
139130
}
140131
return try await loadImageDefault(prompt, with: size, model: model)
141132
}
142-
143-
/// Sets the image on the main thread
144-
/// - Parameter value: The image to be set
145-
@MainActor
146-
private func setImage(_ value : Image){
147-
image = value
148-
}
149-
150-
/// Clears the image and error state properties
151-
@MainActor
152-
private func clear(){
153-
image = nil
154-
error = nil
155-
}
156-
157-
/// Cancels the current loading task if any
158-
private func cancelTask(){
159-
task?.cancel()
160-
task = nil
161-
}
162-
133+
163134
/// Creates and returns a task to fetch the OpenAI image
164135
/// - Returns: A task that fetches the OpenAI image
165-
private func getTask() -> Task<Void, Never>{
166-
Task{
167-
do{
168-
if let image = try await loadImage(prompt, with: size, model: model){
169-
setImage(image)
170-
}
171-
}catch is CancellationError{
172-
self.error = AsyncImageErrors.cancellationError
173-
}catch{
174-
self.error = error
175-
}
136+
private func start(){
137+
taskModel.start{
138+
try await loadImage(prompt, with: size, model: model)
176139
}
177140
}
141+
142+
/// Cancel task
143+
private func cancel(){
144+
taskModel.cancel()
145+
}
178146
}
179147

180148
// MARK: - Public extensions -
@@ -232,3 +200,12 @@ fileprivate func imageTpl(_ state : ImageState) -> some View{
232200
case .loading : ProgressView()
233201
}
234202
}
203+
204+
@Sendable
205+
fileprivate func errorMapper(_ error : Error?) -> AsyncImageErrors?{
206+
if error is CancellationError{
207+
return .cancellationError
208+
}
209+
210+
return nil
211+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /