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
134 changes: 0 additions & 134 deletions lib/core/widgets/dialpad/dial_pad.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'package:bb_mobile/core/themes/app_theme.dart';
import 'package:bb_mobile/core/widgets/inputs/amount_input_formatter.dart';
import 'package:bb_mobile/core/widgets/text/text.dart';
import 'package:flutter/material.dart';

Expand Down Expand Up @@ -99,136 +98,3 @@ class DialPad extends StatelessWidget {
);
}
}

/// DialPad widget for amount entry with built-in formatting
class AmountDialPad extends StatelessWidget {
const AmountDialPad({
super.key,
required this.controller,
required this.inputCurrencyCode,
this.disableFeedback = false,
this.onAmountChanged,
});

final TextEditingController controller;
final String inputCurrencyCode;
final bool disableFeedback;
final VoidCallback? onAmountChanged;

void _handleNumberPressed(String number) {
final formatter = AmountInputFormatter(inputCurrencyCode);
final currentValue = controller.value;
final selectionStart = currentValue.selection.baseOffset;
final selectionEnd = currentValue.selection.extentOffset;
final currentText = currentValue.text;

// Build new text by inserting/replacing at selection
final String newText;
final int newCursorPos;

if (selectionStart == -1) {
// Field is not focused, add to end
newText = currentText + number;
newCursorPos = newText.length;
} else if (selectionStart == selectionEnd) {
// No selection, insert at cursor
newText =
currentText.substring(0, selectionStart) +
number +
currentText.substring(selectionStart);
newCursorPos = selectionStart + number.length;
} else {
// Replace selection
newText =
currentText.substring(0, selectionStart) +
number +
currentText.substring(selectionEnd);
newCursorPos = selectionStart + number.length;
}

// Apply formatter (it handles cursor positioning)
final formattedValue = formatter.formatEditUpdate(
currentValue,
TextEditingValue(
text: newText,
selection: TextSelection.collapsed(offset: newCursorPos),
),
);

if (formattedValue.text != currentText) {
controller.value = formattedValue;
onAmountChanged?.call();
}
}

void _handleBackspacePressed() {
final formatter = AmountInputFormatter(inputCurrencyCode);
final currentValue = controller.value;
final selectionStart = currentValue.selection.baseOffset;
final selectionEnd = currentValue.selection.extentOffset;
final currentText = currentValue.text;

// Build new text by removing at selection
final String newText;
final int newCursorPos;

if (selectionStart == -1) {
// Field is not focused, remove from end
newText =
currentText.isNotEmpty
? currentText.substring(0, currentText.length - 1)
: currentText;
newCursorPos = newText.length;
} else if (selectionStart == selectionEnd) {
// No selection, remove before cursor
if (selectionStart > 0) {
newText =
currentText.substring(0, selectionStart - 1) +
currentText.substring(selectionStart);
newCursorPos = selectionStart - 1;
} else {
newText = currentText;
newCursorPos = 0;
}
} else {
// Remove selection
newText =
currentText.substring(0, selectionStart) +
currentText.substring(selectionEnd);
newCursorPos = selectionStart;
}

// Apply formatter (it handles cursor positioning)
final formattedValue = formatter.formatEditUpdate(
currentValue,
TextEditingValue(
text: newText,
selection: TextSelection.collapsed(offset: newCursorPos),
),
);

if (formattedValue.text != currentText) {
controller.value = formattedValue;
onAmountChanged?.call();
}
}

@override
Widget build(BuildContext context) {
// Check if decimals are allowed
final decimalPlaces =
inputCurrencyCode == 'sats'
? 0
: inputCurrencyCode == 'BTC'
? 8
: 2;
final onlyDigits = decimalPlaces == 0;

return DialPad(
onNumberPressed: _handleNumberPressed,
onBackspacePressed: _handleBackspacePressed,
disableFeedback: disableFeedback,
onlyDigits: onlyDigits,
);
}
}
50 changes: 20 additions & 30 deletions lib/features/ark/ui/send_amount_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ import 'package:bb_mobile/core/settings/domain/settings_entity.dart';
import 'package:bb_mobile/core/themes/app_theme.dart';
import 'package:bb_mobile/core/utils/build_context_x.dart';
import 'package:bb_mobile/core/widgets/buttons/button.dart';
import 'package:bb_mobile/core/widgets/dialpad/dial_pad.dart';
import 'package:bb_mobile/core/widgets/loading/fading_linear_progress.dart';
import 'package:bb_mobile/core/widgets/price_input/balance_row.dart';
import 'package:bb_mobile/core/widgets/price_input/price_input.dart';
import 'package:bb_mobile/core/widgets/scrollable_column.dart';
import 'package:bb_mobile/features/ark/presentation/cubit.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:gap/gap.dart';

