Skip to content

Commit fbc9129

Browse files
committed
Add Create Image example to Demo app
1 parent f0e1709 commit fbc9129

File tree

6 files changed

+200
-7
lines changed

6 files changed

+200
-7
lines changed

Demo/App/APIProvidedView.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import SwiftUI
1212
struct APIProvidedView: View {
1313
@Binding var apiKey: String
1414
@StateObject var chatStore: ChatStore
15+
@StateObject var imageStore: ImageStore
1516
@StateObject var miscStore: MiscStore
1617
@State var isShowingAPIConfigModal: Bool = true
1718

@@ -29,6 +30,11 @@ struct APIProvidedView: View {
2930
idProvider: idProvider
3031
)
3132
)
33+
self._imageStore = StateObject(
34+
wrappedValue: ImageStore(
35+
openAIClient: OpenAI(apiToken: apiKey.wrappedValue)
36+
)
37+
)
3238
self._miscStore = StateObject(
3339
wrappedValue: MiscStore(
3440
openAIClient: OpenAI(apiToken: apiKey.wrappedValue)
@@ -39,6 +45,7 @@ struct APIProvidedView: View {
3945
var body: some View {
4046
ContentView(
4147
chatStore: chatStore,
48+
imageStore: imageStore,
4249
miscStore: miscStore
4350
)
4451
.onChange(of: apiKey) { newApiKey in

Demo/App/ContentView.swift

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import SwiftUI
1111

1212
struct ContentView: View {
1313
@ObservedObject var chatStore: ChatStore
14+
@ObservedObject var imageStore: ImageStore
1415
@ObservedObject var miscStore: MiscStore
1516
@State private var selectedTab = 0
1617
@Environment(\.idProviderValue) var idProvider
@@ -33,6 +34,7 @@ struct ContentView: View {
3334
.tag(1)
3435

3536
ImageView(
37+
store: imageStore
3638
)
3739
.tabItem {
3840
Label("Image", systemImage: "photo")
@@ -63,10 +65,3 @@ struct TranscribeView: View {
6365
.font(.largeTitle)
6466
}
6567
}
66-
67-
struct ImageView: View {
68-
var body: some View {
69-
Text("Image: TBD")
70-
.font(.largeTitle)
71-
}
72-
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//
2+
// ImageStore.swift
3+
// DemoChat
4+
//
5+
// Created by Aled Samuel on 24/04/2023.
6+
//
7+
8+
import Foundation
9+
import OpenAI
10+
11+
public final class ImageStore: ObservableObject {
12+
public var openAIClient: OpenAIProtocol
13+
14+
@Published var images: [ImagesResult.URLResult] = []
15+
16+
public init(
17+
openAIClient: OpenAIProtocol
18+
) {
19+
self.openAIClient = openAIClient
20+
}
21+
22+
@MainActor
23+
func images(query: ImagesQuery) async {
24+
images.removeAll()
25+
do {
26+
let response = try await openAIClient.images(query: query)
27+
images = response.data
28+
} catch {
29+
// TODO: Better error handling
30+
print(error.localizedDescription)
31+
}
32+
}
33+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//
2+
// ImageCreationView.swift
3+
// DemoChat
4+
//
5+
// Created by Aled Samuel on 24/04/2023.
6+
//
7+
8+
import SwiftUI
9+
import OpenAI
10+
import SafariServices
11+
12+
public struct ImageCreationView: View {
13+
@ObservedObject var store: ImageStore
14+
15+
@State private var prompt: String = ""
16+
@State private var n: Int = 1
17+
@State private var size: String
18+
@State private var showSafari = false
19+
20+
private var sizes = ["256x256", "512x512", "1024x1024"]
21+
22+
public init(store: ImageStore) {
23+
self.store = store
24+
size = sizes[0]
25+
}
26+
27+
public var body: some View {
28+
List {
29+
Section {
30+
HStack {
31+
Text("Prompt")
32+
Spacer()
33+
TextEditor(text: $prompt)
34+
.multilineTextAlignment(.trailing)
35+
}
36+
HStack {
37+
Stepper("Amount: \(n)", value: $n, in: 1...10)
38+
}
39+
HStack {
40+
Picker("Size", selection: $size) {
41+
ForEach(sizes, id: \.self) {
42+
Text($0)
43+
}
44+
}
45+
}
46+
}
47+
Section {
48+
HStack {
49+
Button("Create Image" + (n == 1 ? "" : "s")) {
50+
Task {
51+
let query = ImagesQuery(prompt: prompt, n: n, size: size)
52+
await store.images(query: query)
53+
}
54+
}
55+
.foregroundColor(.accentColor)
56+
Spacer()
57+
}
58+
}
59+
if !$store.images.isEmpty {
60+
Section("Images") {
61+
ForEach($store.images, id: \.self) { image in
62+
let urlString = image.wrappedValue.url
63+
if let imageURL = URL(string: urlString), UIApplication.shared.canOpenURL(imageURL) {
64+
Button {
65+
showSafari.toggle()
66+
} label: {
67+
Text(urlString)
68+
.foregroundStyle(.foreground)
69+
}.fullScreenCover(isPresented: $showSafari, content: {
70+
SafariView(url: imageURL)
71+
})
72+
} else {
73+
Text(urlString)
74+
.foregroundStyle(.secondary)
75+
}
76+
}
77+
}
78+
}
79+
}
80+
.listStyle(.insetGrouped)
81+
.navigationTitle("Create Image")
82+
}
83+
}
84+
85+
private struct SafariView: UIViewControllerRepresentable {
86+
var url: URL
87+
88+
func makeUIViewController(context: UIViewControllerRepresentableContext<SafariView>) -> SFSafariViewController {
89+
SFSafariViewController(url: url)
90+
}
91+
92+
func updateUIViewController(_ safariViewController: SFSafariViewController, context: UIViewControllerRepresentableContext<SafariView>) { }
93+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//
2+
// ImageView.swift
3+
// DemoChat
4+
//
5+
// Created by Aled Samuel on 24/04/2023.
6+
//
7+
8+
import SwiftUI
9+
10+
public struct ImageView: View {
11+
@ObservedObject var store: ImageStore
12+
13+
public init(store: ImageStore) {
14+
self.store = store
15+
}
16+
17+
public var body: some View {
18+
NavigationStack {
19+
List {
20+
NavigationLink("Create Image", destination: ImageCreationView(store: store))
21+
NavigationLink("Create Image Edit", destination: ImageEditView(store: store))
22+
.disabled(true)
23+
NavigationLink("Create Image Variation", destination: ImageVariationView(store: store))
24+
.disabled(true)
25+
26+
}
27+
.listStyle(.insetGrouped)
28+
.navigationTitle("Image")
29+
}
30+
}
31+
}
32+
33+
public struct ImageEditView: View {
34+
@ObservedObject var store: ImageStore
35+
36+
public init(store: ImageStore) {
37+
self.store = store
38+
}
39+
40+
public var body: some View {
41+
List {
42+
43+
}
44+
.listStyle(.insetGrouped)
45+
.navigationTitle("Create Image Edit")
46+
}
47+
}
48+
49+
public struct ImageVariationView: View {
50+
@ObservedObject var store: ImageStore
51+
52+
public init(store: ImageStore) {
53+
self.store = store
54+
}
55+
56+
public var body: some View {
57+
List {
58+
59+
}
60+
.listStyle(.insetGrouped)
61+
.navigationTitle("Create Image Variation")
62+
}
63+
}

Sources/OpenAI/Public/Models/ImagesResult.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ public struct ImagesResult: Codable, Equatable {
1515
public let created: TimeInterval
1616
public let data: [URLResult]
1717
}
18+
19+
extension ImagesResult.URLResult: Hashable { }

0 commit comments

Comments
 (0)