diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 920f7ab..06b85eb 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -112,5 +112,12 @@ + + + + + + diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 9393f36..a9d679d 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -45,6 +45,8 @@ "settings": "Einstellungen", "about": "Über", + "reportBug": "Fehler melden", + "couldNotOpenLink": "Link konnte nicht geöffnet werden", "appSettings": "App-Einstellungen", "theme": "Design", "themeLight": "Hell", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index a6a6e11..14355af 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -45,6 +45,8 @@ "settings": "Settings", "about": "About", + "reportBug": "Report Bug", + "couldNotOpenLink": "Could not open link", "appSettings": "App Settings", "theme": "Theme", "themeLight": "Light", diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 855eec9..c5020f5 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -356,6 +356,18 @@ abstract class AppLocalizations { /// **'About'** String get about; + /// No description provided for @reportBug. + /// + /// In en, this message translates to: + /// **'Report Bug'** + String get reportBug; + + /// No description provided for @couldNotOpenLink. + /// + /// In en, this message translates to: + /// **'Could not open link'** + String get couldNotOpenLink; + /// No description provided for @appSettings. /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index ed82870..7216340 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -137,6 +137,12 @@ class AppLocalizationsDe extends AppLocalizations { @override String get about => 'Über'; + @override + String get reportBug => 'Fehler melden'; + + @override + String get couldNotOpenLink => 'Link konnte nicht geöffnet werden'; + @override String get appSettings => 'App-Einstellungen'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index efd3b48..3a6600c 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -137,6 +137,12 @@ class AppLocalizationsEn extends AppLocalizations { @override String get about => 'About'; + @override + String get reportBug => 'Report Bug'; + + @override + String get couldNotOpenLink => 'Could not open link'; + @override String get appSettings => 'App Settings'; diff --git a/lib/widgets/app_menu_button.dart b/lib/widgets/app_menu_button.dart index 3e95540..124786c 100644 --- a/lib/widgets/app_menu_button.dart +++ b/lib/widgets/app_menu_button.dart @@ -1,8 +1,11 @@ // Copyright (c) 2026 tmacinc // Licensed under CC BY-NC-SA 4.0 +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:package_info_plus/package_info_plus.dart'; +import 'package:url_launcher/url_launcher.dart'; import 'package:meshcore_team/screens/connection_screen.dart'; import 'package:meshcore_team/screens/settings_screen.dart'; import '../l10n/app_localizations.dart'; @@ -15,13 +18,41 @@ class AppMenuButton extends StatelessWidget { Future _showAbout(BuildContext context) async { final info = await PackageInfo.fromPlatform(); if (!context.mounted) return; + final l10n = AppLocalizations.of(context)!; showAboutDialog( context: context, applicationName: 'MeshCore TEAM', applicationVersion: 'v${info.version}', + children: [ + TextButton.icon( + icon: const Icon(Icons.bug_report_outlined), + label: Text(l10n.reportBug), + onPressed: () => _reportBug(context, info), + ), + ], ); } + Future _reportBug(BuildContext context, PackageInfo info) async { + final platform = + '${Platform.operatingSystem} ${Platform.operatingSystemVersion}'; + final body = 'App version: ${info.version} (build ${info.buildNumber})\n' + 'Platform: $platform\n\n' + 'Describe the issue:\n'; + final uri = Uri.https('github.com', '/tmacinc/MeshCore-TEAM/issues/new', { + 'body': body, + }); + + final l10n = AppLocalizations.of(context)!; + if (!await launchUrl(uri, mode: LaunchMode.externalApplication)) { + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(l10n.couldNotOpenLink)), + ); + } + } + } + @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index be1ee9a..4f2ea53 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -18,6 +18,7 @@ import share_plus import shared_preferences_foundation import sqflite_darwin import sqlite3_flutter_libs +import url_launcher_macos import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { @@ -34,5 +35,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 9f0aeb7..75cefa0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -737,10 +737,10 @@ packages: dependency: transitive description: name: matcher - sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 url: "https://pub.dev" source: hosted - version: "0.12.18" + version: "0.12.19" material_color_utilities: dependency: transitive description: @@ -753,10 +753,10 @@ packages: dependency: transitive description: name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.18.0" mgrs_dart: dependency: transitive description: @@ -1270,10 +1270,10 @@ packages: dependency: transitive description: name: test_api - sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636" + sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" url: "https://pub.dev" source: hosted - version: "0.7.9" + version: "0.7.11" timezone: dependency: transitive description: @@ -1314,6 +1314,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.0" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 + url: "https://pub.dev" + source: hosted + version: "6.3.2" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: b413d49b73867ac08dd2f9890efd3cc11f2a0e577618d50843440a1fb3776c32 + url: "https://pub.dev" + source: hosted + version: "6.3.32" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "580fe5dfb51671ae38191d316e027f6b76272b026370708c2d898799750a02b0" + url: "https://pub.dev" + source: hosted + version: "6.4.1" url_launcher_linux: dependency: transitive description: @@ -1322,6 +1346,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.2.1" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18" + url: "https://pub.dev" + source: hosted + version: "3.2.5" url_launcher_platform_interface: dependency: transitive description: @@ -1459,5 +1491,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.9.0-0 <4.0.0" - flutter: ">=3.27.0" + dart: ">=3.12.0 <4.0.0" + flutter: ">=3.44.0" diff --git a/pubspec.yaml b/pubspec.yaml index 1566550..83e438a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,6 +64,7 @@ dependencies: # Utilities crypto: ^3.0.3 + url_launcher: ^6.3.2 http: ^1.2.0 package_info_plus: ^8.0.0 battery_plus: ^6.2.0