@@ -58,6 +58,7 @@ class _FeedbackPageState extends State<FeedbackPage> {
5858 ),
5959 body: Column (
6060 mainAxisAlignment: MainAxisAlignment .start,
61+ crossAxisAlignment: CrossAxisAlignment .stretch,
6162 children: [
6263 const SizedBox (height: 10 ),
6364 Padding (
@@ -102,6 +103,87 @@ class _FeedbackPageState extends State<FeedbackPage> {
102103 ),
103104 ),
104105 ),
106+ Padding (
107+ padding: const EdgeInsets .symmetric (horizontal: 10 , vertical: 5 ),
108+ child: ElevatedButton .icon (
109+ onPressed: () async {
110+ if (_emailController.text.isEmpty &&
111+ _messageController.text.contains ('?' )) {
112+ var res = await showDialog (
113+ context: context,
114+ builder: (_) {
115+ return AlertDialog (
116+ content: Text (AppLocalizations .of (context)!
117+ .feedbackMessageContainQ),
118+ actions: [
119+ TextButton (
120+ onPressed: () {
121+ Navigator .of (context).pop (true );
122+ },
123+ child: Text (AppLocalizations .of (context)!
124+ .feedbackSendAnyway)),
125+ TextButton (
126+ onPressed: () {
127+ Navigator .of (context).pop (false );
128+ },
129+ child: Text (AppLocalizations .of (context)!
130+ .feedbackAddEmail))
131+ ],
132+ );
133+ });
134+
135+ // Cancel next operation for user to enter their email
136+ if (! res) return ;
137+ }
138+
139+ if (_formKey.currentState! .validate ()) {
140+ FocusScope .of (context).unfocus ();
141+ var payload = {
142+ 'User email' : _emailController.text.trim (),
143+ 'User message' : _messageController.text.trim (),
144+ if (_logIsChecked) 'Device info' : _deviceInfo
145+ };
146+
147+ payload.addAll (_appMetadata! );
148+ if (_isSensitiveChecked) payload.addAll (_sensitiveData! );
149+
150+ setState (() => _isSendLoading = true );
151+ try {
152+ await http.post (Uri .https (kApiBaseUrl, '/api/feedback' ),
153+ headers: {
154+ HttpHeaders .contentTypeHeader:
155+ ContentType .json.toString ()
156+ },
157+ body: jsonEncode (payload));
158+ setState (() => _isSendLoading = false );
159+ Fluttertoast .showToast (
160+ msg: AppLocalizations .of (context)! .feedbackThanks,
161+ backgroundColor: Colors .green,
162+ toastLength: Toast .LENGTH_LONG )
163+ .then ((value) => Navigator .pop (context));
164+ } catch (e) {
165+ ScaffoldMessenger .of (context).showSnackBar (SnackBar (
166+ content: Text ('Error: $e ' ),
167+ backgroundColor: Colors .red,
168+ ));
169+ setState (() => _isSendLoading = false );
170+ rethrow ;
171+ }
172+ }
173+ },
174+ icon: ! _isSendLoading
175+ ? const FaIcon (FontAwesomeIcons .paperPlane, size: 13 )
176+ : const SizedBox .shrink (),
177+ label: _isSendLoading
178+ ? const SizedBox (
179+ height: 15 ,
180+ width: 15 ,
181+ child: CircularProgressIndicator (
182+ color: Colors .white,
183+ ))
184+ : Text (AppLocalizations .of (context)! .feedbackSend),
185+ ),
186+ ),
105187 FutureBuilder (
106188 future: DeviceInfoPlugin ().androidInfo,
107189 builder: (_, AsyncSnapshot <AndroidDeviceInfo > snapshot) {
@@ -220,84 +302,8 @@ class _FeedbackPageState extends State<FeedbackPage> {
220302 onChanged: (value) {
221303 setState (() => _isSensitiveChecked = value! );
222304 }),
223- ElevatedButton .icon (
224- onPressed: () async {
225- if (_emailController.text.isEmpty &&
226- _messageController.text.contains ('?' )) {
227- var res = await showDialog (
228- context: context,
229- builder: (_) {
230- return AlertDialog (
231- content: Text (AppLocalizations .of (context)!
232- .feedbackMessageContainQ),
233- actions: [
234- TextButton (
235- onPressed: () {
236- Navigator .of (context).pop (true );
237- },
238- child: Text (AppLocalizations .of (context)!
239- .feedbackSendAnyway)),
240- TextButton (
241- onPressed: () {
242- Navigator .of (context).pop (false );
243- },
244- child: Text (AppLocalizations .of (context)!
245- .feedbackAddEmail))
246- ],
247- );
248- });
249-
250- // Cancel next operation for user to enter their email
251- if (! res) return ;
252- }
253-
254- if (_formKey.currentState! .validate ()) {
255- FocusScope .of (context).unfocus ();
256- var payload = {
257- 'User email' : _emailController.text.trim (),
258- 'User message' : _messageController.text.trim (),
259- if (_logIsChecked) 'Device info' : _deviceInfo
260- };
305+ // Send button / butang hantar
261306
262- payload.addAll (_appMetadata! );
263- if (_isSensitiveChecked) payload.addAll (_sensitiveData! );
264-
265- setState (() => _isSendLoading = true );
266- try {
267- await http.post (Uri .https (kApiBaseUrl, '/api/feedback' ),
268- headers: {
269- HttpHeaders .contentTypeHeader:
270- ContentType .json.toString ()
271- },
272- body: jsonEncode (payload));
273- setState (() => _isSendLoading = false );
274- Fluttertoast .showToast (
275- msg: AppLocalizations .of (context)! .feedbackThanks,
276- backgroundColor: Colors .green,
277- toastLength: Toast .LENGTH_LONG )
278- .then ((value) => Navigator .pop (context));
279- } catch (e) {
280- ScaffoldMessenger .of (context).showSnackBar (SnackBar (
281- content: Text ('Error: $e ' ),
282- backgroundColor: Colors .red,
283- ));
284- setState (() => _isSendLoading = false );
285- rethrow ;
286- }
287- }
288- },
289- icon: ! _isSendLoading
290- ? const FaIcon (FontAwesomeIcons .paperPlane, size: 13 )
291- : const SizedBox .shrink (),
292- label: _isSendLoading
293- ? const SizedBox (
294- height: 15 ,
295- width: 15 ,
296- child: CircularProgressIndicator (
297- color: Colors .white,
298- ))
299- : Text (AppLocalizations .of (context)! .feedbackSend),
300- ),
301307 const Spacer (flex: 3 ),
302308 Row (
303309 children: [
0 commit comments