Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/format input value #623

Merged
merged 7 commits into from
Dec 12, 2024
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
5 changes: 3 additions & 2 deletions integration_test/e2e_stake_unstake.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ Future<void> e2eStakeUnstakeTest(WidgetTester tester) async {
await tester.pumpAndSettle();
await tapButton(tester, localization.stakeUnstake, semantics: true);
await tapButton(tester, localization.stake);
expect(widgetByText(localization.sendStakeTransaction), findsOneWidget);
await tapButton(tester, localization.stakeUnstake, semantics: true);
expect(widgetByText(localization.disableStakeTitle), findsOneWidget);
await tapButton(tester, localization.close);
await tester.pumpAndSettle();
await tapButton(tester, localization.unstake);
expect(widgetByText(localization.emptyStakeTitle), findsOneWidget);

Expand Down
4 changes: 4 additions & 0 deletions lib/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,7 @@ const List<String> CUSTOM_ICON_NAMES = [
'myWitWallet-title',
'myWitWallet-title-dark'
];
double ONE_WIT_TO_NANO = 1000000000;
double MAX_STAKING_AMOUNT_NANOWIT = 10000000 * ONE_WIT_TO_NANO;
double MIN_STAKING_AMOUNT_NANOWIT = 10000 * ONE_WIT_TO_NANO;
String DEFAULT_WALLET_ID = '00000000';
4 changes: 3 additions & 1 deletion lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -355,5 +355,7 @@
"feesAndRewards": "Fees and rewards",
"totalDataSynced": "Scan summary",
"welcomeBack": "Welcome back",
"deleteWalletSettings": "Settings: Delete wallet"
"deleteWalletSettings": "Settings: Delete wallet",
"disableStakeTitle": "You don't have enough balance to stake",
"disableStakeMessage": "The minimun amount to stake is 10,000 WIT"
}
4 changes: 3 additions & 1 deletion lib/l10n/app_es.arb
Original file line number Diff line number Diff line change
Expand Up @@ -355,5 +355,7 @@
"feesAndRewards": "Tasas y Recompensas",
"totalDataSynced": "Resumen de la sincronización",
"deleteWalletSettings": "Configuración: Eliminar wallet",
"welcomeBack": "Bienvenido de nuevo"
"welcomeBack": "Bienvenido de nuevo",
"disableStakeTitle": "No tienes suficiente balance para hacer Stake",
"disableStakeMessage": "La cantidad minima para hacer Stake es de 10.000 WIT"
}
8 changes: 4 additions & 4 deletions lib/screens/create_wallet/enc_xprv_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ class EnterXprvCardState extends State<EnterEncryptedXprvCard>
}

void setXprv(String value) {
xprv = XprvInput.dirty(
xprvType: _xprvType,
allowValidation: validationUtils.isFormUnFocus(_formFocusElements),
value: value);
xprv = XprvInput.dirty(
xprvType: _xprvType,
allowValidation: validationUtils.isFormUnFocus(_formFocusElements),
value: value);
}

