Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,12 @@
"leaveFederationConfirm": "Are you sure you want to leave this federation? You will need to re-join this federation to access any remaining funds.",
"@leaveFederationConfirm": {},

"currentBalance": "Current balance",
"@currentBalance": {},

"leaveFederationError": "Could not leave federation. Please try again.",
"@leaveFederationError": {},

"joinFederation": "Join Federation",
"@joinFederation": {},

Expand Down
2 changes: 2 additions & 0 deletions lib/l10n/app_es.arb
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@
"couldNotRegisterLnAddress": "No se pudo registrar la Dirección Lightning",
"leaveFederation": "Abandonar Federación",
"leaveFederationConfirm": "¿Estás seguro de que quieres abandonar esta federación? Necesitarás volver a unirte para acceder a los fondos restantes.",
"currentBalance": "Saldo actual",
"leaveFederationError": "No se pudo abandonar la federación. Inténtalo de nuevo.",
"joinFederation": "Unirse a Federación",
"joinAndRedeemEcash": "Unirse y canjear Ecash",
"recover": "Recuperar",
Expand Down
98 changes: 92 additions & 6 deletions lib/screens/federation_info_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import 'package:ecashapp/screens/guardian_dashboard.dart';
import 'package:ecashapp/widgets/federation_utxo_list.dart';
import 'package:ecashapp/lib.dart';
import 'package:ecashapp/multimint.dart';
import 'package:ecashapp/providers/preferences_provider.dart';
import 'package:ecashapp/toast.dart';
import 'package:ecashapp/utils.dart';
import 'package:ecashapp/widgets/gateways.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:qr_flutter/qr_flutter.dart';

enum _InfoSection { guardians, utxos, gateways }
Expand Down Expand Up @@ -164,6 +166,20 @@ class _FederationInfoScreenState extends State<FederationInfoScreen> {

Future<void> _onLeavePressed() async {
final screenNavigator = Navigator.of(context);
final bitcoinDisplay = context.read<PreferencesProvider>().bitcoinDisplay;

// Fetch the balance up front so we can warn the user before they leave a
// federation that still holds funds. Failures here are non-fatal — we just
// fall back to the plain confirmation dialog.
BigInt? balanceMsats;
try {
balanceMsats = await balance(federationId: _fed!.federationId);
} catch (e) {
AppLogger.instance.warn(
"Could not fetch balance for leave confirmation: $e",
);
}
if (!mounted) return;

await showDialog(
context: context,
Expand All @@ -172,9 +188,73 @@ class _FederationInfoScreenState extends State<FederationInfoScreen> {

return StatefulBuilder(
builder: (sbContext, setState) {
final theme = Theme.of(sbContext);
final hasBalance =
balanceMsats != null && balanceMsats > BigInt.zero;

return AlertDialog(
title: Text(sbContext.l10n.leaveFederation),
content: Text(sbContext.l10n.leaveFederationConfirm),
// Keep the dialog from stretching across wide screens (tablet,
// desktop, foldable) — a modal that spans the viewport reads as
// a full-screen takeover rather than a focused confirmation.
insetPadding: const EdgeInsets.symmetric(
horizontal: 40,
vertical: 24,
),
title: Row(
children: [
Icon(
Icons.warning_amber_rounded,
color: theme.colorScheme.error,
),
const SizedBox(width: 12),
Expanded(child: Text(sbContext.l10n.leaveFederation)),
],
),
content: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 420),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(sbContext.l10n.leaveFederationConfirm),
if (hasBalance) ...[
const SizedBox(height: 20),
// Compact "balance at risk" row — the amount is what
// matters, so lead with it. Kept intentionally quiet
// (no filled background) so it feels like a fact about
// the federation, not a second alarm.
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
Icons.account_balance_wallet_outlined,
color: theme.colorScheme.onSurfaceVariant,
size: 18,
),
const SizedBox(width: 10),
Text(
sbContext.l10n.currentBalance,
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
const Spacer(),
Text(
formatBalance(balanceMsats, false, bitcoinDisplay),
style: theme.textTheme.bodyLarge?.copyWith(
color: theme.colorScheme.error,
fontWeight: FontWeight.w600,
fontFeatures: const [
FontFeature.tabularFigures(),
],
),
),
],
),
],
],
),
),
actions: [
TextButton(
onPressed:
Expand All @@ -184,6 +264,9 @@ class _FederationInfoScreenState extends State<FederationInfoScreen> {
child: Text(sbContext.l10n.cancel),
),
TextButton(
style: TextButton.styleFrom(
foregroundColor: theme.colorScheme.error,
),
onPressed:
isLeaving
? null
Expand Down Expand Up @@ -215,12 +298,15 @@ class _FederationInfoScreenState extends State<FederationInfoScreen> {
AppLogger.instance.error(
"Error leaving federation: $e",
);
ToastService().show(
message: sbContext.l10n.leaveFederationError,
duration: const Duration(seconds: 5),
onTap: () {},
icon: const Icon(Icons.error),
);
if (dialogContext.mounted) {
Navigator.of(dialogContext).pop();
}
screenNavigator.popUntil(
(route) => route.isFirst,
);
} finally {
if (mounted) {
setState(() {
Expand All @@ -236,7 +322,7 @@ class _FederationInfoScreenState extends State<FederationInfoScreen> {
width: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
: Text(sbContext.l10n.confirm),
: Text(sbContext.l10n.leaveFederation),
),
],
);
Expand Down
17 changes: 12 additions & 5 deletions macos/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ PODS:
- app_links (6.4.1):
- FlutterMacOS
- FlutterMacOS (1.0.0)
- geolocator_apple (1.2.0):
- Flutter
- FlutterMacOS
- package_info_plus (0.0.1):
- FlutterMacOS
- path_provider_foundation (0.0.1):
Expand All @@ -16,6 +19,7 @@ PODS:
DEPENDENCIES:
- app_links (from `Flutter/ephemeral/.symlinks/plugins/app_links/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- geolocator_apple (from `Flutter/ephemeral/.symlinks/plugins/geolocator_apple/darwin`)
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
Expand All @@ -26,6 +30,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/app_links/macos
FlutterMacOS:
:path: Flutter/ephemeral
geolocator_apple:
:path: Flutter/ephemeral/.symlinks/plugins/geolocator_apple/darwin
package_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
path_provider_foundation:
Expand All @@ -36,12 +42,13 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos

SPEC CHECKSUMS:
app_links: c3185399a5cabc2e610ee5ad52fb7269b84ff869
app_links: 05a6ec2341985eb05e9f97dc63f5837c39895c3f
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
package_info_plus: 12f1c5c2cfe8727ca46cbd0b26677728972d9a5b
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404
geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e
package_info_plus: f0052d280d17aa382b932f399edf32507174e870
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673

PODFILE CHECKSUM: 54d867c82ac51cbd61b565781b9fada492027009

Expand Down
Loading