diff --git a/assets/translations/en.json b/assets/translations/en.json index 6b632bf0b0164006be8ad2c0116cbba84c2eb300..db9beb9da508e3bfd6d4d0821ee8fe8f963de8cc 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -227,5 +227,10 @@ "cesium_secret_phrase": "Secret phrase", "cesium_password": "Password", "accept": "ACCEPT", - "incorrect_passwords": "Incorrect passwords" + "incorrect_passwords": "Incorrect passwords", + "issueCreatedTitle": "Issue Created", + "issueCreatedSuccessfully": "The issue has been successfully created.", + "viewIssue": "View Issue", + "issueCreationErrorTitle": "Error Creating Issue", + "issueCreationErrorMessage": "There was an error trying to create the issue." } diff --git a/assets/translations/es.json b/assets/translations/es.json index 9a955e3617e975fdd6e98c899b4993d0cfc5046d..b98c54f6a51903f891c2328282a29508866a1157 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -233,5 +233,10 @@ "cesium_password": "Contraseña", "accept": "ACEPTAR", "incorrect_passwords": "Contraseñas incorrectas", - "card_name_changed": "El nombre de tu tarjeta ha sido actualizado. Recuerda que este nombre es público y permite a otr@s encontrarte" + "card_name_changed": "El nombre de tu tarjeta ha sido actualizado. Recuerda que este nombre es público y permite a otr@s encontrarte", + "issueCreatedTitle": "Issue Creada", + "issueCreatedSuccessfully": "La issue ha sido creada exitosamente.", + "viewIssue": "Ver Issue", + "issueCreationErrorTitle": "Error al Crear Issue", + "issueCreationErrorMessage": "Ocurrió un error al intentar crear la issue." } diff --git a/lib/ui/widgets/card_drawer.dart b/lib/ui/widgets/card_drawer.dart index c96ef2cf8a2407af85ece6202b29b26e7d66ee05..26f3fb090b6b003be5651f5daa0d41c31ba346fe 100644 --- a/lib/ui/widgets/card_drawer.dart +++ b/lib/ui/widgets/card_drawer.dart @@ -1,23 +1,29 @@ +import 'dart:convert'; + import 'package:easy_localization/easy_localization.dart'; import 'package:feedback_gitlab/feedback_gitlab.dart'; import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:http/http.dart' as http; import 'package:package_info_plus/package_info_plus.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import '../../data/models/cesium_card.dart'; +import '../../main.dart'; import '../../shared_prefs_helper.dart'; import '../screens/sandbox.dart'; import '../ui_helpers.dart'; import 'first_screen/card_stack.dart'; +typedef IssueCreatedCallback = void Function( + String? issueUrl, Map<String, dynamic> issueData, bool isSuccess); + class CardDrawer extends StatelessWidget { const CardDrawer({super.key}); @override Widget build(BuildContext context) { final List<CesiumCard> cards = SharedPreferencesHelper().cesiumCards; - return FutureBuilder<PackageInfo>( future: PackageInfo.fromPlatform(), builder: (BuildContext context, AsyncSnapshot<PackageInfo> snapshot) { @@ -94,11 +100,80 @@ class CardDrawer extends StatelessWidget { onTap: () { Navigator.pop(context); final String gitLabToken = dotenv.get('GITLAB_TOKEN', - fallback: 'FKb9GMueV4-hyDEWjfAf'); + fallback: 'xjxXTv3ZRzKsc4SPTN4s'); + + final FeedbackController betterFeedback = + BetterFeedback.of(context); + final MyCustomHttpClient httpClient = + MyCustomHttpClient(http.Client()); + + void listener() { + if (!betterFeedback.isVisible && + httpClient.responseDataNotifier.value != null) { + final Map<String, dynamic>? issueData = + httpClient.responseDataNotifier.value; + final String? issueUrl = + issueData?['web_url'] as String?; + if (issueUrl != null) { + showDialog( + context: GinkgoApp.navigatorKey.currentContext!, + builder: (BuildContext dialogContext) { + return AlertDialog( + title: Text(tr('issueCreatedTitle')), + content: Column( + mainAxisSize: MainAxisSize.min, + children: <Widget>[ + Text(tr('issueCreatedSuccessfully')), + if (issueUrl != null) + TextButton( + onPressed: () { + openUrl(issueUrl); + }, + child: Text(tr('viewIssue')), + ), + ], + ), + actions: <Widget>[ + TextButton( + onPressed: () { + Navigator.of(dialogContext).pop(); + }, + child: Text(tr('close')), + ), + ], + ); + }, + ); + } else { + showDialog( + context: GinkgoApp.navigatorKey.currentContext!, + builder: (BuildContext dialogContext) { + return AlertDialog( + title: Text(tr('issueCreationErrorTitle')), + content: Text(tr('issueCreationErrorMessage')), + actions: <Widget>[ + TextButton( + onPressed: () { + Navigator.of(dialogContext).pop(); + }, + child: Text(tr('close')), + ), + ], + ); + }, + ); + } + } + } + + betterFeedback.addListener(listener); + // TODO remove this + BetterFeedback.of(context).showAndUploadToGitLab( projectId: '663', apiToken: gitLabToken, - gitlabUrl: 'git.duniter.org'); + gitlabUrl: 'git.duniter.org', + client: httpClient); /* BetterFeedback.of(context).showAndUploadToSentry( // name: 'Foo Bar', // email: 'foo_bar@example.com', @@ -133,3 +208,38 @@ Future<void> tryCatch() async { await Sentry.captureException(error, stackTrace: stackTrace); } } + +class MyCustomHttpClient extends http.BaseClient { + MyCustomHttpClient(this._inner); + + final http.Client _inner; + + final ValueNotifier<Map<String, dynamic>?> responseDataNotifier = + ValueNotifier<Map<String, dynamic>?>(null); + + @override + Future<http.StreamedResponse> send(http.BaseRequest request) async { + final http.StreamedResponse response = await _inner.send(request); + + if (request.url.path.contains('/api/v4/projects/') && + request.url.path.contains('/issues')) { + final String responseBody = await response.stream.bytesToString(); + final Map<String, dynamic> issueData = + json.decode(responseBody) as Map<String, dynamic>; + + responseDataNotifier.value = issueData; + + final Stream<List<int>> newStream = + Stream<List<int>>.value(utf8.encode(responseBody)); + return http.StreamedResponse(newStream, response.statusCode, + contentLength: response.contentLength, + request: response.request, + headers: response.headers, + isRedirect: response.isRedirect, + persistentConnection: response.persistentConnection, + reasonPhrase: response.reasonPhrase); + } + + return response; + } +}