1313// limitations under the License.
1414
1515import SwiftUI
16+ import GenerativeAIUIComponents
1617
1718struct ImagenScreen : View {
1819 @StateObject var viewModel = ImagenViewModel ( )
@@ -25,29 +26,38 @@ struct ImagenScreen: View {
2526 var focusedField : FocusedField ?
2627
2728 var body : some View {
28- VStack {
29- TextField ( " Enter a prompt to generate an image " , text: $viewModel. userInput)
30- . focused ( $focusedField, equals: . message)
31- . textFieldStyle ( . roundedBorder)
32- . onSubmit {
33- onGenerateTapped ( )
29+ ZStack {
30+ VStack {
31+ InputField ( " Enter a prompt to generate an image " , text: $viewModel. userInput) {
32+ Image (
33+ systemName: viewModel. inProgress ? " stop.circle.fill " : " paperplane.circle.fill "
34+ )
35+ . font ( . title)
3436 }
35- . padding ( )
37+ . focused ( $focusedField, equals: . message)
38+ . onSubmit { sendOrStop ( ) }
3639
37- Button ( " Generate " ) {
38- onGenerateTapped ( )
40+ ScrollView {
41+ let spacing : CGFloat = 10
42+ LazyVGrid ( columns: [
43+ GridItem ( . fixed( UIScreen . main. bounds. width / 2 - spacing) , spacing: spacing) ,
44+ GridItem ( . fixed( UIScreen . main. bounds. width / 2 - spacing) , spacing: spacing) ,
45+ ] , spacing: spacing) {
46+ ForEach ( viewModel. images, id: \. self) { image in
47+ Image ( uiImage: image)
48+ . resizable ( )
49+ . aspectRatio ( contentMode: . fill)
50+ . frame ( width: UIScreen . main. bounds. width / 2 - spacing,
51+ height: UIScreen . main. bounds. width / 2 - spacing)
52+ . cornerRadius ( 12 )
53+ . clipped ( )
54+ }
55+ }
56+ . padding ( . horizontal, spacing)
57+ }
3958 }
40- . padding ( )
4159 if viewModel. inProgress {
42- Text ( " Waiting for model response ... " )
43- }
44- ForEach ( viewModel. images, id: \. self) {
45- Image ( uiImage: $0)
46- . resizable ( )
47- . scaledToFill ( )
48- . frame ( minWidth: 0 , maxWidth: . infinity, minHeight: 0 , maxHeight: . infinity)
49- . aspectRatio ( nil , contentMode: . fit)
50- . clipped ( )
60+ ProgressOverlay ( )
5161 }
5262 }
5363 . navigationTitle ( " Imagen sample " )
@@ -56,11 +66,38 @@ struct ImagenScreen: View {
5666 }
5767 }
5868
59- private func onGenerateTapped( ) {
60- focusedField = nil
61-
69+ private func sendMessage( ) {
6270 Task {
6371 await viewModel. generateImage ( prompt: viewModel. userInput)
72+ focusedField = . message
73+ }
74+ }
75+
76+ private func sendOrStop( ) {
77+ if viewModel. inProgress {
78+ viewModel. stop ( )
79+ } else {
80+ sendMessage ( )
81+ }
82+ }
83+ }
84+
85+ struct ProgressOverlay : View {
86+ var body : some View {
87+ ZStack {
88+ RoundedRectangle ( cornerRadius: 16 )
89+ . fill ( Material . ultraThinMaterial)
90+ . frame ( width: 120 , height: 100 )
91+ . shadow ( radius: 8 )
92+
93+ VStack ( spacing: 12 ) {
94+ ProgressView ( )
95+ . scaleEffect ( 1.5 )
96+
97+ Text ( " Loading... " )
98+ . font ( . subheadline)
99+ . foregroundColor ( . secondary)
100+ }
64101 }
65102 }
66103}
0 commit comments