1
1
import React , { useState , useRef , useEffect } from "react" ;
2
- import {
3
- View ,
4
- Text ,
5
- TextInput ,
6
- TouchableOpacity ,
7
- FlatList ,
8
- ListRenderItem ,
9
- KeyboardAvoidingView ,
10
- Keyboard ,
11
- RefreshControl ,
12
- } from "react-native" ;
2
+ import { View , FlatList , ListRenderItem , RefreshControl } from "react-native" ;
13
3
import { useRecoilState , useRecoilValue } from "recoil" ;
14
4
import imagesState from "../state/imageState" ;
15
- import suggestionState from "../state/suggestionState" ;
16
5
import { ImageUrl } from "../types/imageUrl" ;
17
- import { fetchImages , fetchSuggestion , generateImage } from "../fetchData" ;
6
+ import { fetchImages } from "../fetchData" ;
18
7
import ImageItem from "../components/ImageItem" ;
19
8
import { Toast } from "react-native-toast-message/lib/src/Toast" ;
20
9
import internetState from "../state/internetState" ;
21
- import AsyncStorage from "@react-native-async-storage/async-storage " ;
10
+ import InputPrompt from "./InputPrompt " ;
22
11
23
12
const Body = ( ) => {
24
13
const [ images , setImages ] = useRecoilState ( imagesState ) ;
25
- const [ suggestion , setSuggestion ] = useRecoilState ( suggestionState ) ;
26
-
27
- const [ inputValue , setInputValue ] = useState ( "" ) ;
28
- const [ refreshing , setRefreshing ] = useState ( false ) ;
29
- const [ generating , setGenerating ] = useState ( false ) ;
30
14
const hasInternet = useRecoilValue ( internetState ) ;
15
+ const [ refreshing , setRefreshing ] = useState ( false ) ;
31
16
32
- // Reference for the FlatList
33
17
const flatListRef = useRef < FlatList < ImageUrl > > ( null ) ;
34
18
const isFirstRender = useRef ( true ) ;
35
19
36
- // AsyncStorage key
37
- const LAST_GENERATED_TIME_KEY = "lastGeneratedTime" ;
38
-
39
20
useEffect ( ( ) => {
40
21
// Prevent the toast pop up on the first render
41
22
if ( isFirstRender . current ) {
42
23
isFirstRender . current = false ;
43
24
return ;
44
25
}
45
-
46
26
if ( ! hasInternet ) {
47
27
Toast . show ( {
48
28
type : "error" ,
@@ -53,103 +33,13 @@ const Body = () => {
53
33
}
54
34
} , [ hasInternet ] ) ;
55
35
56
- async function setLastGeneratedTime ( ) {
57
- const currentTime = new Date ( ) . getTime ( ) ;
58
- await AsyncStorage . setItem (
59
- LAST_GENERATED_TIME_KEY ,
60
- JSON . stringify ( currentTime )
61
- ) ;
62
- }
63
-
64
- async function getLastGeneratedTime ( ) {
65
- const lastGeneratedTime = await AsyncStorage . getItem (
66
- LAST_GENERATED_TIME_KEY
67
- ) ;
68
- return lastGeneratedTime ? JSON . parse ( lastGeneratedTime ) : null ;
69
- }
70
-
71
- const handleSubmit = async ( prompt : string ) => {
72
- const lastGeneratedTime = await getLastGeneratedTime ( ) ;
73
- const currentTime = new Date ( ) . getTime ( ) ;
74
-
75
- if ( lastGeneratedTime && currentTime - lastGeneratedTime < 10000 ) {
76
- Toast . show ( {
77
- type : "info" ,
78
- text1 : "Please wait" ,
79
- text2 : "You can generate an image every 10 seconds." ,
80
- position : "bottom" ,
81
- } ) ;
82
- return ;
83
- }
84
-
85
- setGenerating ( true ) ;
86
- console . log ( "Submitting prompt: " , prompt ) ;
87
- Toast . show ( {
88
- type : "info" ,
89
- text1 : "Generating..." ,
90
- text2 : `DALL‧E is creating ${ prompt . slice ( 0 , 30 ) } ...` ,
91
- position : "bottom" ,
92
- } ) ;
93
- setInputValue ( "" ) ;
94
- Keyboard . dismiss ( ) ; // Dismiss the keyboard
95
-
96
- try {
97
- const res = await generateImage ( prompt ) ;
98
- if ( ! res ) {
99
- console . log ( "Error generating image." ) ;
100
- Toast . show ( {
101
- type : "error" ,
102
- text1 : "Error" ,
103
- text2 : "Error generating image. Please try again later." ,
104
- position : "bottom" ,
105
- } ) ;
106
- } else {
107
- Toast . show ( {
108
- type : "success" ,
109
- text1 : "Success!" ,
110
- text2 : "Your image has been generated!" ,
111
- position : "bottom" ,
112
- } ) ;
113
-
114
- await setLastGeneratedTime ( ) ;
115
- await handleRefreshImage ( ) ;
116
-
117
- // Scroll the FlatList to the top
118
- flatListRef . current ?. scrollToOffset ( { offset : 0 , animated : true } ) ;
119
-
120
- console . log ( "Image generated!" ) ;
121
- }
122
- } catch ( error ) {
123
- console . error ( "Error occurred while generating image:" , error ) ;
124
- Toast . show ( {
125
- type : "error" ,
126
- text1 : "Error" ,
127
- text2 :
128
- "An error occurred while generating the image. Please try again later." ,
129
- position : "bottom" ,
130
- } ) ;
131
- } finally {
132
- setGenerating ( false ) ;
133
- }
134
- } ;
135
-
136
- const handleUseSuggestion = ( ) => {
137
- setInputValue ( suggestion ) ;
138
- } ;
139
-
140
36
// This handle the FlatList swipe up to refresh
141
37
const onRefresh = async ( ) => {
142
38
setRefreshing ( true ) ;
143
39
await handleRefreshImage ( ) ;
144
40
setRefreshing ( false ) ;
145
41
} ;
146
42
147
- const handleRefreshSuggestion = async ( ) => {
148
- setSuggestion ( "Loading new suggestion..." ) ;
149
- const newSuggestion = await fetchSuggestion ( ) ;
150
- setSuggestion ( newSuggestion ?? "" ) ;
151
- } ;
152
-
153
43
const handleRefreshImage = async ( ) => {
154
44
if ( ! hasInternet ) return ;
155
45
const newImages = await fetchImages ( ) ;
@@ -162,61 +52,7 @@ const Body = () => {
162
52
163
53
return (
164
54
< View className = "flex-1" >
165
- < KeyboardAvoidingView className = "flex flex-col items-center justify-center mx-4 px-2 py-2 mb-1 rounded-lg border-gray-200 border shadow-inner" >
166
- < View className = "w-full flex flex-row" >
167
- < TextInput
168
- className = "flex-1 h-15 bg-white border border-gray-300 rounded-lg p-2"
169
- placeholder = { suggestion }
170
- value = { inputValue }
171
- onChangeText = { ( text ) => setInputValue ( text ) }
172
- multiline
173
- numberOfLines = { 4 }
174
- textAlignVertical = "top"
175
- />
176
- < View className = "w-2" />
177
- < TouchableOpacity
178
- className = { `h-15 rounded text-center px-3 py-2 justify-center items-center ${
179
- ! inputValue || generating || ! hasInternet
180
- ? " bg-fuchsia-200"
181
- : "bg-fuchsia-600"
182
- } `}
183
- onPress = { ! generating ? ( ) => handleSubmit ( inputValue ) : undefined }
184
- disabled = { ! inputValue || generating || ! hasInternet }
185
- >
186
- < Text className = "text-white font-bold" >
187
- { generating ? "Loading..." : "Submit" }
188
- </ Text >
189
- </ TouchableOpacity >
190
- </ View >
191
- { inputValue &&
192
- ! inputValue . includes ( suggestion ) &&
193
- ( suggestion || hasInternet ) && (
194
- < Text className = "w-full my-1" >
195
- < Text className = "font-medium" > Suggestion💡</ Text >
196
- < Text className = "font-light italic" > { suggestion } </ Text >
197
- </ Text >
198
- ) }
199
- < TouchableOpacity
200
- className = { `w-full h-10 ${
201
- hasInternet ? "bg-green-500" : "bg-green-200"
202
- } rounded text-center p-2 my-1 justify-center items-center`}
203
- onPress = { handleRefreshSuggestion }
204
- disabled = { ! hasInternet }
205
- >
206
- < Text className = "text-white" > Gimme a new suggestion!</ Text >
207
- </ TouchableOpacity >
208
- < TouchableOpacity
209
- className = "w-full h-10 bg-blue-500 rounded text-center p-2 justify-center items-center"
210
- onPress = { handleUseSuggestion }
211
- >
212
- < Text className = "text-white" > Use suggestion!</ Text >
213
- </ TouchableOpacity >
214
- { ! hasInternet && ! isFirstRender . current && (
215
- < Text className = "w-full my-1 text-red-500 font-light italic" >
216
- ⛔️ Error: No internet connection.
217
- </ Text >
218
- ) }
219
- </ KeyboardAvoidingView >
55
+ < InputPrompt flatListRef = { flatListRef } isFirstRender = { isFirstRender } />
220
56
< FlatList
221
57
ref = { flatListRef }
222
58
data = { images }
0 commit comments