From 7f8d46b9e8340f759d6a1585b7f767e633cdd411 Mon Sep 17 00:00:00 2001 From: poka Date: Thu, 8 Dec 2022 08:17:36 +0100 Subject: [PATCH] UX: search: action button is paste address if an address is present in clipboard --- assets/translations/en.json | 3 +- assets/translations/es.json | 3 +- assets/translations/fr.json | 3 +- lib/screens/common_elements.dart | 18 ++++++++++ lib/screens/search.dart | 61 +++++++++++++++++++++++++++----- lib/widgets/bottom_app_bar.dart | 5 ++- pubspec.yaml | 2 +- 7 files changed, 81 insertions(+), 14 deletions(-) diff --git a/assets/translations/en.json b/assets/translations/en.json index eb95125..14d085e 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -202,5 +202,6 @@ "received": "Received", "sent": "Sent", "createIdentity": "Create a new \nidentity", - "memberAccountOf": "Account of {}" + "memberAccountOf": "Account of {}", + "pasteAddress": "Paste address from\nclipboard" } \ No newline at end of file diff --git a/assets/translations/es.json b/assets/translations/es.json index cf0b689..ab871e6 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -203,5 +203,6 @@ "received": "Received", "sent": "Sent", "createIdentity": "Create a new \nidentity", - "memberAccountOf": "Account of {}" + "memberAccountOf": "Account of {}", + "pasteAddress": "Paste address from\nclipboard" } diff --git a/assets/translations/fr.json b/assets/translations/fr.json index f10c89a..3ae3060 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -203,5 +203,6 @@ "received": "Reçus", "sent": "Envoyés", "createIdentity": "Créer sa nouvelle\nidentité", - "memberAccountOf": "Compte de {}" + "memberAccountOf": "Compte de {}", + "pasteAddress": "Coller l'adresse depuis\nle presse-papier" } diff --git a/lib/screens/common_elements.dart b/lib/screens/common_elements.dart index 117d465..54c0f76 100644 --- a/lib/screens/common_elements.dart +++ b/lib/screens/common_elements.dart @@ -402,6 +402,24 @@ Future infoPopup(BuildContext context, String title) async { ); } +bool isAddress(address) { + final RegExp regExp = RegExp( + r'^[a-zA-Z0-9]+$', + caseSensitive: false, + multiLine: false, + ); + + if (regExp.hasMatch(address) == true && + address.length > 45 && + address.length < 52) { + log.d("C'est une adresse !"); + + return true; + } else { + return false; + } +} + // Widget geckoAppBar() { // return AppBar( // toolbarHeight: 60 * ratio, diff --git a/lib/screens/search.dart b/lib/screens/search.dart index 933b715..9749e1c 100644 --- a/lib/screens/search.dart +++ b/lib/screens/search.dart @@ -1,24 +1,49 @@ -import 'package:easy_localization/easy_localization.dart'; +// ignore_for_file: use_build_context_synchronously +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/services.dart'; import 'package:gecko/globals.dart'; import 'package:flutter/material.dart'; import 'package:gecko/models/widgets_keys.dart'; -// import 'package:gecko/providers/home.dart'; import 'package:gecko/providers/search.dart'; import 'package:gecko/screens/common_elements.dart'; import 'package:gecko/screens/search_result.dart'; +import 'package:gecko/screens/wallet_view.dart'; import 'package:provider/provider.dart'; -// import 'package:gecko/models/home.dart'; -// import 'package:provider/provider.dart'; -class SearchScreen extends StatelessWidget { +class SearchScreen extends StatefulWidget { const SearchScreen({Key? key}) : super(key: key); + @override + State createState() => _SearchScreenState(); +} + +class _SearchScreenState extends State { + bool canPasteAddress = false; + String pastedAddress = ''; + + Future getClipBoard() async { + final clipboard = await Clipboard.getData('text/plain'); + pastedAddress = clipboard?.text ?? ''; + canPasteAddress = isAddress(pastedAddress); + } + + @override + void initState() { + WidgetsBinding.instance.addPostFrameCallback((_) async { + await getClipBoard(); + }); + super.initState(); + } + @override Widget build(BuildContext context) { final searchProvider = Provider.of(context); final screenHeight = MediaQuery.of(context).size.height; + final canValidate = searchProvider.searchController.text.length >= 2; + // final canPasteAddress = false; + return WillPopScope( onWillPop: () { searchProvider.searchController.text = ''; @@ -63,7 +88,11 @@ class SearchScreen extends StatelessWidget { autofocus: true, maxLines: 1, textAlign: TextAlign.left, - onChanged: (v) => searchProvider.reload(), + onChanged: (v) async => { + await getClipBoard(), + setState(() {}), + searchProvider.reload() + }, decoration: InputDecoration( filled: true, fillColor: Colors.white, @@ -104,7 +133,7 @@ class SearchScreen extends StatelessWidget { foregroundColor: Colors.white, elevation: 4, backgroundColor: orangeC, // foreground ), - onPressed: searchProvider.searchController.text.length >= 2 + onPressed: canValidate ? () { Navigator.push( context, @@ -113,9 +142,23 @@ class SearchScreen extends StatelessWidget { }), ); } - : null, + : canPasteAddress + ? () async { + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return WalletViewScreen( + address: pastedAddress, username: ''); + }), + ); + } + : null, child: Text( - 'search'.tr(), + canValidate + ? 'search'.tr() + : canPasteAddress + ? 'pasteAddress'.tr() + : 'search'.tr(), textAlign: TextAlign.center, style: const TextStyle( fontSize: 21, fontWeight: FontWeight.w600), diff --git a/lib/widgets/bottom_app_bar.dart b/lib/widgets/bottom_app_bar.dart index 8a1a05e..688b866 100644 --- a/lib/widgets/bottom_app_bar.dart +++ b/lib/widgets/bottom_app_bar.dart @@ -5,6 +5,7 @@ import 'package:gecko/globals.dart'; import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/models/widgets_keys.dart'; import 'package:gecko/providers/my_wallets.dart'; +import 'package:gecko/providers/search.dart'; import 'package:gecko/providers/wallets_profiles.dart'; import 'package:gecko/screens/myWallets/unlocking_wallet.dart'; import 'package:gecko/screens/myWallets/wallets_home.dart'; @@ -19,8 +20,9 @@ class GeckoBottomAppBar extends StatelessWidget { Widget build(BuildContext context) { final myWalletProvider = Provider.of(context, listen: false); - WalletsProfilesProvider historyProvider = + final historyProvider = Provider.of(context, listen: false); + final searchProvider = Provider.of(context, listen: false); final size = MediaQuery.of(context).size; const bool showBottomBar = true; @@ -40,6 +42,7 @@ class GeckoBottomAppBar extends StatelessWidget { iconSize: 40, icon: const Image(image: AssetImage('assets/loupe-noire.png')), onPressed: () { + searchProvider.reload(); Navigator.popUntil( context, ModalRoute.withName('/'), diff --git a/pubspec.yaml b/pubspec.yaml index 6e37117..414b6b9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ description: Pay with G1. # pub.dev using `pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 0.0.15+47 +version: 0.0.15+48 environment: sdk: '>=2.12.0 <3.0.0'