feat: update unit display to match cashu.me style

This commit is contained in:
Forte11Cuba
2026-02-06 14:54:46 -06:00
parent 7540e7e413
commit 922fabc784
2 changed files with 98 additions and 62 deletions
+39 -4
View File
@@ -34,16 +34,34 @@ class UnitFormatter {
}
/// Formatea un balance con su unidad.
/// Ejemplo: 1000 sat → "1,000 BTC", 500 usd → "5.00 USD"
/// Ejemplo: 1000 sat → "1,000 sat", 500 usd → "5.00 USD"
static String formatBalanceWithUnit(BigInt amount, String unit) {
final formatted = formatBalance(amount, unit);
final label = getUnitLabel(unit);
return '$formatted $label';
}
/// Obtiene la etiqueta de display para una unidad.
/// sat → BTC, usd → USD, eur → EUR, msat → MSAT
/// Obtiene la etiqueta de display para una unidad (para balances).
/// Siguiendo el estándar de cashu.me: minúsculas para sat/msat
/// Ejemplo: "855 sat", "5.00 USD"
static String getUnitLabel(String unit) {
switch (unit.toLowerCase()) {
case 'sat':
return 'sat';
case 'usd':
return 'USD';
case 'eur':
return 'EUR';
case 'msat':
return 'msat';
default:
return unit;
}
}
/// Obtiene la etiqueta para el botón toggle de unidad.
/// sat → "BTC" (indica Bitcoin), otros → mayúsculas
static String getToggleLabel(String unit) {
switch (unit.toLowerCase()) {
case 'sat':
return 'BTC';
@@ -52,7 +70,24 @@ class UnitFormatter {
case 'eur':
return 'EUR';
case 'msat':
return 'MSAT';
return 'mSAT';
default:
return unit.toUpperCase();
}
}
/// Obtiene la etiqueta en mayúsculas (para badges, estados).
/// Ejemplo: "PENDING: 536 SAT"
static String getUnitLabelUppercase(String unit) {
switch (unit.toLowerCase()) {
case 'sat':
return 'SAT';
case 'usd':
return 'USD';
case 'eur':
return 'EUR';
case 'msat':
return 'mSAT';
default:
return unit.toUpperCase();
}
+59 -58
View File
@@ -136,6 +136,9 @@ class _HomeScreenState extends State<HomeScreen> {
final walletProvider = context.watch<WalletProvider>();
final settingsProvider = context.read<SettingsProvider>();
final activeUnit = walletProvider.activeUnit;
// Toggle button: "BTC" para sat (como cashu.me)
final toggleLabel = UnitFormatter.getToggleLabel(activeUnit);
// Balance label: "sat" minúsculas (como cashu.me)
final unitLabel = UnitFormatter.getUnitLabel(activeUnit);
return Padding(
@@ -146,84 +149,82 @@ class _HomeScreenState extends State<HomeScreen> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// Ojo encima del saldo (centrado)
Center(
child: GestureDetector(
onTap: () {
setState(() {
_isBalanceVisible = !_isBalanceVisible;
});
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
_isBalanceVisible ? LucideIcons.eye : LucideIcons.eyeOff,
color: AppColors.textSecondary.withValues(alpha: 0.6),
size: 24,
// Botón toggle de unidad (arriba, como cashu.me)
GestureDetector(
onTap: () async {
await walletProvider.cycleUnit();
await settingsProvider.setActiveUnit(walletProvider.activeUnit);
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(24),
),
child: Text(
toggleLabel,
style: const TextStyle(
fontFamily: 'Inter',
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
),
),
const SizedBox(height: 24),
// Ojo para ocultar/mostrar balance
GestureDetector(
onTap: () {
setState(() {
_isBalanceVisible = !_isBalanceVisible;
});
},
child: Icon(
_isBalanceVisible ? LucideIcons.eye : LucideIcons.eyeOff,
color: AppColors.textSecondary.withValues(alpha: 0.5),
size: 20,
),
),
const SizedBox(height: 8),
// Balance reactivo del mint activo
// Balance con unidad al lado (como cashu.me: "855 sat")
StreamBuilder<BigInt>(
stream: walletProvider.streamBalance(),
builder: (context, snapshot) {
final balance = snapshot.data ?? BigInt.zero;
final formattedBalance = UnitFormatter.formatBalance(balance, activeUnit);
return Text(
_isBalanceVisible ? formattedBalance : '••••••',
style: const TextStyle(
fontFamily: 'Inter',
fontSize: 48,
fontWeight: FontWeight.bold,
color: Colors.white,
),
);
},
),
const SizedBox(height: 4),
// Unidad - tap para ciclar
GestureDetector(
onTap: () async {
// Ciclar unidad
await walletProvider.cycleUnit();
// Guardar en settings
await settingsProvider.setActiveUnit(walletProvider.activeUnit);
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
decoration: BoxDecoration(
color: AppColors.primaryAction.withValues(alpha: 0.15),
borderRadius: BorderRadius.circular(12),
),
child: Row(
mainAxisSize: MainAxisSize.min,
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
Text(
unitLabel,
_isBalanceVisible ? formattedBalance : '••••••',
style: const TextStyle(
fontFamily: 'Inter',
fontSize: 18,
fontWeight: FontWeight.w600,
color: AppColors.primaryAction,
fontSize: 48,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
// Mostrar indicador si hay más de una unidad
if (walletProvider.activeUnits.length > 1) ...[
const SizedBox(width: 4),
Icon(
LucideIcons.refreshCw,
color: AppColors.primaryAction.withValues(alpha: 0.7),
size: 14,
const SizedBox(width: 8),
Text(
_isBalanceVisible ? unitLabel : '',
style: TextStyle(
fontFamily: 'Inter',
fontSize: 32,
fontWeight: FontWeight.w400,
color: Colors.white.withValues(alpha: 0.7),
),
],
),
],
),
),
);
},
),
],
),