From f45848331e32f392c6a6f61fd76296b73e32593d Mon Sep 17 00:00:00 2001
From: Pupsi28 <larslukasneuhaus@gmx.de>
Date: Sun, 31 Mar 2024 15:35:12 +0200
Subject: [PATCH 1/3] added bigger feedback dialog widget

---
 .../pages/more/feedback/feedbackDialog.dart   | 79 +++++++++++++++++++
 lib/view/pages/overhang.dart                  |  2 +-
 2 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/lib/view/pages/more/feedback/feedbackDialog.dart b/lib/view/pages/more/feedback/feedbackDialog.dart
index 69c1746..9a1da1e 100644
--- a/lib/view/pages/more/feedback/feedbackDialog.dart
+++ b/lib/view/pages/more/feedback/feedbackDialog.dart
@@ -20,6 +20,84 @@ class _FeedbackDialogState extends State<FeedbackDialog> {
 
   @override
   Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(
+        title: const Text('Feedback'),
+      ),
+      body: Column(
+        mainAxisSize: MainAxisSize.max,
+        children: [
+          const SizedBox(height: 5),
+          const Text('Feedback, Anregungen, Ideen, Fehler und Verbesserungen', textAlign: TextAlign.center),
+          const SizedBox(height: 15),
+          const Text('Bitte gib keine geheimen Daten wie z.B. Passwörter weiter.', textAlign: TextAlign.center, style: TextStyle(fontSize: 11)),
+          const SizedBox(height: 20),
+          Padding(
+            padding: const EdgeInsets.all(10),
+            child: TextField(
+              controller: _feedbackInput,
+              autofocus: true,
+              decoration: const InputDecoration(
+                  border: OutlineInputBorder(),
+                  label: Text('Feedback und Verbesserungen')
+              ),
+              // style: TextStyle(),
+              // expands: true,
+              minLines: 4,
+              maxLines: 7,
+            )
+          ),
+          Visibility(
+              visible: _error != null,
+              child: Text('Senden fehlgeschlagen: $_error', style: const TextStyle(color: Colors.red)),
+          ),
+          Padding(
+            padding: const EdgeInsets.only(right: 20),
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.end,
+              children: [
+                TextButton(
+                  onPressed: () async {
+                    AddFeedback(
+                        AddFeedbackParams(
+                            user: AccountData().getUserSecret(),
+                            feedback: _feedbackInput.text,
+                            appVersion: int.parse((await PackageInfo.fromPlatform()).buildNumber)
+                        )
+                    ).run().then((value) {
+                      Navigator.of(context).pop();
+                      InfoDialog.show(context, 'Danke für dein Feedback!');
+                    }).catchError((error, trace) {
+                      setState(() {
+                        _error = error.toString();
+                      });
+                    });
+                  },
+                  child: const Text('Senden'),
+                )
+              ]
+            )
+          )
+
+        ],
+      ),
+    );
+
+    /*
+    return Scaffold(
+      appBar: AppBar(
+        title: const Text('Raumplan'),
+      ),
+      body: PhotoView(
+        imageProvider: Image.asset('assets/img/raumplan.jpg').image,
+        minScale: 0.5,
+        maxScale: 2.0,
+        backgroundDecoration: BoxDecoration(color: Theme.of(context).colorScheme.background),
+      ),
+    );
+     */
+
+    /*
     return AlertDialog(
 
       title: const Text('Feedback'),
@@ -74,5 +152,6 @@ class _FeedbackDialogState extends State<FeedbackDialog> {
         )
       ],
     );
+     */
   }
 }
diff --git a/lib/view/pages/overhang.dart b/lib/view/pages/overhang.dart
index 020207e..4ed82c0 100644
--- a/lib/view/pages/overhang.dart
+++ b/lib/view/pages/overhang.dart
@@ -74,7 +74,7 @@ class Overhang extends StatelessWidget {
             title: const Text('Du hast eine Idee?'),
             subtitle: const Text('Fehler und Verbessungsvorschläge'),
             trailing: const Icon(Icons.arrow_right),
-            onTap: () => showDialog(context: context, barrierDismissible: false, builder: (context) => const FeedbackDialog()),
+            onTap: () => pushScreen(context, withNavBar: false, screen: const FeedbackDialog()),
           ),
         ],
       ),

From ea329d8d64bc8ca1ff9f4859f2568bc2be629979 Mon Sep 17 00:00:00 2001
From: Pupsi28 <larslukasneuhaus@gmx.de>
Date: Sun, 31 Mar 2024 21:02:47 +0200
Subject: [PATCH 2/3] added option to attach image to feedback

