Skip to content

Commit 399b271

Browse files
authored
Merge pull request #4 from kelvinthh/dev
0.31
2 parents d8c16eb + 7d8bdc3 commit 399b271

File tree

5 files changed

+217
-191
lines changed

5 files changed

+217
-191
lines changed

App.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,32 @@ const AppContent = () => {
1616
const [hasInternet, setHasInternet] = useRecoilState(internetState);
1717

1818
useEffect(() => {
19+
20+
// Internet check
1921
const unsubscribe = NetInfo.addEventListener((state) => {
2022
console.log(`Internet state: ${state.type} ${state.isInternetReachable}`);
2123
setHasInternet(state.isInternetReachable);
2224
});
2325

24-
return () => {
25-
unsubscribe();
26-
};
27-
}, []);
28-
29-
useEffect(() => {
26+
// Fetch getImages and prompt suggestion
3027
(async () => {
3128
const images = await fetchImages();
3229
const suggestion = await fetchSuggestion();
3330

3431
setImages(images ?? []); // Provide an empty array as the default value
3532
setSuggestion(suggestion ?? ""); // Provide an empty string as the default value
3633
})();
34+
35+
return () => {
36+
unsubscribe(); // Stop internet connection check on unmount
37+
};
3738
}, []);
3839

3940
return (
4041
<SafeAreaView className="flex-1">
4142
<Header />
4243
<Body />
43-
<StatusBar barStyle={'dark-content'}/>
44+
<StatusBar barStyle={"dark-content"} />
4445
</SafeAreaView>
4546
);
4647
};

ios/imggenrn/imggenrn.entitlements

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
33
<plist version="1.0">
4-
<dict>
5-
<key>aps-environment</key>
6-
<string>development</string>
7-
</dict>
8-
</plist>
4+
<dict/>
5+
</plist>

src/components/Body.tsx

Lines changed: 5 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,28 @@
11
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";
133
import { useRecoilState, useRecoilValue } from "recoil";
144
import imagesState from "../state/imageState";
15-
import suggestionState from "../state/suggestionState";
165
import { ImageUrl } from "../types/imageUrl";
17-
import { fetchImages, fetchSuggestion, generateImage } from "../fetchData";
6+
import { fetchImages } from "../fetchData";
187
import ImageItem from "../components/ImageItem";
198
import { Toast } from "react-native-toast-message/lib/src/Toast";
209
import internetState from "../state/internetState";
21-
import AsyncStorage from "@react-native-async-storage/async-storage";
10+
import InputPrompt from "./InputPrompt";
2211

2312
const Body = () => {
2413
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);
3014
const hasInternet = useRecoilValue(internetState);
15+
const [refreshing, setRefreshing] = useState(false);
3116

32-
// Reference for the FlatList
3317
const flatListRef = useRef<FlatList<ImageUrl>>(null);
3418
const isFirstRender = useRef(true);
3519

36-
// AsyncStorage key
37-
const LAST_GENERATED_TIME_KEY = "lastGeneratedTime";
38-
3920
useEffect(() => {
4021
// Prevent the toast pop up on the first render
4122
if (isFirstRender.current) {
4223
isFirstRender.current = false;
4324
return;
4425
}
45-
4626
if (!hasInternet) {
4727
Toast.show({
4828
type: "error",
@@ -53,103 +33,13 @@ const Body = () => {
5333
}
5434
}, [hasInternet]);
5535

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-
14036
// This handle the FlatList swipe up to refresh
14137
const onRefresh = async () => {
14238
setRefreshing(true);
14339
await handleRefreshImage();
14440
setRefreshing(false);
14541
};
14642

147-
const handleRefreshSuggestion = async () => {
148-
setSuggestion("Loading new suggestion...");
149-
const newSuggestion = await fetchSuggestion();
150-
setSuggestion(newSuggestion ?? "");
151-
};
152-
15343
const handleRefreshImage = async () => {
15444
if (!hasInternet) return;
15545
const newImages = await fetchImages();
@@ -162,61 +52,7 @@ const Body = () => {
16252

16353
return (
16454
<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} />
22056
<FlatList
22157
ref={flatListRef}
22258
data={images}

src/components/ImageItem.tsx

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ interface ImageItemProps {
1212
item: ImageUrl;
1313
}
1414

15+
const hasNonAsciiCharacters = (str: string): boolean => {
16+
for (let i = 0; i < str.length; i++) {
17+
if (str.charCodeAt(i) > 127) {
18+
return true;
19+
}
20+
}
21+
return false;
22+
};
23+
1524
const ImageItem: React.FC<ImageItemProps> = ({ item }) => {
1625
const [loading, setLoading] = useState(true);
1726
const [showOverlay, setShowOverlay] = useState(false);
@@ -20,15 +29,6 @@ const ImageItem: React.FC<ImageItemProps> = ({ item }) => {
2029
setShowOverlay(!showOverlay);
2130
};
2231

23-
const hasNonAsciiCharacters = (str: string): boolean => {
24-
for (let i = 0; i < str.length; i++) {
25-
if (str.charCodeAt(i) > 127) {
26-
return true;
27-
}
28-
}
29-
return false;
30-
};
31-
3232
const spacelessUrl = item.url.replace(/ /g, "%20");
3333
const lastSvIndex = spacelessUrl.lastIndexOf("?sv=");
3434

@@ -38,7 +38,6 @@ const ImageItem: React.FC<ImageItemProps> = ({ item }) => {
3838

3939
const sasToken = spacelessUrl.substring(lastSvIndex);
4040
const formattedUrl = imageFileName + sasToken;
41-
// console.log(formattedUrl);
4241

4342
return (
4443
<View key={item.name} className="py-1">

0 commit comments

Comments
 (0)