void clearForm() {
Expand Down
2 changes: 1 addition & 1 deletion lib/util/storage/database/wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class Wallet {
required this.internalAccounts,
this.lastSynced = -1,
}) {
this.id = '00000000';
this.id = DEFAULT_WALLET_ID;
this.externalAccounts.forEach((key, Account account) {
account.balance;
});
Expand Down
9 changes: 0 additions & 9 deletions lib/widgets/inputs/input_amount.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@ import 'package:my_wit_wallet/util/get_localization.dart';
import 'package:my_wit_wallet/constants.dart';
import 'package:my_wit_wallet/widgets/buttons/text_btn.dart';
import 'package:my_wit_wallet/widgets/inputs/input_text.dart';
import 'package:my_wit_wallet/widgets/validations/vtt_amount_input.dart';


class InputAmount extends InputText {
InputAmount({
required this.amount,
required super.focusNode,
required super.styledTextController,
super.prefixIcon,
Expand All @@ -17,7 +14,6 @@ class InputAmount extends InputText {
super.hint,
super.keyboardType,
super.obscureText,
this.route,
super.onChanged,
super.onEditingComplete,
super.onFieldSubmitted,
Expand All @@ -27,16 +23,11 @@ class InputAmount extends InputText {
super.inputFormatters,
});

final VttAmountInput amount;
final String? route;

@override
_InputAmountState createState() => _InputAmountState();
}

class _InputAmountState extends State<InputAmount> {
TextSelection? lastSelection;

@override
void initState() {
super.initState();
Expand Down
53 changes: 36 additions & 17 deletions lib/widgets/inputs/input_slider.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import 'package:flutter/material.dart';
import 'package:my_wit_wallet/util/get_localization.dart';
import 'package:my_wit_wallet/constants.dart';
import 'package:my_wit_wallet/util/extensions/num_extensions.dart';
import 'package:my_wit_wallet/widgets/inputs/input_amount.dart';

import 'input_text.dart';

class InputSlider extends InputText {
InputSlider({
String? route,
required this.maxAmount,
required this.minAmount,
required super.focusNode,
Expand All @@ -24,6 +25,7 @@ class InputSlider extends InputText {
super.onTap,
super.onSuffixTap,
super.inputFormatters,
super.enabled,
});

final double maxAmount;
Expand All @@ -48,6 +50,16 @@ class _InputSliderState extends State<InputSlider> {
widget.focusNode.removeListener(widget.onFocusChange);
}

double getSliderValue({maxAmount, value, minAmount}) {
if (value >= maxAmount) {
return maxAmount;
} else if (value <= minAmount) {
return minAmount;
} else {
return value;
}
}

Widget build(BuildContext context) {
final theme = Theme.of(context);

Expand All @@ -58,42 +70,49 @@ class _InputSliderState extends State<InputSlider> {

String? inputValue = widget.styledTextController.text;
double sliderValue = 0;
bool isSliderDisabled = widget.maxAmount < widget.minAmount;
double maxAmount = isSliderDisabled ? 0 : widget.maxAmount;
double minAmount = isSliderDisabled ? 0 : widget.minAmount;
try {
sliderValue = inputValue != '' ? double.parse(inputValue) : 0;
} catch (err) {
print('Error parsing sliderValue $inputValue');
}
return Column(children: [
Container(
child: widget.buildInput(
context: context,
decoration: InputDecoration(
hintText: widget.hint ?? localization.inputAmountHint,
errorText: widget.errorText,
prefixIcon:
widget.prefixIcon != null ? Icon(widget.prefixIcon) : null,
suffixText: WIT_UNIT[WitUnit.Wit],
suffixIconConstraints: BoxConstraints(minHeight: 44),
),
child: InputAmount(
hint: localization.amount,
validator: (String? amount) => widget.errorText ?? null,
errorText: widget.errorText,
styledTextController: widget.styledTextController,
focusNode: widget.focusNode,
keyboardType: TextInputType.number,
onChanged: widget.onChanged,
onTap: widget.onTap,
inputFormatters: widget.inputFormatters,
onFieldSubmitted: widget.onFieldSubmitted,
onEditingComplete: widget.onEditingComplete,
),
),
SizedBox(height: 8),
Column(children: [
Slider(
value:
sliderValue >= widget.maxAmount ? widget.maxAmount : sliderValue,
max: widget.maxAmount,
min: widget.minAmount,
value: getSliderValue(
maxAmount: maxAmount, minAmount: minAmount, value: sliderValue),
max: maxAmount,
min: minAmount,
label: sliderValue.toString(),
onChanged: (double value) =>
{widget.onChanged!(value.toStringAsFixed(9))},
),
Row(
children: [
Text('Min ${widget.minAmount} ${WIT_UNIT[WitUnit.Wit]}',
Text(
'Min ${widget.minAmount.standardizeWitUnits(inputUnit: WitUnit.Wit, outputUnit: WitUnit.Wit)} ${WIT_UNIT[WitUnit.Wit]}',
style: theme.textTheme.bodySmall),
Spacer(),
Text('Max ${widget.maxAmount} ${WIT_UNIT[WitUnit.Wit]}',
Text(
'Max ${widget.maxAmount.standardizeWitUnits(inputUnit: WitUnit.Wit, outputUnit: WitUnit.Wit)} ${WIT_UNIT[WitUnit.Wit]}',
style: theme.textTheme.bodySmall),
],
)
Expand Down
3 changes: 3 additions & 0 deletions lib/widgets/inputs/input_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ abstract class InputText extends StatefulWidget {
this.textInputAction,
this.maxLines,
this.minLines,
this.enabled = true,
});
final IconData? prefixIcon;
final FocusNode focusNode;
Expand All @@ -52,11 +53,13 @@ abstract class InputText extends StatefulWidget {
final int? maxLines;
final int? minLines;
final TextInputAction? textInputAction;
final bool enabled;

Widget buildInput(
{required BuildContext context, InputDecoration? decoration = null}) {
return TextFormField(
decoration: decoration ?? decoration,
enabled: enabled,
minLines: minLines,
maxLines: maxLines ?? 1,
keyboardType: keyboardType,
Expand Down
20 changes: 19 additions & 1 deletion lib/widgets/layouts/dashboard_layout.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:my_wit_wallet/constants.dart';
import 'package:my_wit_wallet/screens/dashboard/bloc/dashboard_bloc.dart';
import 'package:my_wit_wallet/util/clear_and_redirect.dart';
import 'package:my_wit_wallet/util/current_route.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:my_wit_wallet/screens/login/bloc/login_bloc.dart';
Expand Down Expand Up @@ -91,6 +93,22 @@ class DashboardLayoutState extends State<DashboardLayout>
});
}

Widget _buildDashboardListener(Widget content) {
return BlocListener<DashboardBloc, DashboardState>(
listenWhen: (previousState, currentState) {
if ((previousState.currentWalletId != DEFAULT_WALLET_ID) &&
(previousState.currentWalletId != currentState.currentWalletId)) {
clearAndRedirectToDashboard(context);
}
return true;
},
listener: (BuildContext context, DashboardState state) {},
child: BlocBuilder<DashboardBloc, DashboardState>(
builder: (BuildContext context, DashboardState state) {
return content;
}));
}

Widget _authBuilder() {
final theme = Theme.of(context);
return BlocListener<LoginBloc, LoginState>(
Expand Down Expand Up @@ -155,7 +173,7 @@ class DashboardLayoutState extends State<DashboardLayout>
.getNavigationActions(context),
isDashboard: true,
bottomNavigation: _buildBottomNavigation(),
widgetList: [_body, SizedBox(height: 16)],
widgetList: [_buildDashboardListener(_body), SizedBox(height: 16)],
actions: [],
slidingPanel: panelContent,
);
Expand Down
38 changes: 5 additions & 33 deletions lib/widgets/layouts/send_transaction_layout.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import 'package:my_wit_wallet/bloc/transactions/value_transfer/vtt_create/vtt_cr
import 'package:my_wit_wallet/shared/api_database.dart';
import 'package:my_wit_wallet/shared/locator.dart';
import 'package:my_wit_wallet/util/storage/database/wallet_storage.dart';
import 'package:my_wit_wallet/screens/dashboard/bloc/dashboard_bloc.dart';
import 'package:my_wit_wallet/widgets/buttons/custom_btn.dart';
import 'package:my_wit_wallet/widgets/layouts/dashboard_layout.dart';
import 'package:my_wit_wallet/widgets/step_bar.dart';
Expand Down Expand Up @@ -261,37 +260,6 @@ class SendTransactionLayoutState extends State<SendTransactionLayout>
);
}

BlocListener _dashboardBlocListener() {
return BlocListener<DashboardBloc, DashboardState>(
listener: (BuildContext context, DashboardState state) {
BlocProvider.of<TransactionBloc>(context).add(ResetTransactionEvent());
Navigator.pushReplacement(
context,
CustomPageRoute(
builder: (BuildContext context) {
return SendTransactionLayout(
routeName: widget.routeName,
transactionType: widget.transactionType,
);
},
maintainState: false,
settings: RouteSettings(name: widget.routeName)));
},
child: _dashboardBlocBuilder(),
);
}

BlocBuilder _dashboardBlocBuilder() {
return BlocBuilder<DashboardBloc, DashboardState>(
builder: (BuildContext context, DashboardState state) {
return DashboardLayout(
scrollController: scrollController,
dashboardChild: _transactionBlocListener(),
actions: [],
);
});
}

BlocListener _transactionBlocListener() {
final theme = Theme.of(context);
return BlocListener<TransactionBloc, TransactionState>(
Expand Down Expand Up @@ -328,7 +296,11 @@ class SendTransactionLayoutState extends State<SendTransactionLayout>
Widget build(BuildContext context) {
return BlocBuilder<TransactionBloc, TransactionState>(
builder: (context, state) {
return _dashboardBlocListener();
return DashboardLayout(
scrollController: scrollController,
dashboardChild: _transactionBlocListener(),
actions: [],
);
});
}
}
32 changes: 23 additions & 9 deletions lib/widgets/stake_unstake.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:my_wit_wallet/bloc/transactions/value_transfer/vtt_create/vtt_create_bloc.dart';
import 'package:my_wit_wallet/constants.dart';
import 'package:my_wit_wallet/screens/dashboard/view/dashboard_screen.dart';
import 'package:my_wit_wallet/screens/stake/stake_screen.dart';
import 'package:my_wit_wallet/screens/unstake/unstake_screen.dart';
Expand All @@ -15,6 +16,7 @@ import 'package:my_wit_wallet/widgets/buttons/custom_btn.dart';
import 'package:my_wit_wallet/widgets/buttons/icon_btn.dart';
import 'package:my_wit_wallet/widgets/layouts/dashboard_layout.dart';
import 'package:flutter/material.dart';
import 'package:my_wit_wallet/widgets/witnet/transactions/value_transfer/modals/disable_stake_modal.dart';
import 'package:my_wit_wallet/widgets/witnet/transactions/value_transfer/modals/empty_stake_modal.dart';

typedef void VoidCallback();
Expand All @@ -28,17 +30,28 @@ class StakeUnstakeButtons extends StatelessWidget {
ApiDatabase db = Locator.instance.get<ApiDatabase>();
Wallet currentWallet = db.walletStorage.currentWallet;
late StakedBalanceInfo stakeInfo = currentWallet.stakedNanoWit();
bool allowStake = MIN_STAKING_AMOUNT_NANOWIT <
currentWallet.balanceNanoWit().availableNanoWit;

Future<void> _goToStakeScreen() async {
BlocProvider.of<TransactionBloc>(context).add(ResetTransactionEvent());
Navigator.push(
context,
CustomPageRoute(
builder: (BuildContext context) {
return StakeScreen();
},
maintainState: false,
settings: RouteSettings(name: StakeScreen.route)));
if (allowStake) {
BlocProvider.of<TransactionBloc>(context).add(ResetTransactionEvent());
Navigator.push(
context,
CustomPageRoute(
builder: (BuildContext context) {
return StakeScreen();
},
maintainState: false,
settings: RouteSettings(name: StakeScreen.route)));
} else {
ScaffoldMessenger.of(context).clearSnackBars();
buildDisableStakeModal(
theme: theme,
context: context,
originRouteName: DashboardScreen.route,
originRoute: DashboardScreen());
}
}

Future<void> _goToUnstakeScreen() async {
Expand All @@ -56,6 +69,7 @@ class StakeUnstakeButtons extends StatelessWidget {
ScaffoldMessenger.of(context).clearSnackBars();
buildEmptyStakeModal(
theme: theme,
allowStake: allowStake,
context: context,
originRouteName: DashboardScreen.route,
originRoute: DashboardScreen());
Expand Down
Loading
Loading