develop-biggerFeedbackWidget #51
@@ -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,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,19 @@
 | 
			
		||||
 | 
			
		||||
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 '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';
 | 
			
		||||
 | 
			
		||||
class FeedbackDialog extends StatefulWidget {
 | 
			
		||||
@@ -15,64 +24,150 @@ class FeedbackDialog extends StatefulWidget {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _FeedbackDialogState extends State<FeedbackDialog> {
 | 
			
		||||
  final ImagePicker picker = ImagePicker();
 | 
			
		||||
 | 
			
		||||
  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) {
 | 
			
		||||
    return AlertDialog(
 | 
			
		||||
 | 
			
		||||
      title: const Text('Feedback'),
 | 
			
		||||
      content: Column(
 | 
			
		||||
        mainAxisSize: MainAxisSize.min,
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: AppBar(
 | 
			
		||||
        title: const Text('Feedback'),
 | 
			
		||||
      ),
 | 
			
		||||
      body: Column(
 | 
			
		||||
        mainAxisSize: MainAxisSize.max,
 | 
			
		||||
        children: [
 | 
			
		||||
| 
					
	
	
	
	
	
	
	
	 
					
					Pupsi marked this conversation as resolved
					
				 
				 | 
			||||
          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')
 | 
			
		||||
          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: InputDecoration(
 | 
			
		||||
                  border: const OutlineInputBorder(),
 | 
			
		||||
                  label: const Text('Feedback und Verbesserungen'),
 | 
			
		||||
                  errorText: _textFieldEmpty ? 'Bitte gib eine Beschreibung an' : null,
 | 
			
		||||
              ),
 | 
			
		||||
              minLines: 4,
 | 
			
		||||
              maxLines: 7,
 | 
			
		||||
            ),
 | 
			
		||||
            // style: TextStyle(),
 | 
			
		||||
            // expands: true,
 | 
			
		||||
            minLines: 3,
 | 
			
		||||
            maxLines: 5,
 | 
			
		||||
          ),
 | 
			
		||||
          Visibility(
 | 
			
		||||
            visible: _error != null,
 | 
			
		||||
            child: Text('Senden fehlgeschlagen: $_error', style: const TextStyle(color: Colors.red))
 | 
			
		||||
          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)),
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
          Padding(
 | 
			
		||||
            padding: const EdgeInsets.only(right: 20, left: 10),
 | 
			
		||||
            child: Row(
 | 
			
		||||
              mainAxisAlignment: MainAxisAlignment.end,
 | 
			
		||||
              children: [
 | 
			
		||||
                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(
 | 
			
		||||
                            user: AccountData().getUserSecret(),
 | 
			
		||||
                            feedback: _feedbackInput.text,
 | 
			
		||||
                            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'),
 | 
			
		||||
                )
 | 
			
		||||
              ]
 | 
			
		||||
            )
 | 
			
		||||
          )
 | 
			
		||||
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
      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'),
 | 
			
		||||
        )
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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()),
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user
	
?