class SendAmountPage extends StatefulWidget {
const SendAmountPage({
Expand Down Expand Up @@ -124,8 +122,10 @@ class _SendAmountPageState extends State<SendAmountPage> {
final inputAmount = _controller.text;
final exchangeRate = context.read<ArkCubit>().state.exchangeRate;
final bitcoinUnit = context.read<ArkCubit>().state.preferredBitcoinUnit;
final equivalentCurrencyCode =
context.read<ArkCubit>().state.equivalentCurrencyCode;
final equivalentCurrencyCode = context
.read<ArkCubit>()
.state
.equivalentCurrencyCode;
String equivalentValue = '0';
if (_currencyCode == BitcoinUnit.sats.code) {
final amountSat = int.tryParse(inputAmount) ?? 0;
Expand All @@ -135,10 +135,9 @@ class _SendAmountPageState extends State<SendAmountPage> {
equivalentValue = (amountBtc * exchangeRate).toStringAsFixed(2);
} else {
final amountFiat = double.tryParse(inputAmount) ?? 0;
equivalentValue =
bitcoinUnit == BitcoinUnit.sats
? (amountFiat * 1e8 / exchangeRate).toStringAsFixed(0)
: (amountFiat / exchangeRate).toStringAsFixed(8);
equivalentValue = bitcoinUnit == BitcoinUnit.sats
? (amountFiat * 1e8 / exchangeRate).toStringAsFixed(0)
: (amountFiat / exchangeRate).toStringAsFixed(8);
}
return '$equivalentValue $equivalentCurrencyCode';
}
Expand Down Expand Up @@ -168,15 +167,14 @@ class _SendAmountPageState extends State<SendAmountPage> {
),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(3),
child:
_isLoading
? FadingLinearProgress(
height: 3,
trigger: _isLoading,
backgroundColor: context.appColors.surface,
foregroundColor: context.appColors.primary,
)
: const SizedBox(height: 3),
child: _isLoading
? FadingLinearProgress(
height: 3,
trigger: _isLoading,
backgroundColor: context.appColors.surface,
foregroundColor: context.appColors.primary,
)
: const SizedBox(height: 3),
),
),
body: SafeArea(
Expand Down Expand Up @@ -204,14 +202,11 @@ class _SendAmountPageState extends State<SendAmountPage> {
Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: BalanceRow(
balance:
_preferredBitcoinUnit == BitcoinUnit.btc
? (_maxSpendableSat != null
? (_maxSpendableSat! / 1e8).toStringAsFixed(
8,
)
: '0.00000000')
: (_maxSpendableSat?.toString() ?? '0'),
balance: _preferredBitcoinUnit == BitcoinUnit.btc
? (_maxSpendableSat != null
? (_maxSpendableSat! / 1e8).toStringAsFixed(8)
: '0.00000000')
: (_maxSpendableSat?.toString() ?? '0'),
currencyCode: _preferredBitcoinUnit.code,
onMaxPressed: () async {
await context
Expand All @@ -224,11 +219,6 @@ class _SendAmountPageState extends State<SendAmountPage> {
walletLabel: context.loc.arkInstantPayments,
),
),
const Gap(24),
AmountDialPad(
controller: _controller,
inputCurrencyCode: _currencyCode,
),
],
),
BBButton.big(
Expand Down
23 changes: 9 additions & 14 deletions lib/features/receive/ui/screens/receive_amount_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import 'package:bb_mobile/core/utils/build_context_x.dart';
import 'package:bb_mobile/core/widgets/buttons/button.dart';
import 'package:bb_mobile/features/receive/presentation/bloc/receive_bloc.dart';
import 'package:bb_mobile/features/receive/ui/widgets/receive_amount_entry.dart';
import 'package:bb_mobile/features/receive/ui/widgets/receive_numberpad.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
Expand All @@ -16,14 +15,13 @@ class ReceiveAmountScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocListener<ReceiveBloc, ReceiveState>(
listenWhen:
(previous, current) =>
// Only listen on confirmed amount changes
previous.confirmedAmountSat != current.confirmedAmountSat &&
// Only listen when no amount exception is present
current.amountException == null &&
// Prevent using the amount from a previous receive type
previous.type == current.type,
listenWhen: (previous, current) =>
// Only listen on confirmed amount changes
previous.confirmedAmountSat != current.confirmedAmountSat &&
// Only listen when no amount exception is present
current.amountException == null &&
// Prevent using the amount from a previous receive type
previous.type == current.type,
listener: (context, state) {
onContinueNavigation?.call() ?? context.pop();
},
Expand Down Expand Up @@ -84,10 +82,8 @@ class _AmountPageState extends State<AmountPage> {
@override
Widget build(BuildContext context) {
return BlocListener<ReceiveBloc, ReceiveState>(
listenWhen:
(previous, current) =>
previous.inputAmountCurrencyCode !=
current.inputAmountCurrencyCode,
listenWhen: (previous, current) =>
previous.inputAmountCurrencyCode != current.inputAmountCurrencyCode,
listener: (context, state) {
// Clear the controller when currency changes
_amountController.clear();
Expand All @@ -105,7 +101,6 @@ class _AmountPageState extends State<AmountPage> {
amountController: _amountController,
focusNode: _amountFocusNode,
),
ReceiveNumberPad(amountController: _amountController),
ReceiveAmountContinueButton(
onContinueNavigation: widget.onContinueNavigation,
),
Expand Down
22 changes: 0 additions & 22 deletions lib/features/receive/ui/widgets/receive_numberpad.dart

This file was deleted.

Loading