develop-biggerFeedbackWidget #51

Merged
MineTec merged 4 commits from develop-biggerFeedbackWidget into develop 2024-04-02 07:32:53 +00:00
4 changed files with 147 additions and 48 deletions

View File

@ -6,12 +6,14 @@ part 'addFeedbackParams.g.dart';
class AddFeedbackParams { class AddFeedbackParams {
String user; String user;
String feedback; String feedback;
String? screenshot;
int appVersion; int appVersion;
AddFeedbackParams({ AddFeedbackParams({
required this.user, required this.user,
required this.feedback, required this.feedback,
this.screenshot,
required this.appVersion, required this.appVersion,
}); });

View File

@ -10,6 +10,7 @@ AddFeedbackParams _$AddFeedbackParamsFromJson(Map<String, dynamic> json) =>
AddFeedbackParams( AddFeedbackParams(
user: json['user'] as String, user: json['user'] as String,
feedback: json['feedback'] as String, feedback: json['feedback'] as String,
screenshot: json['screenshot'] as String?,
appVersion: json['appVersion'] as int, appVersion: json['appVersion'] as int,
); );
@ -17,5 +18,6 @@ Map<String, dynamic> _$AddFeedbackParamsToJson(AddFeedbackParams instance) =>
<String, dynamic>{ <String, dynamic>{
'user': instance.user, 'user': instance.user,
'feedback': instance.feedback, 'feedback': instance.feedback,
'screenshot': instance.screenshot,
'appVersion': instance.appVersion, 'appVersion': instance.appVersion,
}; };

View File

@ -1,10 +1,19 @@
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/material.dart'; 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: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/addFeedback.dart';
import '../../../../api/mhsl/server/feedback/addFeedbackParams.dart'; import '../../../../api/mhsl/server/feedback/addFeedbackParams.dart';
import '../../../../model/accountData.dart'; import '../../../../model/accountData.dart';
import '../../../../storage/base/settingsProvider.dart';
import '../../../../widget/filePick.dart';
import '../../../../widget/infoDialog.dart'; import '../../../../widget/infoDialog.dart';
class FeedbackDialog extends StatefulWidget { class FeedbackDialog extends StatefulWidget {
@ -15,64 +24,150 @@ class FeedbackDialog extends StatefulWidget {
} }
class _FeedbackDialogState extends State<FeedbackDialog> { class _FeedbackDialogState extends State<FeedbackDialog> {
final ImagePicker picker = ImagePicker();
final TextEditingController _feedbackInput = TextEditingController(); final TextEditingController _feedbackInput = TextEditingController();
Uint8List? _image;
String? _error; String? _error;
bool _textFieldEmpty = false;
@override
void initState() {
super.initState();
_feedbackInput.addListener(() {
setState(() {
_textFieldEmpty = _feedbackInput.text.isEmpty;
_error = null;
});
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return Scaffold(
appBar: AppBar(
title: const Text('Feedback'), title: const Text('Feedback'),
content: Column( ),
mainAxisSize: MainAxisSize.min, body: Column(
mainAxisSize: MainAxisSize.max,
children: [ children: [
Pupsi marked this conversation as resolved
Review

?

?
const Text('Feedback, Anregungen, Ideen, Fehler und Verbesserungen'), const SizedBox(height: 5),
const SizedBox(height: 10), const Text('Feedback, Anregungen, Ideen, Fehler und Verbesserungen', textAlign: TextAlign.center),
const Text('Bitte gib keine geheimen Daten wie z.B. Passwörter weiter.', style: TextStyle(fontSize: 10)), const SizedBox(height: 15),
const SizedBox(height: 10), const Text('Bitte gib keine geheimen Daten wie z.B. Passwörter weiter.', textAlign: TextAlign.center, style: TextStyle(fontSize: 11)),
TextField( const SizedBox(height: 20),
controller: _feedbackInput, Padding(
autofocus: true, padding: const EdgeInsets.all(10),
decoration: const InputDecoration( child: TextField(
border: OutlineInputBorder(), controller: _feedbackInput,
label: Text('Feedback und Verbesserungen') 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( const SizedBox(height: 10),
visible: _error != null, if(_image != null) Row(
child: Text('Senden fehlgeschlagen: $_error', style: const TextStyle(color: Colors.red)) mainAxisAlignment: MainAxisAlignment.center,
Pupsi marked this conversation as resolved Outdated

bitte hier nochmal auf das Design achten, du kannst einen offline betrieb im emulator mithilfe des flugmodus in der Benachrichtigungsleiste simulieren

bitte hier nochmal auf das Design achten, du kannst einen offline betrieb im emulator mithilfe des flugmodus in der Benachrichtigungsleiste simulieren
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();
Pupsi marked this conversation as resolved Outdated

raus wenn es nicht benötigt wird

raus wenn es nicht benötigt wird
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'),
)
],
); );
} }
} }

View File

@ -74,7 +74,7 @@ class Overhang extends StatelessWidget {
title: const Text('Du hast eine Idee?'), title: const Text('Du hast eine Idee?'),
subtitle: const Text('Fehler und Verbessungsvorschläge'), subtitle: const Text('Fehler und Verbessungsvorschläge'),
trailing: const Icon(Icons.arrow_right), trailing: const Icon(Icons.arrow_right),
onTap: () => showDialog(context: context, barrierDismissible: false, builder: (context) => const FeedbackDialog()), onTap: () => pushScreen(context, withNavBar: false, screen: const FeedbackDialog()),
), ),
], ],
), ),