From 5170f438a3fc7dab924ffc1e39fd6231ccd3fac5 Mon Sep 17 00:00:00 2001 From: Erdem Yerebasmaz Date: Thu, 6 Jul 2023 01:09:32 +0300 Subject: [PATCH] Handle input on clicking "Paste Invoice or ID" --- lib/handlers/input_handler.dart | 24 +++++---- lib/routes/home/home_page.dart | 16 +++--- .../bottom_actions_bar.dart | 9 +++- .../send_options_bottom_sheet.dart | 50 ++++++++++--------- 4 files changed, 60 insertions(+), 39 deletions(-) diff --git a/lib/handlers/input_handler.dart b/lib/handlers/input_handler.dart index e02ead3e1..95a41ac0d 100644 --- a/lib/handlers/input_handler.dart +++ b/lib/handlers/input_handler.dart @@ -66,15 +66,7 @@ class InputHandler extends Handler { _handlingRequest = true; handleInputData(inputState.inputData) .then((result) { - _log.v("Input state handled: $result"); - if (result is LNURLPageResult && result.protocol != null) { - final context = contextProvider?.getBuildContext(); - if (context != null) { - handleLNURLPageResult(context, result); - } else { - _log.v("Skipping handling of result: $result because context is null"); - } - } + handleResult(result); }) .whenComplete(() => _handlingRequest = false) .onError((error, _) { @@ -92,6 +84,18 @@ class InputHandler extends Handler { }); } + void handleResult(result) { + _log.v("Input state handled: $result"); + if (result is LNURLPageResult && result.protocol != null) { + final context = contextProvider?.getBuildContext(); + if (context != null) { + handleLNURLPageResult(context, result); + } else { + _log.v("Skipping handling of result: $result because context is null"); + } + } + } + Future handleInputData(dynamic parsedInput) async { _log.v("handle input $parsedInput"); final context = contextProvider?.getBuildContext(); @@ -110,6 +114,8 @@ class InputHandler extends Handler { } else if (parsedInput is InputType_NodeId) { return handleNodeID(context, parsedInput.nodeId); } + // Input wasn't handled + return false; } Future handleInvoice(BuildContext context, Invoice invoice) async { diff --git a/lib/routes/home/home_page.dart b/lib/routes/home/home_page.dart index 9e612ba1d..09d6ca004 100644 --- a/lib/routes/home/home_page.dart +++ b/lib/routes/home/home_page.dart @@ -34,17 +34,18 @@ class HomeState extends State with AutoLockMixin, HandlerContextProvider { final GlobalKey firstPaymentItemKey = GlobalKey(); final ScrollController scrollController = ScrollController(); final handlers = []; + late final InputHandler inputHandler = InputHandler( + firstPaymentItemKey, + scrollController, + _scaffoldKey, + ); @override void initState() { super.initState(); SchedulerBinding.instance.addPostFrameCallback((_) { handlers.addAll([ - InputHandler( - firstPaymentItemKey, - scrollController, - _scaffoldKey, - ), + inputHandler, ConnectivityHandler(), PaymentResultHandler(), ]); @@ -89,7 +90,10 @@ class HomeState extends State with AutoLockMixin, HandlerContextProvider { drawerDragStartBehavior: DragStartBehavior.down, drawerEdgeDragWidth: mediaSize.width, drawer: HomeDrawer(key: _drawerKey), - bottomNavigationBar: BottomActionsBar(firstPaymentItemKey), + bottomNavigationBar: BottomActionsBar( + firstPaymentItemKey, + inputHandler, + ), floatingActionButton: QrActionButton(firstPaymentItemKey), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, body: _drawerKey.currentState?.screen() ?? AccountPage(firstPaymentItemKey, scrollController), diff --git a/lib/routes/home/widgets/bottom_actions_bar/bottom_actions_bar.dart b/lib/routes/home/widgets/bottom_actions_bar/bottom_actions_bar.dart index a0064beab..f2f1e3931 100644 --- a/lib/routes/home/widgets/bottom_actions_bar/bottom_actions_bar.dart +++ b/lib/routes/home/widgets/bottom_actions_bar/bottom_actions_bar.dart @@ -2,6 +2,7 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:breez_translations/breez_translations_locales.dart'; import 'package:c_breez/bloc/account/account_bloc.dart'; import 'package:c_breez/bloc/account/account_state.dart'; +import 'package:c_breez/handlers/input_handler.dart'; import 'package:c_breez/routes/home/widgets/bottom_actions_bar/receive_options_bottom_sheet.dart'; import 'package:c_breez/routes/home/widgets/bottom_actions_bar/send_options_bottom_sheet.dart'; import 'package:flutter/material.dart'; @@ -11,9 +12,11 @@ import 'bottom_action_item.dart'; class BottomActionsBar extends StatelessWidget { final GlobalKey firstPaymentItemKey; + final InputHandler inputHandler; const BottomActionsBar( - this.firstPaymentItemKey, { + this.firstPaymentItemKey, + this.inputHandler, { Key? key, }) : super(key: key); @@ -31,6 +34,7 @@ class BottomActionsBar extends StatelessWidget { children: [ SendOptions( firstPaymentItemKey: firstPaymentItemKey, + inputHandler: inputHandler, actionsGroup: actionsGroup, ), Container(width: 64), @@ -49,11 +53,13 @@ class BottomActionsBar extends StatelessWidget { class SendOptions extends StatelessWidget { final GlobalKey> firstPaymentItemKey; + final InputHandler inputHandler; final AutoSizeGroup actionsGroup; const SendOptions({ Key? key, required this.firstPaymentItemKey, + required this.inputHandler, required this.actionsGroup, }) : super(key: key); @@ -67,6 +73,7 @@ class SendOptions extends StatelessWidget { builder: (context) { return SendOptionsBottomSheet( firstPaymentItemKey: firstPaymentItemKey, + inputHandler: inputHandler, ); }, ), diff --git a/lib/routes/home/widgets/bottom_actions_bar/send_options_bottom_sheet.dart b/lib/routes/home/widgets/bottom_actions_bar/send_options_bottom_sheet.dart index 3c1ab94a0..75075862a 100644 --- a/lib/routes/home/widgets/bottom_actions_bar/send_options_bottom_sheet.dart +++ b/lib/routes/home/widgets/bottom_actions_bar/send_options_bottom_sheet.dart @@ -1,15 +1,13 @@ -import 'package:breez_sdk/bridge_generated.dart'; import 'package:breez_translations/breez_translations_locales.dart'; import 'package:c_breez/bloc/account/account_bloc.dart'; import 'package:c_breez/bloc/account/account_state.dart'; import 'package:c_breez/bloc/input/input_bloc.dart'; import 'package:c_breez/bloc/input/input_state.dart'; +import 'package:c_breez/handlers/input_handler.dart'; import 'package:c_breez/routes/home/widgets/bottom_actions_bar/bottom_action_item_image.dart'; import 'package:c_breez/routes/home/widgets/bottom_actions_bar/enter_payment_info_dialog.dart'; -import 'package:c_breez/routes/spontaneous_payment/spontaneous_payment_page.dart'; import 'package:c_breez/routes/withdraw_funds/withdraw_funds_address_page.dart'; import 'package:c_breez/theme/theme_provider.dart' as theme; -import 'package:c_breez/widgets/route.dart'; import 'package:fimber/fimber.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -18,8 +16,13 @@ final _log = FimberLog("SendOptionsBottomSheet"); class SendOptionsBottomSheet extends StatelessWidget { final GlobalKey firstPaymentItemKey; + final InputHandler inputHandler; - const SendOptionsBottomSheet({super.key, required this.firstPaymentItemKey}); + const SendOptionsBottomSheet({ + super.key, + required this.firstPaymentItemKey, + required this.inputHandler, + }); @override Widget build(BuildContext context) { @@ -77,31 +80,32 @@ class SendOptionsBottomSheet extends StatelessWidget { ); } + /// This documentation is for clarification purposes. + /// + /// Even though this function is named paste tapped it assumes that the + /// latest inputData on InputBloc's InputState comes from device's clipboard stream. + /// Which is a good assumption because otherwise that inputData would've been handled. void _pasteTapped( BuildContext context, dynamic inputData, GlobalKey firstPaymentItemKey, ) async { + // Close bottom sheet Navigator.of(context).pop(); - if (inputData is InputType_NodeId) { - _log.v("Input data is of type InputType_NodeId, pushing SpontaneousPaymentPage"); - Navigator.of(context).push( - FadeInRoute( - builder: (_) => SpontaneousPaymentPage( - inputData.nodeId, - firstPaymentItemKey, - ), - ), - ); - } else { - _log.v("Input data is $inputData, showing EnterPaymentInfoDialog"); - await showDialog( - useRootNavigator: false, - context: context, - barrierDismissible: false, - builder: (_) => EnterPaymentInfoDialog(paymentItemKey: firstPaymentItemKey), - ); - } + // and handle input data + inputHandler.handleInputData(inputData).then((result) async { + // If input data can't be handled(unsupported input type, empty device clipboard) display EnterPaymentInfoDialog + if (result == false) { + await showDialog( + useRootNavigator: false, + context: context, + barrierDismissible: false, + builder: (_) => EnterPaymentInfoDialog(paymentItemKey: firstPaymentItemKey), + ); + } else { + inputHandler.handleResult(result); + } + }); } void _push(BuildContext context, String route, {Object? arguments}) {