---
 .../server/feedback/addFeedbackParams.dart    |  2 +
 .../server/feedback/addFeedbackParams.g.dart  |  2 +
 .../pages/more/feedback/feedbackDialog.dart   | 47 +++++++++++++++++--
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/lib/api/mhsl/server/feedback/addFeedbackParams.dart b/lib/api/mhsl/server/feedback/addFeedbackParams.dart
index 4f3e8b0..3ed0c55 100644
--- a/lib/api/mhsl/server/feedback/addFeedbackParams.dart
+++ b/lib/api/mhsl/server/feedback/addFeedbackParams.dart
@@ -6,12 +6,14 @@ part 'addFeedbackParams.g.dart';
 class AddFeedbackParams {
   String user;
   String feedback;
+  String? screenshot;
   int appVersion;
 
 
   AddFeedbackParams({
     required this.user,
     required this.feedback,
+    this.screenshot,
     required this.appVersion,
   });
 
diff --git a/lib/api/mhsl/server/feedback/addFeedbackParams.g.dart b/lib/api/mhsl/server/feedback/addFeedbackParams.g.dart
index 47f2105..f401495 100644
--- a/lib/api/mhsl/server/feedback/addFeedbackParams.g.dart
+++ b/lib/api/mhsl/server/feedback/addFeedbackParams.g.dart
@@ -10,6 +10,7 @@ AddFeedbackParams _$AddFeedbackParamsFromJson(Map<String, dynamic> json) =>
     AddFeedbackParams(
       user: json['user'] as String,
       feedback: json['feedback'] as String,
+      screenshot: json['screenshot'] as String?,
       appVersion: json['appVersion'] as int,
     );
 
@@ -17,5 +18,6 @@ Map<String, dynamic> _$AddFeedbackParamsToJson(AddFeedbackParams instance) =>
     <String, dynamic>{
       'user': instance.user,
       'feedback': instance.feedback,
+      'screenshot': instance.screenshot,
       'appVersion': instance.appVersion,
     };
diff --git a/lib/view/pages/more/feedback/feedbackDialog.dart b/lib/view/pages/more/feedback/feedbackDialog.dart
index 9a1da1e..e37e858 100644
--- a/lib/view/pages/more/feedback/feedbackDialog.dart
+++ b/lib/view/pages/more/feedback/feedbackDialog.dart
@@ -1,10 +1,16 @@
 
+import 'dart:convert';
+import 'dart:typed_data';
+
 import 'package:flutter/material.dart';
+import 'package:image_picker/image_picker.dart';
+import 'package:loader_overlay/loader_overlay.dart';
 import 'package:package_info/package_info.dart';
 
 import '../../../../api/mhsl/server/feedback/addFeedback.dart';
 import '../../../../api/mhsl/server/feedback/addFeedbackParams.dart';
 import '../../../../model/accountData.dart';
+import '../../../../widget/filePick.dart';
 import '../../../../widget/infoDialog.dart';
 
 class FeedbackDialog extends StatefulWidget {
@@ -15,7 +21,10 @@ class FeedbackDialog extends StatefulWidget {
 }
 
 class _FeedbackDialogState extends State<FeedbackDialog> {
+  final ImagePicker picker = ImagePicker();
+
   final TextEditingController _feedbackInput = TextEditingController();
+  Uint8List? _image;
   String? _error;
 
   @override
@@ -39,38 +48,68 @@ class _FeedbackDialogState extends State<FeedbackDialog> {
               autofocus: true,
               decoration: const InputDecoration(
                   border: OutlineInputBorder(),
-                  label: Text('Feedback und Verbesserungen')
+                  label: Text('Feedback und Verbesserungen'),
               ),
               // style: TextStyle(),
               // expands: true,
               minLines: 4,
               maxLines: 7,
-            )
+            ),
+          ),
+          if(_image != null) Container(
+            decoration: BoxDecoration(
+              borderRadius: const BorderRadius.all(Radius.circular(5)),
+              border: Border.all(
+                width: 3,
+                color: Theme.of(context).primaryColor,
+              ),
+            ),
+            height: 150,
+            child: Image(
+              image: Image.memory(_image!).image,
+              fit: BoxFit.contain,
+            ),
           ),
           Visibility(
               visible: _error != null,
               child: Text('Senden fehlgeschlagen: $_error', style: const TextStyle(color: Colors.red)),
           ),
           Padding(
-            padding: const EdgeInsets.only(right: 20),
+            padding: const EdgeInsets.only(right: 20, left: 10),
             child: Row(
               mainAxisAlignment: MainAxisAlignment.end,
               children: [
+                IconButton(
+                  onPressed: () async {
+                    context.loaderOverlay.show();
+                    var imageData = await (await FilePick.galleryPick())?.readAsBytes();
+                    context.loaderOverlay.hide();
+                    setState(() {
+                      _image = imageData;
+                    });
+                  },
+                  icon: const Icon(Icons.attach_file_outlined),
+                ),
+                const Expanded(child: SizedBox.shrink()),
                 TextButton(
                   onPressed: () async {
+                    context.loaderOverlay.show();
                     AddFeedback(
                         AddFeedbackParams(
                             user: AccountData().getUserSecret(),
                             feedback: _feedbackInput.text,
-                            appVersion: int.parse((await PackageInfo.fromPlatform()).buildNumber)
+                            screenshot: _image != null ? base64Encode(_image!) : null,
+                            appVersion: int.parse((await PackageInfo.fromPlatform()).buildNumber),
                         )
                     ).run().then((value) {
                       Navigator.of(context).pop();
                       InfoDialog.show(context, 'Danke für dein Feedback!');
+                      context.loaderOverlay.hide();
                     }).catchError((error, trace) {
                       setState(() {
                         _error = error.toString();
                       });
+                      context.loaderOverlay.hide();
                     });
                   },
                   child: const Text('Senden'),

From 07b32f1e32fb5df0eed9057ef6ba47d42eb3a91a Mon Sep 17 00:00:00 2001
From: Pupsi28 <larslukasneuhaus@gmx.de>
Date: Mon, 1 Apr 2024 12:57:27 +0200
Subject: [PATCH 3/3] added option to attach image to feedback

---
 .../pages/more/feedback/feedbackDialog.dart   | 177 ++++++++----------
 1 file changed, 77 insertions(+), 100 deletions(-)

diff --git a/lib/view/pages/more/feedback/feedbackDialog.dart b/lib/view/pages/more/feedback/feedbackDialog.dart
index e37e858..3f63e26 100644
--- a/lib/view/pages/more/feedback/feedbackDialog.dart
+++ b/lib/view/pages/more/feedback/feedbackDialog.dart
@@ -6,10 +6,13 @@ import 'package:flutter/material.dart';
 import 'package:image_picker/image_picker.dart';
 import 'package:loader_overlay/loader_overlay.dart';
 import 'package:package_info/package_info.dart';
+import 'package:provider/provider.dart';
+import 'package:badges/badges.dart' as badges;
 
 import '../../../../api/mhsl/server/feedback/addFeedback.dart';
 import '../../../../api/mhsl/server/feedback/addFeedbackParams.dart';
 import '../../../../model/accountData.dart';
+import '../../../../storage/base/settingsProvider.dart';
 import '../../../../widget/filePick.dart';
 import '../../../../widget/infoDialog.dart';
 
@@ -26,6 +29,18 @@ class _FeedbackDialogState extends State<FeedbackDialog> {
   final TextEditingController _feedbackInput = TextEditingController();
   Uint8List? _image;
   String? _error;
+  bool _textFieldEmpty = false;
+
+  @override
+  void initState() {
+    super.initState();
+    _feedbackInput.addListener(() {
+      setState(() {
+        _textFieldEmpty = _feedbackInput.text.isEmpty;
+        _error = null;
+      });
+    });
+  }
 
   @override
   Widget build(BuildContext context) {
@@ -46,53 +61,85 @@ class _FeedbackDialogState extends State<FeedbackDialog> {
             child: TextField(
               controller: _feedbackInput,
               autofocus: true,
-              decoration: const InputDecoration(
-                  border: OutlineInputBorder(),
-                  label: Text('Feedback und Verbesserungen'),
+              decoration: InputDecoration(
+                  border: const OutlineInputBorder(),
+                  label: const Text('Feedback und Verbesserungen'),
+                  errorText: _textFieldEmpty ? 'Bitte gib eine Beschreibung an' : null,
               ),
-              // style: TextStyle(),
-              // expands: true,
               minLines: 4,
               maxLines: 7,
             ),
           ),
-          if(_image != null) Container(
-            decoration: BoxDecoration(
-              borderRadius: const BorderRadius.all(Radius.circular(5)),
-              border: Border.all(
-                width: 3,
-                color: Theme.of(context).primaryColor,
+          const SizedBox(height: 10),
+          if(_image != null) Row(
+            mainAxisAlignment: MainAxisAlignment.center,
+            children: [
+              badges.Badge(
+                badgeContent: const Icon(Icons.close_outlined, size: 17),
+                badgeStyle: const badges.BadgeStyle(
+                  padding: EdgeInsets.all(2),
+                ),
+                child: Container(
+                  decoration: BoxDecoration(
+                    borderRadius: const BorderRadius.all(Radius.circular(5)),
+                    border: Border.all(
+                      width: 3,
+                      color: Theme.of(context).primaryColor,
+                    ),
+                  ),
+                  height: 150,
+                  child: Image(
+                    image: Image.memory(_image!).image,
+                    fit: BoxFit.contain,
+                  ),
+                ),
+                onTap: () async {
+                  setState(() {
+                    _image = null;
+                  });
+                },
+              ),
+            ],
+          ),
+          Padding(
+            padding: const EdgeInsets.all(5),
+            child: Visibility(
+              visible: _error != null,
+              child: Visibility(
+                visible: Provider.of<SettingsProvider>(context, listen: false).val().devToolsEnabled,
+                replacement: const Text('Senden fehlgeschlagen, bitte überprüfe die Internetverbindung.', textAlign: TextAlign.center, style: TextStyle(color: Colors.red)),
+                child: Text('Senden fehlgeschlagen: \n $_error', textAlign: TextAlign.center, style: const TextStyle(color: Colors.red)),
               ),
             ),
-            height: 150,
-            child: Image(
-              image: Image.memory(_image!).image,
-              fit: BoxFit.contain,
-            ),
-          ),
-          Visibility(
-              visible: _error != null,
-              child: Text('Senden fehlgeschlagen: $_error', style: const TextStyle(color: Colors.red)),
           ),
           Padding(
             padding: const EdgeInsets.only(right: 20, left: 10),
             child: Row(
               mainAxisAlignment: MainAxisAlignment.end,
               children: [
-                IconButton(
-                  onPressed: () async {
-                    context.loaderOverlay.show();
-                    var imageData = await (await FilePick.galleryPick())?.readAsBytes();
-                    context.loaderOverlay.hide();
-                    setState(() {
-                      _image = imageData;
-                    });
-                  },
-                  icon: const Icon(Icons.attach_file_outlined),
+                Visibility(
+                  visible: _image == null,
+                  child: IconButton(
+                    onPressed: () async {
+                      context.loaderOverlay.show();
+                      var imageData = await (await FilePick.galleryPick())?.readAsBytes();
+                      context.loaderOverlay.hide();
+                      setState(() {
+                        _image = imageData;
+                      });
+                    },
+                    icon: const Icon(Icons.attach_file_outlined),
+                  ),
                 ),
                 const Expanded(child: SizedBox.shrink()),
                 TextButton(
                   onPressed: () async {
+                    if(_feedbackInput.text.isEmpty){
+                      setState(() {
+                        _textFieldEmpty = true;
+                      });
+                      return;
+                    }
                     context.loaderOverlay.show();
                     AddFeedback(
                         AddFeedbackParams(
@@ -122,75 +169,5 @@ class _FeedbackDialogState extends State<FeedbackDialog> {
       ),
     );
 
-    /*
-    return Scaffold(
-      appBar: AppBar(
-        title: const Text('Raumplan'),
-      ),
-      body: PhotoView(
-        imageProvider: Image.asset('assets/img/raumplan.jpg').image,
-        minScale: 0.5,
-        maxScale: 2.0,
-        backgroundDecoration: BoxDecoration(color: Theme.of(context).colorScheme.background),
-      ),
-    );
-     */
-
-    /*
-    return AlertDialog(
-
-      title: const Text('Feedback'),
-      content: Column(
-        mainAxisSize: MainAxisSize.min,
-        children: [
-          const Text('Feedback, Anregungen, Ideen, Fehler und Verbesserungen'),
-          const SizedBox(height: 10),
-          const Text('Bitte gib keine geheimen Daten wie z.B. Passwörter weiter.', style: TextStyle(fontSize: 10)),
-          const SizedBox(height: 10),
-          TextField(
-            controller: _feedbackInput,
-            autofocus: true,
-            decoration: const InputDecoration(
-              border: OutlineInputBorder(),
-              label: Text('Feedback und Verbesserungen')
-            ),
-            // style: TextStyle(),
-            // expands: true,
-            minLines: 3,
-            maxLines: 5,
-          ),
-          Visibility(
-            visible: _error != null,
-            child: Text('Senden fehlgeschlagen: $_error', style: const TextStyle(color: Colors.red))
-          )
-        ],
-      ),
-      actions: [
-        TextButton(onPressed: () => Navigator.of(context).pop(), child: const Text('Abbrechen')),
-        TextButton(
-          onPressed: () async {
-            AddFeedback(
-              AddFeedbackParams(
-                user: AccountData().getUserSecret(),
-                feedback: _feedbackInput.text,
-                appVersion: int.parse((await PackageInfo.fromPlatform()).buildNumber)
-              )
-            )
-            .run()
-            .then((value) {
-              Navigator.of(context).pop();
-              InfoDialog.show(context, 'Danke für dein Feedback!');
-            })
-            .catchError((error, trace) {
-                setState(() {
-                  _error = error.toString();
-                });
-            });
-          },
-          child: const Text('Senden'),
-        )
-      ],
-    );
-     */
   }
 }