From 75073bd1ddc25d9fd79eab33017fb3babbb82b2c Mon Sep 17 00:00:00 2001 From: vjrj <vjrj@comunes.org> Date: Sun, 14 May 2023 14:28:34 +0200 Subject: [PATCH] Better currency format and styles --- lib/g1/currency.dart | 2 +- lib/ui/notification_controller_mobile.dart | 12 ++- lib/ui/notification_controller_web.dart | 12 ++- lib/ui/ui_helpers.dart | 61 +++++++++++++-- .../fourth_screen/transaction_item.dart | 75 ++++++++++++++---- .../fourth_screen/transaction_page.dart | 76 +++++++++++++++++-- 6 files changed, 205 insertions(+), 33 deletions(-) diff --git a/lib/g1/currency.dart b/lib/g1/currency.dart index a7669677..6d57a9e0 100644 --- a/lib/g1/currency.dart +++ b/lib/g1/currency.dart @@ -6,7 +6,7 @@ extension CurrencyExtension on Currency { case Currency.G1: return 'Äž1'; case Currency.DU: - return 'DUÄŸ1'; + return 'DU'; } } } diff --git a/lib/ui/notification_controller_mobile.dart b/lib/ui/notification_controller_mobile.dart index 48571df6..a0dae59d 100644 --- a/lib/ui/notification_controller_mobile.dart +++ b/lib/ui/notification_controller_mobile.dart @@ -150,11 +150,19 @@ class NotificationController { : tr('notification_new_sent_title'); final String desc = from != null ? tr('notification_new_payment_desc', namedArgs: <String, String>{ - 'amount': formatAmountWithLocale(locale.languageCode, amount, isG1), + 'amount': formatAmountWithLocale( + locale: locale.languageCode, + amount: amount, + isG1: isG1, + useSymbol: true), 'from': from, }) : tr('notification_new_sent_desc', namedArgs: <String, String>{ - 'amount': formatAmountWithLocale(locale.languageCode, amount, isG1), + 'amount': formatAmountWithLocale( + locale: locale.languageCode, + amount: amount, + isG1: isG1, + useSymbol: true), 'to': to!, }); if (kIsWeb) { diff --git a/lib/ui/notification_controller_web.dart b/lib/ui/notification_controller_web.dart index 62254980..f1405f2a 100644 --- a/lib/ui/notification_controller_web.dart +++ b/lib/ui/notification_controller_web.dart @@ -101,11 +101,19 @@ class NotificationController { : tr('notification_new_sent_title'); final String desc = from != null ? tr('notification_new_payment_desc', namedArgs: <String, String>{ - 'amount': formatAmountWithLocale(locale.languageCode, amount, isG1), + 'amount': formatAmountWithLocale( + locale: locale.languageCode, + amount: amount, + isG1: isG1, + useSymbol: true), 'from': from, }) : tr('notification_new_sent_desc', namedArgs: <String, String>{ - 'amount': formatAmountWithLocale(locale.languageCode, amount, isG1), + 'amount': formatAmountWithLocale( + locale: locale.languageCode, + amount: amount, + isG1: isG1, + useSymbol: true), 'to': to!, }); try { diff --git a/lib/ui/ui_helpers.dart b/lib/ui/ui_helpers.dart index ee8503cd..340d86a4 100644 --- a/lib/ui/ui_helpers.dart +++ b/lib/ui/ui_helpers.dart @@ -124,25 +124,61 @@ bool bigScreen(BuildContext context) => bool smallScreen(BuildContext context) => MediaQuery.of(context).size.width <= smallScreenWidth; -String formatAmount(BuildContext context, double amount, bool isG1) { +String formatAmount( + {required BuildContext context, + required double amount, + required bool isG1, + required bool useSymbol}) { return formatAmountWithLocale( - Localizations.localeOf(context).toString(), amount, isG1); + locale: currentLocale(context), + amount: amount, + isG1: isG1, + useSymbol: useSymbol); } -String formatAmountWithLocale(String locale, double amount, bool isG1) { +String currentLocale(BuildContext context) => + Localizations.localeOf(context).toString(); + +String formatAmountWithLocale( + {required String locale, + required double amount, + required bool isG1, + required bool useSymbol}) { + final NumberFormat currencyFormatter = + currentNumberFormat(isG1: isG1, locale: locale, useSymbol: useSymbol); + return currencyFormatter.format(amount); +} + +NumberFormat currentNumberFormat( + {required bool useSymbol, required bool isG1, required String locale}) { final NumberFormat currencyFormatter = NumberFormat.currency( // in English $10 is G110 ... confusing - symbol: isG1 ? '${Currency.G1.name()} ' : '${Currency.DU.name()} ', + symbol: useSymbol ? currentCurrency(isG1) : '', locale: locale, decimalDigits: isG1 ? 2 : 4, ); - return currencyFormatter.format(amount); + return currencyFormatter; +} + +String currentCurrency(bool isG1) { + return isG1 ? '${Currency.G1.name()} ' : '${Currency.DU.name()} '; +} + +String currentCurrencyTrimmed(bool isG1) { + return currentCurrency(isG1).trim(); } String formatKAmount( - BuildContext context, double amount, bool isG1, double currentUd) => + {required BuildContext context, + required double amount, + required bool isG1, + required double currentUd, + required bool useSymbol}) => formatAmount( - context, isG1 ? amount / 100 : ((amount / 100) / currentUd), isG1); + context: context, + amount: isG1 ? amount / 100 : ((amount / 100) / currentUd), + isG1: isG1, + useSymbol: useSymbol); double parseToDoubleLocalized( {required String locale, required String number}) => @@ -361,3 +397,14 @@ final GlobalKey<ScaffoldMessengerState> globalMessengerKey = GlobalKey<ScaffoldMessengerState>(); const Color deleteColor = Color(0xFFFE4A49); + +bool isSymbolPlacementBefore(String pattern) { + final int symbolIndex = pattern.indexOf('\u00A4'); + final int numberIndex = pattern.indexOf('#'); + + if (symbolIndex < numberIndex) { + return true; + } else { + return false; + } +} diff --git a/lib/ui/widgets/fourth_screen/transaction_item.dart b/lib/ui/widgets/fourth_screen/transaction_item.dart index 51f4b261..c606d9f8 100644 --- a/lib/ui/widgets/fourth_screen/transaction_item.dart +++ b/lib/ui/widgets/fourth_screen/transaction_item.dart @@ -23,6 +23,8 @@ class TransactionListItem extends StatelessWidget { required this.index, required this.isG1, required this.currentUd, + required this.currentSymbol, + required this.isCurrencyBefore, this.afterCancel, this.afterRetry}); @@ -31,6 +33,8 @@ class TransactionListItem extends StatelessWidget { final int index; final bool isG1; final double currentUd; + final String currentSymbol; + final bool isCurrencyBefore; final VoidCallback? afterCancel; final VoidCallback? afterRetry; @@ -49,10 +53,15 @@ class TransactionListItem extends StatelessWidget { Color? iconColor; String statusText; - final amountWithSymbol = - formatKAmount(context, transaction.amount, isG1, currentUd); + final String amountWithSymbol = formatKAmount( + context: context, + amount: transaction.amount, + isG1: isG1, + currentUd: currentUd, + useSymbol: false); + final String amountS = - '${transaction.amount < 0 ? "" : "+"}${amountWithSymbol}'; + '${transaction.amount < 0 ? "" : "+"}$amountWithSymbol'; statusText = tr('transaction_${transaction.type.name}'); switch (transaction.type) { case TransactionType.pending: @@ -219,16 +228,26 @@ class TransactionListItem extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, children: <Widget>[ - Text( - amountS, - style: TextStyle( - // fontWeight: FontWeight.bold, - color: transaction.type == TransactionType.received || - transaction.type == TransactionType.receiving - ? Colors.blue - : Colors.red, - ), - ), + Text.rich(TextSpan( + children: <InlineSpan>[ + if (isCurrencyBefore) + currencyBalanceWidget(isG1, currentSymbol), + if (isCurrencyBefore) separatorSpan(), + TextSpan( + text: amountS, + style: TextStyle( + // fontWeight: FontWeight.bold, + color: transaction.type == TransactionType.received || + transaction.type == TransactionType.receiving + ? Colors.blue + : Colors.red, + ), + ), + if (!isCurrencyBefore) separatorSpan(), + if (!isCurrencyBefore) + currencyBalanceWidget(isG1, currentSymbol), + ], + )), const SizedBox(height: 4.0), Tooltip( message: DateFormat.yMd(context.locale.languageCode) @@ -258,3 +277,33 @@ class TransactionListItem extends StatelessWidget { afterRetry!(); } } + +WidgetSpan separatorSpan() { + return const WidgetSpan( + child: SizedBox(width: 3), + ); +} + +InlineSpan currencyBalanceWidget(bool isG1, String currentSymbol) { + return TextSpan(children: <InlineSpan>[ + TextSpan( + text: currentSymbol, + style: const TextStyle( + color: Colors.black54, + ), + ), + if (!isG1) + WidgetSpan( + child: Transform.translate( + offset: const Offset(1, 4), + child: const Text( + 'Äž1', + style: TextStyle( + fontSize: 12, + // fontWeight: FontWeight.w500, + // fontFeatures: <FontFeature>[FontFeature.subscripts()], + color: Colors.black54, + ), + ))) + ]); +} diff --git a/lib/ui/widgets/fourth_screen/transaction_page.dart b/lib/ui/widgets/fourth_screen/transaction_page.dart index b174495a..dad5a514 100644 --- a/lib/ui/widgets/fourth_screen/transaction_page.dart +++ b/lib/ui/widgets/fourth_screen/transaction_page.dart @@ -48,6 +48,7 @@ class _TransactionsAndBalanceWidgetState final int _pendingPageSize = 30; final Cron cron = Cron(); + static const double balanceFontSize = 36.0; @override void initState() { @@ -141,10 +142,17 @@ class _TransactionsAndBalanceWidgetState final String myPubKey = SharedPreferencesHelper().getPubKey(); final bool isG1 = appCubit.currency == Currency.G1; final double currentUd = appCubit.currentUd; + final String currentSymbol = currentCurrencyTrimmed(isG1); + final NumberFormat currentNumber = currentNumberFormat( + useSymbol: true, isG1: isG1, locale: currentLocale(context)); + final bool isCurrencyBefore = + isSymbolPlacementBefore(currentNumber.symbols.CURRENCY_PATTERN); + return BlocBuilder<TransactionCubit, TransactionState>( builder: (BuildContext context, TransactionState transBalanceState) { // final List<Transaction> transactions = transBalanceState.transactions; final double balance = transBalanceState.balance; + return BackdropScaffold( appBar: BackdropAppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, @@ -190,14 +198,30 @@ class _TransactionsAndBalanceWidgetState Padding( padding: const EdgeInsets.symmetric(vertical: 10.0), child: Center( - child: Text( - formatKAmount(context, balance, isG1, currentUd), - style: TextStyle( - fontSize: 36.0, - color: - balance == 0 ? Colors.lightBlue : Colors.lightBlue, - fontWeight: FontWeight.bold), - )), + child: Text.rich(TextSpan( + children: <InlineSpan>[ + if (isCurrencyBefore) + currencyBalanceWidget(isG1, currentSymbol), + if (isCurrencyBefore) separatorSpan(), + TextSpan( + text: formatKAmount( + context: context, + amount: balance, + isG1: isG1, + currentUd: currentUd, + useSymbol: false), + style: TextStyle( + fontSize: balanceFontSize, + color: balance == 0 + ? Colors.lightBlue + : Colors.lightBlue, + fontWeight: FontWeight.bold), + ), + if (!isCurrencyBefore) separatorSpan(), + if (!isCurrencyBefore) + currencyBalanceWidget(isG1, currentSymbol), + ], + ))), ), // if (!kReleaseMode) TransactionChart(transactions: transactions) ], @@ -234,7 +258,9 @@ class _TransactionsAndBalanceWidgetState index: index, transaction: tx, isG1: isG1, + currentSymbol: currentSymbol, currentUd: currentUd, + isCurrencyBefore: isCurrencyBefore, afterRetry: () => _refresh(), afterCancel: () => _refresh()); }, @@ -253,6 +279,8 @@ class _TransactionsAndBalanceWidgetState pubKey: myPubKey, currentUd: currentUd, isG1: isG1, + isCurrencyBefore: isCurrencyBefore, + currentSymbol: currentSymbol, index: index + (_pendingController.itemList != null ? _pendingController.itemList!.length @@ -269,6 +297,38 @@ class _TransactionsAndBalanceWidgetState }); } + InlineSpan separatorSpan() { + return const WidgetSpan( + child: SizedBox(width: 7), + ); + } + + InlineSpan currencyBalanceWidget(bool isG1, String currentSymbol) { + return TextSpan(children: <InlineSpan>[ + TextSpan( + text: currentSymbol, + style: const TextStyle( + fontSize: balanceFontSize, + fontWeight: FontWeight.w500, + color: Colors.deepPurple, + ), + ), + if (!isG1) + WidgetSpan( + child: Transform.translate( + offset: const Offset(2, 16), + child: const Text( + 'Äž1', + style: TextStyle( + fontSize: balanceFontSize - 10, + fontWeight: FontWeight.w500, + // fontFeatures: <FontFeature>[FontFeature.subscripts()], + color: Colors.deepPurple, + ), + ))) + ]); + } + Future<void> _refresh() { return Future<void>.sync(() { _pagingController.refresh(); -- GitLab