feat(#527): About outbound links (website, Play, donate)

Adds three tappable rows to the About page opening in the external browser via
url_launcher: offband.org, the Google Play listing (app.offband.meshcore), and
offband.org/donate (Ko-fi + GitHub Sponsors options, live-verified). Failure
surfaces a snackbar. Completes epic #525.

Agent: QuietSnow (session 31eaba02)
pull/561/head
Strycher 2 months ago
parent 7fdb58204d
commit d5789d8e96

@ -249,6 +249,10 @@
"settings_aboutLegalese": "© 2026 Offband. Based on MeshCore Open by zjs81, MIT licensed.",
"settings_aboutDescription": "Offband Meshcore is an open-source client for MeshCore LoRa mesh networking devices.",
"settings_aboutLicenses": "View licenses",
"settings_aboutWebsite": "Offband website",
"settings_aboutPlayStore": "Google Play",
"settings_aboutDonate": "Donate or sponsor",
"settings_aboutLinkFailed": "Could not open the link",
"settings_aboutOpenMeteoAttribution": "LOS elevation data: Open-Meteo (CC BY 4.0)",
"settings_infoName": "Name",
"settings_infoId": "ID",

@ -1210,6 +1210,30 @@ abstract class AppLocalizations {
/// **'View licenses'**
String get settings_aboutLicenses;
/// No description provided for @settings_aboutWebsite.
///
/// In en, this message translates to:
/// **'Offband website'**
String get settings_aboutWebsite;
/// No description provided for @settings_aboutPlayStore.
///
/// In en, this message translates to:
/// **'Google Play'**
String get settings_aboutPlayStore;
/// No description provided for @settings_aboutDonate.
///
/// In en, this message translates to:
/// **'Donate or sponsor'**
String get settings_aboutDonate;
/// No description provided for @settings_aboutLinkFailed.
///
/// In en, this message translates to:
/// **'Could not open the link'**
String get settings_aboutLinkFailed;
/// No description provided for @settings_aboutOpenMeteoAttribution.
///
/// In en, this message translates to:

@ -615,6 +615,18 @@ class AppLocalizationsBg extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'Данни за надморска височина на LOS: Open-Meteo (CC BY 4.0)';

@ -610,6 +610,18 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'LOS-Höhendaten: Open-Meteo (CC BY 4.0)';

@ -601,6 +601,18 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'LOS elevation data: Open-Meteo (CC BY 4.0)';

@ -611,6 +611,18 @@ class AppLocalizationsEs extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'Datos de elevación LOS: Open-Meteo (CC BY 4.0)';

@ -615,6 +615,18 @@ class AppLocalizationsFr extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'Données d\'élévation LOS : Open-Meteo (CC BY 4.0)';

@ -613,6 +613,18 @@ class AppLocalizationsHu extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'LOS magassági adatok: Open-Meteo (CC BY 4.0)';

@ -613,6 +613,18 @@ class AppLocalizationsIt extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'Dati di elevazione LOS: Open-Meteo (CC BY 4.0)';

@ -586,6 +586,18 @@ class AppLocalizationsJa extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'LOS 標高データ:Open-Meteo (CC BY 4.0)';

@ -586,6 +586,18 @@ class AppLocalizationsKo extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'LOS 고도 데이터: Open-Meteo (CC BY 4.0)';

@ -607,6 +607,18 @@ class AppLocalizationsNl extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'LOS-hoogtegegevens: Open-Meteo (CC BY 4.0)';

@ -615,6 +615,18 @@ class AppLocalizationsPl extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'Dane wysokościowe LOS: Open-Meteo (CC BY 4.0)';

@ -613,6 +613,18 @@ class AppLocalizationsPt extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'Dados de elevação LOS: Open-Meteo (CC BY 4.0)';

@ -612,6 +612,18 @@ class AppLocalizationsRu extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'Данные о высоте LOS: Open-Meteo (CC BY 4.0)';

@ -607,6 +607,18 @@ class AppLocalizationsSk extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'Údaje o nadmorskej výške LOS: Open-Meteo (CC BY 4.0)';

@ -604,6 +604,18 @@ class AppLocalizationsSl extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'Podatki o višini LOS: Open-Meteo (CC BY 4.0)';

@ -602,6 +602,18 @@ class AppLocalizationsSv extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'LOS-höjddata: Open-Meteo (CC BY 4.0)';

@ -610,6 +610,18 @@ class AppLocalizationsUk extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'Дані про висоту LOS: Open-Meteo (CC BY 4.0)';

@ -578,6 +578,18 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get settings_aboutLicenses => 'View licenses';
@override
String get settings_aboutWebsite => 'Offband website';
@override
String get settings_aboutPlayStore => 'Google Play';
@override
String get settings_aboutDonate => 'Donate or sponsor';
@override
String get settings_aboutLinkFailed => 'Could not open the link';
@override
String get settings_aboutOpenMeteoAttribution =>
'LOS 高程数据:Open-Meteo (CC BY 4.0)';

@ -7,6 +7,7 @@ import 'package:meshcore_open/utils/gpx_export.dart';
import 'package:meshcore_open/widgets/elements_ui.dart';
import 'package:provider/provider.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart';
import '../connector/meshcore_connector.dart';
import '../connector/meshcore_protocol.dart';
@ -801,6 +802,27 @@ class _SettingsScreenState extends State<SettingsScreen> {
),
),
const Divider(height: 1),
ListTile(
leading: const Icon(Icons.language),
title: Text(l10n.settings_aboutWebsite),
trailing: const Icon(Icons.open_in_new, size: 18),
onTap: () => _openExternalUrl('https://offband.org'),
),
ListTile(
leading: const Icon(Icons.shop_outlined),
title: Text(l10n.settings_aboutPlayStore),
trailing: const Icon(Icons.open_in_new, size: 18),
onTap: () => _openExternalUrl(
'https://play.google.com/store/apps/details?id=app.offband.meshcore',
),
),
ListTile(
leading: const Icon(Icons.favorite_outline),
title: Text(l10n.settings_aboutDonate),
trailing: const Icon(Icons.open_in_new, size: 18),
onTap: () => _openExternalUrl('https://offband.org/donate'),
),
const Divider(height: 1),
ListTile(
leading: const Icon(Icons.description_outlined),
title: Text(l10n.settings_aboutLicenses),
@ -819,6 +841,24 @@ class _SettingsScreenState extends State<SettingsScreen> {
);
}
Future<void> _openExternalUrl(String url) async {
try {
if (await launchUrl(
Uri.parse(url),
mode: LaunchMode.externalApplication,
)) {
return;
}
} catch (_) {
// fall through to the failure message
}
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(context.l10n.settings_aboutLinkFailed)),
);
}
}
Widget _buildDebugCard(BuildContext context) {
final l10n = context.l10n;
final settingsService = context.watch<AppSettingsService>();

@ -24,6 +24,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -128,6 +132,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -232,6 +240,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -336,6 +348,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -440,6 +456,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -544,6 +564,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -648,6 +672,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -752,6 +780,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -856,6 +888,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -960,6 +996,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -1064,6 +1104,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -1168,6 +1212,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -1272,6 +1320,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -1376,6 +1428,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -1480,6 +1536,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -1584,6 +1644,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",
@ -1688,6 +1752,10 @@
"settings_experimentalAlreadyUnlocked",
"settings_experimentalCountdown",
"settings_aboutLicenses",
"settings_aboutWebsite",
"settings_aboutPlayStore",
"settings_aboutDonate",
"settings_aboutLinkFailed",
"settings_infoFirmware",
"settings_infoModel",
"settings_infoOffbandCaps",

Loading…
Cancel
Save

Powered by TurnKey Linux.