Skip to content

Commit 0a940fd

Browse files
committed
🔧 Update feedback submit URL
And cleanup the page a bit
1 parent 097aa6c commit 0a940fd

File tree

4 files changed

+364
-276
lines changed

4 files changed

+364
-276
lines changed

lib/env.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
// API base
55
const envApiBaseHost = 'mpt-server.vercel.app';
6+
const feedbackSubmissionUrl = 'https://feedback.waktusolat.app/api/send';
67

78
//App info
89
const envPlayStoreListingLink =

lib/features/feedback/services/feedback_submission_service.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ class FeedbackSubmissionService {
99
static Future<void> submitFeedback(String message,
1010
{String? email, Map<String, dynamic>? otherPayloads}) async {
1111
final payload = {
12-
'User email': email,
13-
'User message': message,
12+
'email': email,
13+
'message': message,
1414
};
1515

1616
final body = {
1717
...payload,
1818
if (otherPayloads != null) ...otherPayloads,
1919
};
2020

21-
final feedbackApiUri = Uri.https(envApiBaseHost).resolve('/api/feedback');
21+
final feedbackApiUri = Uri.parse(feedbackSubmissionUrl);
2222

2323
await http.post(
2424
feedbackApiUri,
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import 'dart:developer';
2+
import 'dart:io';
3+
4+
import 'package:device_info_plus/device_info_plus.dart';
5+
import 'package:flutter/material.dart';
6+
import 'package:get_storage/get_storage.dart';
7+
import 'package:package_info_plus/package_info_plus.dart';
8+
9+
import '../../../constants.dart';
10+
import '../../../location_utils/location_data.dart';
11+
import '../services/feedback_submission_service.dart';
12+
13+
class FeedbackViewModel extends ChangeNotifier {
14+
final TextEditingController messageController = TextEditingController();
15+
final TextEditingController emailController = TextEditingController();
16+
final formKey = GlobalKey<FormState>();
17+
18+
Map<String, dynamic>? deviceInfo;
19+
Map<String, dynamic>? appMetadata;
20+
Map<String, dynamic>? sensitiveData;
21+
22+
bool isSendLoading = false;
23+
bool logIsChecked = true;
24+
bool isSensitiveChecked = false;
25+
26+
FeedbackViewModel() {
27+
_initSensitiveData();
28+
}
29+
30+
void _initSensitiveData() {
31+
sensitiveData = {
32+
'Recent GPS':
33+
'${LocationData.position?.latitude},${LocationData.position?.longitude}',
34+
};
35+
}
36+
37+
void toggleLogChecked(bool value) {
38+
logIsChecked = value;
39+
notifyListeners();
40+
}
41+
42+
void toggleSensitiveChecked(bool value) {
43+
isSensitiveChecked = value;
44+
notifyListeners();
45+
}
46+
47+
Future<bool> validateAndSubmitFeedback(BuildContext context) async {
48+
if (formKey.currentState?.validate() ?? false) {
49+
isSendLoading = true;
50+
notifyListeners();
51+
52+
try {
53+
debugPrint('Sending feedback...');
54+
await FeedbackSubmissionService.submitFeedback(
55+
messageController.text.trim(),
56+
email: emailController.text.trim(),
57+
otherPayloads: {
58+
'app_info': appMetadata,
59+
if (logIsChecked) 'device_info': deviceInfo,
60+
if (isSensitiveChecked) 'additional_info': sensitiveData
61+
},
62+
);
63+
64+
isSendLoading = false;
65+
notifyListeners();
66+
return true;
67+
} catch (e) {
68+
isSendLoading = false;
69+
notifyListeners();
70+
return false;
71+
}
72+
}
73+
return false;
74+
}
75+
76+
Future<void> loadDeviceInfo(BuildContext context) async {
77+
try {
78+
final deviceInfoPlugin = DeviceInfoPlugin();
79+
final androidInfo = await deviceInfoPlugin.androidInfo;
80+
81+
deviceInfo = {
82+
'Android version': androidInfo.version.release,
83+
'Android Sdk': androidInfo.version.sdkInt,
84+
'Device': androidInfo.device,
85+
'Brand': androidInfo.brand,
86+
'Model': androidInfo.model,
87+
'Supported ABIs': androidInfo.supportedAbis,
88+
'Screen Sizes': MediaQuery.of(context).size.toString(),
89+
'Timezone': DateTime.now().timeZoneOffset.toString(),
90+
'Device Locale': Platform.localeName,
91+
};
92+
} catch (e) {
93+
log('Error loading device info: $e');
94+
deviceInfo = null;
95+
} finally {
96+
notifyListeners();
97+
}
98+
}
99+
100+
Future<void> loadAppMetadata(BuildContext context, String locale) async {
101+
try {
102+
final packageInfo = await PackageInfo.fromPlatform();
103+
104+
appMetadata = {
105+
'App version': packageInfo.version,
106+
'App build number': packageInfo.buildNumber,
107+
'Prayer API': GetStorage().read(kStoredApiPrayerCall),
108+
'zone': GetStorage().read(kStoredLocationJakimCode),
109+
'app locale': locale,
110+
};
111+
} catch (e) {
112+
log('Error loading app metadata: $e');
113+
appMetadata = null;
114+
} finally {
115+
notifyListeners();
116+
}
117+
}
118+
119+
bool hasQuestionMark() {
120+
return messageController.text.contains('?');
121+
}
122+
123+
bool isEmailEmpty() {
124+
return emailController.text.isEmpty;
125+
}
126+
127+
@override
128+
void dispose() {
129+
messageController.dispose();
130+
emailController.dispose();
131+
super.dispose();
132+
}
133+
}

0 commit comments

Comments
 (0)