generated from TBD54566975/tbd-project-template
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: remove
NumberPad
callbacks (#24)
* replace callbacks with `ValueNotifier` and handle some input edge cases * use `NumberPad` without defining callbacks * fix tests now that deposit input/output default to integers * change tests to reflect removal of callbacks in `NumberPad` * refactor number validation util * refactor shake animation * refactor number pad to take only `onKeyPressed()` * add `Currency` class * add `CurrencyDropdown` * add `Payin` and `Payout` * refactor `SendPage` * refactor `DepositPage` and `WithdrawPage` * add `auto_size_text` * update tests * refactor test * set `shouldAnimate` based on transaction type * add `bottomSheetTheme` * support btc symbol in number format
- Loading branch information
Showing
25 changed files
with
881 additions
and
593 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||
import 'package:intl/intl.dart'; | ||
|
||
class Currency { | ||
final double exchangeRate; | ||
final String label; | ||
final IconData icon; | ||
|
||
Currency({ | ||
required this.exchangeRate, | ||
required this.label, | ||
required this.icon, | ||
}); | ||
|
||
static String formatFromString(String amount, {String? currency}) { | ||
final parsedAmount = double.tryParse(amount) ?? 0.0; | ||
|
||
if (currency == 'BTC') { | ||
return NumberFormat.currency( | ||
symbol: '₿', | ||
decimalDigits: amount.contains('.') ? 8 : 0, | ||
).format(parsedAmount); | ||
} | ||
|
||
return NumberFormat.simpleCurrency( | ||
name: currency, | ||
decimalDigits: amount.contains('.') ? 2 : 0, | ||
).format(parsedAmount); | ||
} | ||
|
||
static String formatFromDouble(double amount, {String? currency}) { | ||
if (currency == 'BTC') { | ||
return NumberFormat.currency( | ||
symbol: '₿', | ||
decimalDigits: amount % 1 == 0 ? 0 : 8, | ||
).format(amount); | ||
} | ||
|
||
return NumberFormat.simpleCurrency( | ||
name: currency, | ||
decimalDigits: amount % 1 == 0 ? 0 : 2, | ||
).format(amount); | ||
} | ||
} | ||
|
||
final _defaultList = [ | ||
Currency(exchangeRate: 1, label: 'USD', icon: Icons.attach_money), | ||
Currency(exchangeRate: 17, label: 'MXN', icon: Icons.attach_money), | ||
Currency(exchangeRate: 0.000024, label: 'BTC', icon: Icons.currency_bitcoin), | ||
]; | ||
|
||
final currencyProvider = Provider<List<Currency>>((ref) { | ||
return _defaultList; | ||
}); |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import 'package:didpay/features/currency/currency.dart'; | ||
import 'package:didpay/features/currency/currency_modal.dart'; | ||
import 'package:didpay/shared/theme/grid.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||
|
||
class CurrencyDropdown extends HookConsumerWidget { | ||
final ValueNotifier<Currency?> selectedCurrency; | ||
|
||
const CurrencyDropdown({ | ||
required this.selectedCurrency, | ||
super.key, | ||
}); | ||
|
||
@override | ||
Widget build(BuildContext context, WidgetRef ref) { | ||
final currencies = ref.watch(currencyProvider); | ||
|
||
return Directionality( | ||
textDirection: TextDirection.rtl, | ||
child: ElevatedButton.icon( | ||
icon: const Icon(Icons.keyboard_arrow_down), | ||
label: Text( | ||
selectedCurrency.value?.label.toString() ?? '', | ||
style: Theme.of(context).textTheme.headlineMedium, | ||
), | ||
style: ElevatedButton.styleFrom( | ||
padding: const EdgeInsets.only(left: Grid.xxs), | ||
backgroundColor: Colors.transparent, | ||
elevation: 0, | ||
), | ||
onPressed: () { | ||
CurrencyModal.show( | ||
context, | ||
(value) => selectedCurrency.value = | ||
currencies.firstWhere((c) => c.label == value), | ||
currencies, | ||
selectedCurrency.value?.label.toString() ?? ''); | ||
}, | ||
), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
import 'package:auto_size_text/auto_size_text.dart'; | ||
import 'package:didpay/features/currency/currency.dart'; | ||
import 'package:didpay/features/currency/currency_dropdown.dart'; | ||
import 'package:didpay/features/home/transaction.dart'; | ||
import 'package:didpay/l10n/app_localizations.dart'; | ||
import 'package:didpay/shared/shake_animated_text.dart'; | ||
import 'package:didpay/shared/theme/grid.dart'; | ||
import 'package:didpay/shared/utils/number_validation_util.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_hooks/flutter_hooks.dart'; | ||
|
||
class PayinKeyPress { | ||
final int count; | ||
final String key; | ||
|
||
PayinKeyPress(this.count, this.key); | ||
} | ||
|
||
class Payin extends HookWidget { | ||
final String transactionType; | ||
final ValueNotifier<String> amount; | ||
final ValueNotifier<PayinKeyPress> keyPress; | ||
final ValueNotifier<Currency?> currency; | ||
|
||
const Payin({ | ||
required this.transactionType, | ||
required this.amount, | ||
required this.keyPress, | ||
required this.currency, | ||
super.key, | ||
}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final shouldAnimate = useState(false); | ||
|
||
final formattedAmount = transactionType == Type.deposit | ||
? Currency.formatFromString(amount.value, | ||
currency: currency.value?.label) | ||
: Currency.formatFromString(amount.value); | ||
|
||
useEffect(() { | ||
WidgetsBinding.instance.addPostFrameCallback((_) => amount.value = '0'); | ||
return; | ||
}, [currency.value]); | ||
|
||
useEffect(() { | ||
WidgetsBinding.instance.addPostFrameCallback((_) { | ||
final current = amount.value; | ||
final key = keyPress.value.key; | ||
if (key == '') return; | ||
|
||
shouldAnimate.value = (key == '<') | ||
? !NumberValidationUtil.isValidDelete(current) | ||
: (transactionType == Type.deposit | ||
? !NumberValidationUtil.isValidInput( | ||
current, | ||
key, | ||
currency: currency.value?.label, | ||
) | ||
: !NumberValidationUtil.isValidInput(current, key)); | ||
if (shouldAnimate.value) return; | ||
|
||
if (key == '<') { | ||
amount.value = (current.length > 1) | ||
? current.substring(0, current.length - 1) | ||
: '0'; | ||
} else { | ||
amount.value = (current == '0' && key == '.') | ||
? '$current$key' | ||
: (current == '0') | ||
? key | ||
: '$current$key'; | ||
} | ||
}); | ||
|
||
return; | ||
}, [keyPress.value]); | ||
|
||
return Column( | ||
crossAxisAlignment: CrossAxisAlignment.start, | ||
children: [ | ||
ShakeAnimatedWidget( | ||
shouldAnimate: shouldAnimate, | ||
child: Column( | ||
mainAxisAlignment: MainAxisAlignment.start, | ||
crossAxisAlignment: CrossAxisAlignment.start, | ||
children: [ | ||
Row( | ||
crossAxisAlignment: CrossAxisAlignment.baseline, | ||
textBaseline: TextBaseline.alphabetic, | ||
children: [ | ||
Flexible( | ||
child: AutoSizeText( | ||
formattedAmount, | ||
style: Theme.of(context).textTheme.displayMedium, | ||
maxFontSize: | ||
Theme.of(context).textTheme.displayMedium?.fontSize ?? | ||
45.0, | ||
minFontSize: | ||
Theme.of(context).textTheme.bodyLarge?.fontSize ?? | ||
16.0, | ||
maxLines: 1, | ||
), | ||
), | ||
const SizedBox(width: Grid.half), | ||
transactionType == Type.deposit | ||
? CurrencyDropdown(selectedCurrency: currency) | ||
: Padding( | ||
padding: | ||
const EdgeInsets.symmetric(horizontal: Grid.xxs), | ||
child: Text( | ||
Loc.of(context).usd, | ||
style: Theme.of(context).textTheme.headlineMedium, | ||
), | ||
), | ||
], | ||
), | ||
], | ||
), | ||
), | ||
const SizedBox(height: Grid.xs), | ||
Text( | ||
transactionType == Type.deposit | ||
? Loc.of(context).youDeposit | ||
: Loc.of(context).youWithdraw, | ||
style: Theme.of(context).textTheme.bodyLarge, | ||
) | ||
], | ||
); | ||
} | ||
} |
Oops, something went wrong.