Skip to content

Commit a2078cc

Browse files
committed
feat: enhance bug report functionality with image attachment and loading state
1 parent 2ceaed3 commit a2078cc

File tree

1 file changed

+144
-61
lines changed

1 file changed

+144
-61
lines changed

src/screens/settings/bug-report.tsx

Lines changed: 144 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
TextInput,
1111
Tooltip,
1212
useTheme,
13+
ActivityIndicator,
1314
} from 'react-native-paper';
1415
import BaseView from '../../components/baseview/baseview.tsx';
1516
import {FONTS} from '../../config/misc.ts';
@@ -22,6 +23,12 @@ import {
2223
} from '../../config/dimensions.ts';
2324
import {PhotoType} from '../../config/image-picker/image-picker.tsx';
2425
import ImagePicker from 'react-native-image-crop-picker';
26+
import storage from '@react-native-firebase/storage';
27+
import firestore from '@react-native-firebase/firestore';
28+
import auth from '@react-native-firebase/auth';
29+
import {alert} from '@baronha/ting';
30+
import {getRandomInt} from '../../utils/algo-utils.ts';
31+
import {Appodeal, AppodealAdType, AppodealMrec} from 'react-native-appodeal';
2532

2633
const BugReport: React.FC = () => {
2734
const navigation = useNavigation();
@@ -34,11 +41,83 @@ const BugReport: React.FC = () => {
3441

3542
const [isTouched, setIsTouched] = useState(false);
3643

44+
const [loading, setLoading] = useState(false);
45+
3746
const incorrectReport = () => {
3847
const textLength = reportText.trim().length;
3948
return textLength < 19 || textLength > 240;
4049
};
4150

51+
const handleSendReport = async () => {
52+
if (incorrectReport()) {
53+
alert({
54+
preset: 'error',
55+
title: 'Invalid Report',
56+
message: 'Report must be between 20 and 240 characters',
57+
});
58+
return;
59+
}
60+
61+
setLoading(true);
62+
try {
63+
let photoUrl = null;
64+
const user = auth().currentUser;
65+
66+
if (!user) {
67+
return;
68+
}
69+
70+
const uid = user.uid;
71+
72+
if (!uid) {
73+
return;
74+
}
75+
76+
if (userPhoto) {
77+
const photoRef = storage().ref(
78+
`bug-reports/${Date.now()}-${userPhoto?.filename}`,
79+
);
80+
await photoRef.putFile(userPhoto.path);
81+
photoUrl = await photoRef.getDownloadURL();
82+
}
83+
84+
await firestore().collection('bug_reports').add({
85+
text: reportText.trim(),
86+
screenshot: photoUrl,
87+
uid: uid,
88+
createdAt: firestore.FieldValue.serverTimestamp(),
89+
status: 'pending',
90+
});
91+
92+
alert({
93+
preset: 'done',
94+
title: 'Report Sent',
95+
message: 'Thank you for your feedback!',
96+
});
97+
98+
const randomNumber = getRandomInt(1, 3);
99+
if (__DEV__) {
100+
console.log('random number for ad is:', randomNumber);
101+
}
102+
if (randomNumber === 2) {
103+
Appodeal.show(AppodealAdType.INTERSTITIAL, 'Interstitial');
104+
}
105+
106+
navigation.goBack();
107+
} catch (error) {
108+
if (__DEV__) {
109+
console.log(error);
110+
}
111+
alert({
112+
preset: 'error',
113+
title: 'Error',
114+
message: 'Failed to send report. Please try again.',
115+
});
116+
} finally {
117+
setLoading(false);
118+
}
119+
};
120+
42121
return (
43122
<BaseView
44123
needsPaddingTop={false}
@@ -72,73 +151,77 @@ const BugReport: React.FC = () => {
72151
setReportText(text);
73152
setIsTouched(true);
74153
}}
154+
/>
155+
</View>
156+
<HelperText
157+
type={incorrectReport() ? 'error' : 'info'}
158+
visible={isTouched && incorrectReport()}>
159+
{reportText.trim().length > 240
160+
? 'Report message must be less than 240 characters.'
161+
: 'Report message must be longer than 20 characters.'}
162+
</HelperText>
163+
<View style={styles.attachView}>
164+
{userPhoto ? (
165+
<>
166+
<Image
167+
source={{uri: userPhoto?.path}}
168+
style={{
169+
marginTop: heightPercentageToDP(0.5),
170+
height: heightPercentageToDP(40),
171+
width: widthPercentageToDP(40),
172+
borderRadius: 8,
173+
resizeMode: 'cover',
174+
overflow: 'hidden',
175+
}}
75176
/>
76-
</View>
77-
<HelperText
78-
type={incorrectReport() ? 'error' : 'info'}
79-
visible={isTouched && incorrectReport()}>
80-
{reportText.trim().length > 240
81-
? 'Report message must be less than 240 characters.'
82-
: 'Report message must be longer than 20 characters.'}
83-
</HelperText>
84-
<View style={styles.attachView}>
85-
{userPhoto ? (
86-
<>
87-
<Image
88-
source={{uri: userPhoto?.path}}
177+
<Pressable
178+
style={{
179+
marginTop: heightPercentageToDP(-39),
180+
marginLeft: widthPercentageToDP(28),
181+
}}
182+
onPress={() => setUserPhoto(null)}>
183+
<Avatar.Icon
184+
size={24}
185+
icon={'close'}
89186
style={{
90-
marginTop: heightPercentageToDP(0.5),
91-
height: heightPercentageToDP(40),
92-
width: widthPercentageToDP(40),
93-
borderRadius: 8,
94-
resizeMode: 'cover',
95187
overflow: 'hidden',
96188
}}
97189
/>
98-
<Pressable
99-
style={{
100-
marginTop: heightPercentageToDP(-39),
101-
marginLeft: widthPercentageToDP(28),
102-
}}
103-
onPress={() => setUserPhoto(null)}>
104-
<Avatar.Icon
105-
size={24}
106-
icon={'close'}
107-
style={{
108-
overflow: 'hidden',
109-
}}
110-
/>
111-
</Pressable>
112-
</>
113-
) : (
114-
<Chip
115-
icon={'image-plus'}
116-
mode={'outlined'}
117-
onPress={() => {
118-
ImagePicker.openPicker({
119-
width: 1024,
120-
height: 1024,
121-
cropping: false,
122-
mediaType: 'photo',
190+
</Pressable>
191+
</>
192+
) : (
193+
<Chip
194+
icon={'image-plus'}
195+
mode={'outlined'}
196+
onPress={() => {
197+
ImagePicker.openPicker({
198+
width: 1024,
199+
height: 1024,
200+
cropping: false,
201+
mediaType: 'photo',
202+
})
203+
.then(image => {
204+
setUserPhoto(image as PhotoType);
123205
})
124-
.then(image => {
125-
setUserPhoto(image as PhotoType);
126-
})
127-
.catch(error => {
128-
if (__DEV__) {
129-
console.error(error);
130-
}
131-
});
132-
}}>
133-
Attach Photo
134-
</Chip>
135-
)}
136-
</View>
137-
<FAB
138-
style={styles.fab}
139-
icon={'send'}
140-
onPress={() => console.log('hello')}
141-
/>
206+
.catch(error => {
207+
if (__DEV__) {
208+
console.error(error);
209+
}
210+
});
211+
}}>
212+
Attach Photo
213+
</Chip>
214+
)}
215+
</View>
216+
<AppodealMrec placement={'Mrec'} />
217+
<FAB
218+
icon={'send'}
219+
label="Send Report"
220+
style={styles.fab}
221+
loading={loading}
222+
onPress={handleSendReport}
223+
disabled={loading || incorrectReport()}
224+
/>
142225
</BaseView>
143226
);
144227
};

0 commit comments

Comments
 (0)