Commit cd2e4b8

derdilla <derdilla06@gmail.com>
2023-09-11 17:32:19
add fallback screen
1 parent f16c5af
Changed files (1)
lib/screens/error_reporting.dart
@@ -0,0 +1,146 @@
+import 'dart:io';
+
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:package_info_plus/package_info_plus.dart';
+import 'package:path/path.dart';
+import 'package:share_plus/share_plus.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+import 'package:sqflite/sqflite.dart';
+import 'package:url_launcher/url_launcher.dart';
+
+// TODO: test
+class ErrorReporting {
+  static bool isErrorState = false;
+  ErrorReporting._create();
+
+  /// Replaces the application with an ErrorScreen
+  /// This method can be used to avoid running any further code in your current function, by awaiting
+  static Future<void> reportCriticalError(String title, String text) async {
+    if (isErrorState) throw Exception('Tried to report another error:\n title = $title,\n text = $text');
+    isErrorState = true;
+    runApp(ErrorScreen(
+      title: title,
+      text: text,
+      debugInfo: await _carefullyCollectDebugInfo(),
+    ));
+    return Future.delayed(const Duration(days: 30,));
+  }
+
+  static Future<PackageInfo> _carefullyCollectDebugInfo() async {
+    PackageInfo packageInfo;
+    try {
+      packageInfo = await PackageInfo.fromPlatform();
+    } catch (e) {
+      packageInfo = PackageInfo(appName: 'err', packageName: 'err', version: 'err', buildNumber: 'err');
+    }
+
+    return packageInfo;
+  }
+}
+
+class ErrorScreen extends StatelessWidget {
+  final String title;
+  final String text;
+  final PackageInfo debugInfo;
+  
+  const ErrorScreen({super.key, required this.title, required this.text, required this.debugInfo});
+
+  @override
+  Widget build(BuildContext context) {
+    return MaterialApp(
+      title: 'Critical error',
+      home: Scaffold(
+        appBar: AppBar(
+          title: const Text('Critical error'),
+          backgroundColor: Colors.red,
+        ),
+        body: Builder(
+          builder: (context) {
+            final scaffoldMessenger = ScaffoldMessenger.of(context);
+            return SingleChildScrollView(
+              child: Column(
+                mainAxisSize: MainAxisSize.min,
+                children: [
+                  const SizedBox(height: 20,),
+                  Text('App version: ${debugInfo.version}'),
+                  Text('Build number: ${debugInfo.buildNumber}'),
+                  const Divider(),
+                  Text(title),
+                  Text(text),
+                  const Divider(),
+                  TextButton(
+                    onPressed: () {
+                      Clipboard.setData(ClipboardData(
+                        text: 'Error:\nBuild number:${debugInfo.buildNumber}\n-----\n$title:\n---\n$text\n'
+                      ));
+                      scaffoldMessenger.showSnackBar(const SnackBar(
+                          content: Text('Copied to clipboard')));
+                    },
+                    child: const Text('copy error message')
+                  ),
+                  TextButton(
+                      onPressed: () async {
+                        try {
+                          final url = Uri.parse('https://github.com/NobodyForNothing/blood-pressure-monitor-fl/issues');
+                          if (await canLaunchUrl(url)) {
+                            await launchUrl(url, mode: LaunchMode.externalApplication);
+                          } else {
+                            scaffoldMessenger.showSnackBar(const SnackBar(
+                              content: Text('ERR: Please open this website: https://github.com/NobodyForNothing/blood-pressure-monitor-fl/issues')));
+                          }
+                        } catch (e) {
+                          scaffoldMessenger.showSnackBar(SnackBar(
+                              content: Text('ERR: ${e.toString()}')));
+                        }
+                      },
+                      child: const Text('open issue reporting website')
+                  ),
+                  TextButton(
+                      onPressed: () async {
+                        try {
+                          var dbPath = await getDatabasesPath();
+
+                          assert(dbPath != inMemoryDatabasePath);
+                          dbPath = join(dbPath, 'blood_pressure.db');
+                          assert(Platform.isAndroid);
+                          Share.shareXFiles([
+                            XFile(dbPath,)
+                          ]);
+                        } catch(e) {
+                          scaffoldMessenger.showSnackBar(SnackBar(
+                              content: Text('ERR: ${e.toString()}')));
+                        }
+                      },
+                      child: const Text('rescue measurements')
+                  ),
+                  TextButton(
+                      onPressed: () async {
+                        try {
+                          final prefs = await SharedPreferences.getInstance();
+                          var prefsText = '';
+                          for (final key in prefs.getKeys()) {
+                            prefsText += '$key:\t${prefs.get(key).toString()}\n';
+                          }
+                          Clipboard.setData(ClipboardData(
+                              text: prefsText
+                          ));
+                          scaffoldMessenger.showSnackBar(const SnackBar(
+                              content: Text('Copied to clipboard')));
+                        } catch(e) {
+                          scaffoldMessenger.showSnackBar(SnackBar(
+                              content: Text('ERR: ${e.toString()}')));
+                        }
+                      },
+                      child: const Text('export settings')
+                  ),
+                ],
+              ),
+            );
+          }
+        ),
+      ),
+    );
+  }
+  
+}
\ No newline at end of file