Compare commits

...

130 Commits

Author SHA1 Message Date
cgeek f34f020433 fix: build iOS 2023-02-28 10:19:52 +01:00
poka 472a4c1e5d set ios platform minimum version to 10 2023-02-27 19:43:16 +01:00
guenoel c8933fd5be fix: parse double to int in initCurrencyParameters for iPhone 2023-02-27 19:08:28 +01:00
poka 532a004fd9 remove old todo 2023-02-27 19:08:28 +01:00
poka 22c59613ee fix: double delimters in activity view 2023-02-27 19:08:28 +01:00
poka 60427463b5 feat: can copy app version number 2023-02-27 19:08:28 +01:00
poka 83764194e7 fix: french typo 2023-02-27 19:08:28 +01:00
pokapow 721e26ce05 Merge branch 'master' into 'master'
Master

See merge request clients/gecko!55
2023-02-27 18:44:00 +01:00
atlasan f5904e4f88 format 2023-02-26 02:26:12 +01:00
atlasan a0a3910adc translation updates, styles try? 2023-02-26 02:23:28 +01:00
atlasan d4740ab647 translations, debug test 2023-02-26 01:41:33 +01:00
pokapow 975614d873 Merge branch 'master' into 'master'
Translations and fixes

See merge request clients/gecko!54
2023-02-21 22:16:14 +01:00
atlasan 8e128963ad disable unused import 2023-02-19 19:59:19 +01:00
atlasan 515a058377 format: after disabling changeChest 2023-02-19 19:44:57 +01:00
atlasan 2d9e8025c0 disabling ChooseChest 2023-02-19 19:35:11 +01:00
atlasan 2cb7f234e5 flutter format 2023-02-03 11:47:55 +01:00
atlasan a347796a42 #71 2023-02-02 16:06:24 +01:00
atlasan 9496b9206b Translations and fixes
- couple missing strings
- showing error conditioned on kDebug
- debugging network errors
2023-02-02 15:45:01 +01:00
poka 1a3df7d2f8 fix build link script 2023-02-01 23:02:21 +01:00
poka 9f5a15cc40 bump 0.1.0+54 2023-02-01 22:52:28 +01:00
poka 2ea77b0fce Merge remote-tracking branch 'atlasan-PR53/master' 2023-02-01 22:49:08 +01:00
poka 46bc38a1e9 fix flutter icon 2023-02-01 22:41:40 +01:00
poka 0634335854 upgrade flutter 3.7 2023-02-01 22:25:26 +01:00
atlasan 22325f7299 remove unused import - after translations 2023-01-31 16:34:45 +01:00
atlasan 31627c2060 fix format - after translation mods 2023-01-31 16:16:43 +01:00
atlasan 5b561d52ae Translations
- added IT locale
- added some untranslated strings to locale conf files
- this is a first try run test, Doc? Marty
2023-01-31 15:24:13 +01:00
poka 9a4c1d602b fix: bad virtual keybaord for tchois (team peer programming) 2023-01-31 03:14:01 +01:00
poka 8382cbfc29 add tuto package; safe_home is stateful 2022-12-23 01:59:21 +01:00
poka 9983ea9f78 new BalanceBuilder Widget 2022-12-23 01:58:44 +01:00
poka 0ab955b2da GPT fixed this issue (fake offline detection): https://git.duniter.org/clients/gecko/-/issues/21 2022-12-22 23:53:12 +01:00
poka 60ea8ecac1 fix: bad substrate-sdk commit ref 2022-12-18 14:15:11 +01:00
poka 3d9ce9dc14 downgrade flutter_icon to 2.0.4 2022-12-18 13:18:00 +01:00
poka 9ad20184db Merge branch 'dev' 2022-12-14 20:28:15 +01:00
poka 38498d2370 fix: android icon 2022-12-14 20:27:55 +01:00
poka bd97495cd2 Merge branch 'master' into dev 2022-12-14 20:14:54 +01:00
poka 0b4f86638e Merge branch 'dev' 2022-12-14 20:14:42 +01:00
poka b0d29fceb3 fix CI 2 2022-12-14 20:12:20 +01:00
poka e1c5943667 fix CI 1 2022-12-14 20:09:25 +01:00
poka 1364b36cbf fix: flutter format 2022-12-14 20:00:20 +01:00
poka 1f1ccc0882 add hugo bootnode 2022-12-14 19:59:28 +01:00
poka a176611c83 v0.1.0 2022-12-14 19:56:21 +01:00
poka d1194d5eb5 fix: sometime on startup, app says you upgraded dataVersion (but no) and forget your safes... 2022-12-14 19:54:56 +01:00
poka 71d222307b fix: shouln't be able to see "My contacts" menu if you have no safes. 2022-12-14 19:21:51 +01:00
poka bca3082845 upgrade icons generation 2022-12-11 22:13:25 +01:00
poka 5d084f44e7 Merge branch 'dev' 2022-12-10 08:23:57 +01:00
poka d19131e86a big recto: commons Widgets 2022-12-10 08:22:52 +01:00
poka 5e4f135470 Merge branch 'dev' 2022-12-10 06:18:20 +01:00
poka 26cc024b87 UX: global improvements 2022-12-10 06:18:04 +01:00
poka 3ba04470f9 Merge branch 'dev' 2022-12-10 02:21:34 +01:00
poka ad92a06060 Merge branch 'dev-compute-transactionTile' into dev 2022-12-09 06:24:00 +01:00
poka 792ac2f715 fix: bug on delimiter redondance 2022-12-09 06:23:47 +01:00
poka f7fe3fa7df WIP: extract transaction view computation; bug on delimiter redondance 2022-12-09 05:21:00 +01:00
poka c055dbfe3a refacto: new TransactionTile widget 2022-12-09 05:19:34 +01:00
poka 613b6b282e fix: add deboune to search, and swap onChange to sync 2022-12-09 03:48:12 +01:00
poka 8ddd877131 Merge branch 'wip-fix-history' into dev 2022-12-09 03:36:58 +01:00
poka c6cfb4e548 refacto: ContactsList and SearchResult Widget 2022-12-09 03:36:46 +01:00
poka 875341a804 wip: try to fix history begginin 2022-12-08 11:38:45 +01:00
poka 70f4f151c0 safeHome: add safe image in topbar 2022-12-08 09:51:08 +01:00
pokapow c1ebfc62bc Merge branch 'dev' into 'master'
UX: search: action button is paste address if an address is present in clipboard

See merge request clients/gecko!51
2022-12-08 08:20:36 +01:00
poka 7f8d46b9e8 UX: search: action button is paste address if an address is present in clipboard 2022-12-08 08:17:36 +01:00
pokapow 7cdc13273e Merge branch 'dev' into 'master'
Big refacto

See merge request clients/gecko!50
2022-12-08 05:30:12 +01:00
poka 6155552424 Merge branch 'dev-walletsNamesWidget' into dev 2022-12-08 05:27:12 +01:00
poka 622ceda579 UX: improve appBar in safeHome 2022-12-08 05:26:55 +01:00
poka a28df90c18 fix: bad screen view canCert state 2022-12-08 01:18:09 +01:00
poka d7731504c7 big refacto: home screen stateful; walletnames refacto 2022-12-07 23:10:28 +01:00
poka cf4387a280 fix: null username on search_result screen 2022-12-06 22:42:30 +01:00
poka 82c1d5bf4c WIP: bug on walletname edition and display 2022-12-06 22:33:42 +01:00
poka c81662de83 refacto: new UdUnitDisplay Widget 2022-12-06 04:38:33 +01:00
poka 150f6892f8 refacto: new Balance and Certifications Widgets 2022-12-06 04:35:17 +01:00
poka 4ef5f77888 refacto: new WalletName Widget 2022-12-06 03:58:10 +01:00
poka c50aa53f38 refacto: new IdentityStatus Widget 2022-12-06 03:35:35 +01:00
poka 30b8b68bef fix null is not int when initCurrencyParameters
https://sentry.io/share/issue/da813434b4ba48c7b53dadaeb5d70cc1/
2022-12-06 02:47:56 +01:00
poka 535e121505 fix null avlue on indexer blockchainStartTime on app startup
https://sentry.io/share/issue/d26f6b14ddbc4dc59c5a59eaeb975780/
2022-12-06 01:39:22 +01:00
pokapow 88b34b1008 Merge branch 'dev' into 'master'
Dev

See merge request clients/gecko!49
2022-12-05 14:58:01 +01:00
poka b1a5ca748c bump 0.0.14+46 2022-12-05 14:55:44 +01:00
poka e5e71667df UX: big improvements on unlocking screen 2022-12-05 14:49:32 +01:00
poka 9a2b99977e upgrade packages 2022-12-05 06:41:19 +01:00
pokapow cd2c257779 Merge branch 'dev' into 'master'
fix: bad wallet view info

See merge request clients/gecko!48
2022-12-05 04:38:32 +01:00
poka ef7f6eff1b fix: bad wallet view info 2022-12-05 04:34:45 +01:00
pokapow 24aee6a53c Merge branch 'dev' into 'master'
Dev

See merge request clients/gecko!47
2022-12-05 04:18:51 +01:00
poka 853ad0eb6a fix: null username wor simple wallets in search view 2022-12-05 04:16:54 +01:00
poka 25c0144098 refacto: improve username cache 2022-12-05 04:03:53 +01:00
pokapow 1903b988de Merge branch 'dev' into 'master'
Dev

See merge request clients/gecko!46
2022-12-05 02:39:54 +01:00
poka 8b3ecae62f CI fix: The declaration 'callback' isn't referenced 2022-12-05 02:34:51 +01:00
poka 1ea3be788e bump 0.0.14+43 2022-12-05 02:29:52 +01:00
poka ae36f7384e UX: improve search: button and keyboard action 2022-12-05 02:25:49 +01:00
pokapow 44c8cfb9bc Merge branch 'dev' into 'master'
MR: fix bad widget ancestor when popUntil at the end of onboarding + UX: improve certification popup

See merge request clients/gecko!45
2022-12-04 23:24:59 +01:00
poka b924d644b7 UX: improve certification popup 2022-12-04 23:18:30 +01:00
poka 2ae32982f8 fix: bad widget ancestor when popUntil at the end of onboarding 2022-12-04 23:17:46 +01:00
poka 9ed76b071e improve paddings 2022-12-04 03:24:23 +01:00
pokapow 92fd504505 Merge branch 'dev' into 'master'
use new clean polkawallet_sdk fork + add certifications counter; show message if smith try to migrate identity

See merge request clients/gecko!44
2022-12-04 03:09:55 +01:00
poka d749c9a997 CI: fix unused imports 2022-12-04 03:06:35 +01:00
poka 4158a5308c add certifications counter; show message if smith try to migrate identity 2022-12-04 03:03:08 +01:00
poka b4e0f110a3 use new clean polkawallet_sdk fork 2022-12-03 23:40:03 +01:00
poka e602099cc3 Merge branch 'dev' 2022-12-03 10:45:09 +01:00
poka bc75ae114f add ability to copy mnemonic to clipboard on onboarding 2022-12-03 10:44:48 +01:00
poka 9e91408220 Merge branch 'master' into dev 2022-12-03 08:49:57 +01:00
pokapow 42801f8145 Merge branch 'dev' into 'master'
activity screen: add gdev start time delimiter

See merge request clients/gecko!43
2022-12-03 08:48:47 +01:00
poka 806a96d127 activity screen: add gdev start time delimiter 2022-12-03 08:44:44 +01:00
pokapow 5b89f661ed Merge branch 'dev' into 'master'
Dev

See merge request clients/gecko!42
2022-12-03 00:22:00 +01:00
poka 397d795e8b identity confirmation: check if username exist before valdate 2022-12-02 21:18:28 +01:00
poka 4c7326bfaa g1v1 import: display v1 pubkey instead of v2 address 2022-12-02 19:45:46 +01:00
poka 826dcf7c7c fix: double is not int; remove useless typed 2022-12-02 10:23:21 +01:00
poka f19a441af3 add itdy name to appbar; add link in wallet options 2022-12-02 06:58:18 +01:00
poka 7e98a1d063 bump 0.0.12+36 2022-12-02 06:28:46 +01:00
poka 68fe7925ac hotfix: bad parent data 2022-12-02 06:28:19 +01:00
pokapow bafd853884 Merge branch 'certsScreen' into 'master'
add certs screen

See merge request clients/gecko!41
2022-12-02 06:04:13 +01:00
poka 6b1df55ede fix: flutter format 2022-12-02 06:02:30 +01:00
poka 0241efc223 certifications screen is ok 2022-12-02 05:57:24 +01:00
poka 7a93ff4d78 received certs widget is working 2022-12-02 03:22:53 +01:00
poka 9a9bc6788c fuck git. start to implement certs screen 2022-12-02 02:11:22 +01:00
poka 413c3c708e fix: flutter format 2022-12-01 05:23:42 +01:00
poka cf6571e9da add certs screen 2022-12-01 05:23:42 +01:00
poka da0e9ba2df fix: unused imports 2022-12-01 05:21:48 +01:00
poka 80416f5753 change all providers reference to final 2022-12-01 05:21:36 +01:00
poka 96854fddb9 apply point 7 of volune rapport: remove setPreferredOrientations everywhere on app, replace by global boot instruction 2022-12-01 05:21:23 +01:00
Kapis 6c34dd2425 Update assets/onBoarding/gecko_also_can_forget_es.png 2022-12-01 05:18:49 +01:00
Kapis e65915a333 Update assets/onBoarding/forgot_password_es.png
Deleted assets/onBoarding/gecko_also_can_forget_es.png
2022-12-01 05:18:49 +01:00
Kapis b48be00149 Fixed errors and improved translations 2022-12-01 05:18:49 +01:00
Millicent Billette 1481352f6c Update .gitlab-ci.yml file 2022-12-01 03:22:54 +01:00
pokapow bae16d3a5f Merge branch 'finalProvidersReferences' into 'master'
Final providers references

See merge request clients/gecko!39
2022-11-30 06:22:38 +01:00
poka b7311970e2 fix: unused imports 2022-11-30 06:14:27 +01:00
poka 965ce0f977 fix: flutter format 2022-11-30 05:53:46 +01:00
poka 3a5674ae41 change all providers reference to final 2022-11-30 05:51:56 +01:00
pokapow 38c8b9a995 Merge branch 'voluneRapport7' into 'master'
apply point 7 of volune rapport: remove setPreferredOrientations everywhere on...

See merge request clients/gecko!38
2022-11-30 05:27:39 +01:00
poka 8169e1e840 apply point 7 of volune rapport: remove setPreferredOrientations everywhere on app, replace by global boot instruction 2022-11-30 05:22:37 +01:00
pokapow e88cf3b2f7 Merge branch 'scanlegentil-master-patch-45604' into 'master'
Update assets/translations/es.json

See merge request clients/gecko!37
2022-11-28 11:21:07 +01:00
Scan le Gentil cc36e2652d Update assets/translations/es.json, assets/translations/fr.json 2022-11-28 11:17:11 +01:00
poka 6ea827faf9 fix: homeContext randomly reset after pushNamedAndRemoveUntil 2022-11-28 07:11:39 +01:00
poka 44993557c6 add gdev.p2p.legal endpoint 2022-11-27 03:30:49 +01:00
132 changed files with 5379 additions and 3318 deletions

6
.gitignore vendored
View File

@ -47,9 +47,6 @@ android/key.properties
# Rust things
/target
# Linux builds
linux/
# Custom
scripts/private/
AppDir/
@ -59,5 +56,4 @@ android/app/build.gradle
integration_test/duniter/data/chains/
# Ignore PC deps
macos/
windows/
scripts/pushGecko

View File

@ -7,7 +7,7 @@ stages:
.env:
image: axiomteam/gecko-ci:v0.0.11
tags:
- redshift
- docker
format:
extends: .env
@ -28,9 +28,10 @@ build_and_test:
- if: $CI_COMMIT_TAG || $CI_MERGE_REQUEST_ID
- when: manual
stage: build_and_test
tags:
- redshift
script:
- flutter clean
- rm -rf /root/.pub-cache
- flutter pub get
- flutter analyze
releases:test:

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

After

Width:  |  Height:  |  Size: 192 KiB

BIN
assets/party.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -71,7 +71,8 @@
"areYouSureToDeleteWallet": "Are you sure you want to delete the chest \"{}\"?",
"areYouSureForgetAllChests": "Are you sure you want to forget all your chests?",
"areYouSureToForgetWallet": "Are you sure you wan to forget the wallet \"{}\"?",
"areYouSureYouWantToCertify": "Are you sure you want to certify the address:\n\n{}",
"areYouSureYouWantToCertify1": "Are you sure you want to certify the identity :",
"areYouSureYouWantToCertify2": "having the address :",
"yes": "Yes",
"no": "No",
"keepYourMnemonicSecret": "Try to keep this phrase a secret, as it allows anyone who knows it to access all your wallets.",
@ -103,6 +104,7 @@
"identityConfirmed": "Identity confirmed",
"identityExpired": "Identity expired",
"confirmYourIdentity": "Confirm your identity",
"noResult": "No results",
"noDuniterNodeAvailableTryLater": "No Duniter node available, please try again later",
"youAreConnectedToNode": "You are connected to node",
"accountActivity": "Account activity",
@ -156,7 +158,7 @@
"hours": "{} hours {}",
"days": "{} days",
"months": "{} months",
"certify": "Certify",
"certify": "Certify this\nidentity",
"from": "From:",
"to": "To:",
"amount": "Amount:",
@ -168,7 +170,7 @@
"deleteThisWallet": "Delete this wallet",
"cancel": "Cancel",
"inBlockchainResult": "In {} blockchain",
"search": "Search",
"search": "Search an identity\nor an address",
"currencyNode": "{} node :",
"contactsManagementWithNbr": "My contacts ({})",
"contactsManagement": "My contacts",
@ -195,5 +197,24 @@
"youCannotRevokeThisIdentity": "You cannot revoke this identity while\nit is member of the blacksmiths web",
"showUdAmounts": "Show amounts in UD",
"ud": "{}UD",
"chooseATargetWallet": "Choose a target wallet"
"chooseATargetWallet": "Choose a target wallet",
"thisMnemonicHasBeenCopiedToClipboard": "This mnemonic has been copied to clipboard",
"smithCantMigrateIdentity":"You can't migrate this identity while you're member of smith web",
"received": "Received",
"sent": "Sent",
"createIdentity": "Create a new \nidentity",
"memberAccountOf": "Account of {}",
"pasteAddress": "Paste address from\nclipboard",
"historyStart" :"Beginning of history",
"blockchainStart": "Beginning of the ĞDev",
"networkSettings": "Network Settings",
"displaySettings": "Display Settings",
"indexer": "Indexer",
"anAutoNodeChoosed": "A secure and valid node will be automatically used from a random list.",
"rootWallet": "Root Wallet",
"blockN": "block N°{}",
"thisIsNotAGoodCode": "This is not a good code",
"youHaveToBeConnectedToValidateChest": "You have to be connected\nto validate your chest",
"thisIdentityAlreadyExist": "This identity already exists"
}

View File

@ -1,90 +1,92 @@
{
"searchWallet": "Buscar\nbilletera",
"manageWallets": "Gestionar\nbilleteras",
"searchWallet": "Buscar\nmonedero",
"manageWallets": "Gestionar\nmonederos",
"scanQRCode": "Escanear un\ncódigo QR",
"wellConnectedToNode": "Estas bien conectada al nodo\n{}",
"wellConnectedToNode": "Estás bien conectado al nodo\n{}",
"networkLost": "Se ha perdido la red...",
"noDuniterEndointAvailable": "No hay servidor disponible...",
"connectionPending": "Conexión pendiente...",
"noLizard": "no hay lagarto ;-)",
"loading": "Cargando...",
"forgot_password.png": "forgot_password_en.png",
"warningForgotPassword": "In a blockchain, there is no email recovery procedure. Only your recovery phrase can allow you to recover your Ğ1 at any time.",
"forgot_password.png": "forgot_password_es.png",
"warningForgotPassword": "En una cadena de bloques o blockchain, no hay procedimiento de recuperación mediante correo electrónico. Sólo tu frase de recuperación puede permitirte recuperar tus Ğ1 en cualquier momento.",
"fastAppDescription": "La aplicación de pago {}\nmás rápida que un reptil de Vietnam",
"createWallet": "Crear una billetera",
"restoreWallet": "Restaurar mis billeteras",
"createWallet": "Crear un monedero",
"restoreWallet": "Restaurar mis monederos",
"parameters": "Parámetros",
"chooseAnotherMnemonic": "Choose an other\nmnemonic sentence",
"iNotedMyMnemonic": "He escrito mi frase",
"printMyMnemonic": "Print my mnemonic sentence",
"manageChest": "Configure this chest",
"changeChest": "Change chest",
"geckoChest": "Ğecko chest",
"toUnlockEnterPassword": "To unlock your safe, enter your secret code, away from prying lizards:",
"rememberPassword": "Keep this code in memory for 15 minutes",
"myRootWallet": "Mi billetera principal",
"currentWallet": "My current chest",
"wallet": "Billetera",
"displayMnemonic": "Display my mnemonic sentence",
"chooseAnotherMnemonic": "Elige otra frase de restauración",
"iNotedMyMnemonic": "He anotado mi frase de restauración",
"printMyMnemonic": "Imprimir mi frase de restauración",
"manageChest": "Configurar este cofre",
"changeChest": "Cambiar de cofre",
"GeckoChest": "Cofre de Ğecko",
"toUnlockEnterPassword": "Para desbloquear tu cofre, introduce tu contraseña, lejos de lagartijas curiosas:",
"rememberPassword": "Mantener en memoria mi contraseña durante 15 minutos",
"myRootWallet": "Mi monedero principal",
"currentWallet": "Mi cofre actual",
"wallet": "monedero",
"displayMnemonic": "Mostrar mi frase de restauración",
"changePassword": "Cambiar mi contraseña",
"createDerivation": "Create a new derivation",
"createCustomDerivation": "Create a new custom derivation",
"deleteChest": "Delete this chest",
"openThisChest": "Open this chest",
"createChest": "Create a new chest",
"importChest": "Import a chest",
"selectMyChest": "Select my chest",
"accessMyChest": "Access my chest",
"manageMembership": "Manage my membership",
"chooseThisWallet": "Elegir esta billetera",
"thisWalletIsDefault": "This wallet is the default one",
"defineWalletAsDefault": "Define this as the default one",
"displayActivity": "Display activity",
"displayNActivity": "Display\nactivity",
"createDerivation": "Crear una nueva derivación",
"createCustomDerivation": "Crear una nueva derivación personalizada",
"deleteChest": "Borrar este cofre",
"openThisChest": "Abrir este cofre",
"createChest": "Crear un nuevo cofre",
"importChest": "Importar un cofre",
"selectMyChest": "Seleccionar mi cofre",
"accessMyChest": "Acceder a mi cofre",
"manageMembership": "Administrar mi afiliación",
"chooseThisWallet": "Elegir este monedero",
"thisWalletIsDefault": "Monedero definido por defecto",
"defineWalletAsDefault": "Definir este monedero como por defecto",
"displayActivity": "Visualizar actividad",
"displayNActivity": "Visualizar\nactividad",
"memberValidated": "Miembro validado!",
"copyAddress": "Copiar\ndirección",
"copyAddress": "Copiar\nla dirección",
"copy": "Copiar",
"thisAddressHasBeenCopiedToClipboard": "Esta dirección se ha copiado al cortapapeles",
"chooseWalletName": "Choose a new name\nfor your wallet:",
"choosePassword": "Choose a random password:",
"chooseDerivation": "Choose a derivation:",
"thisAddressHasBeenCopiedToClipboard": "Esta dirección se ha copiado al portapapeles",
"chooseWalletName": "Elige un nuevo nombre\npara tu monedero:",
"choosePassword": "Elige una contraseña aleatoria:",
"chooseDerivation": "Elige una derivación:",
"validate": "Validar",
"confirm": "Confirmar",
"confirmPayment": "Confirmar pago",
"geckoGenerateYourWalletFromMnemonic": "Ğecko builds your wallet from a **restoration sentence**. It is a bit like the blueprint that builds your wallet.",
"keepThisMnemonicSecure": "Keep this sentence carefully, because without it Ğecko will not be able to rebuild your wallets the day you change your phone.",
"geckoGeneratedYourMnemonicKeepItSecret": "Ğecko generated your mnemonic successfully! Keep it secret, because anyone who knows it can access all your wallets.",
"newWallet": "New Wallet",
"itsTimeToUseAPenAndPaper": "It's time to take a **pen and paper** in order to write down your mnemonic.",
"yourMnemonic": "Your mnemonic",
"gecko_also_can_forget.png": "gecko_also_can_forget_en.png",
"didYouNoteMnemonicToBeSureTypeWord": "Did you write down your menmonic?\n\n To be sure, please type the **{}th word** of your restoration phrase in the field below:",
"geckoWillGenerateAPassword": "Gecko will now generate for you a short password that will allow you to quickly access your wallets, without having to type your recovery sentence every time.",
"myPassword": "My password",
"thisPasswordProtectsYourWalletsInASecureChest": "This secret code protects your wallets in a safe **which only you have the code for**, so that your wallets cannot be used by others.",
"hereIsThePasswordKeepIt": "And here is your password!\n\nMemorize it or write it down, because you will be asked **every time** you want to make a payment on this device.",
"GeckoGenerateYourWalletFromMnemonic": "Ğecko construye tu monedero a partir de una **frase de restauración**. Es como unos planos que permiten restaurar tu monedero.",
"keepThisMnemonicSecure": "Guarda esta frase con cuidado, porque sin ella Ğecko no podrá restaurar tus monederos el día que cambies de dispositivo.",
"GeckoGeneratedYourMnemonicKeepItSecret": "¡Ğecko generó tu frase de restauración con éxito! Mantenla en secreto, porque cualquiera que la sepa puede acceder a todos tus monederos.",
"newWallet": "Nuevo monedero",
"itsTimeToUseAPenAndPaper": "Es el momento de coger un **papel y un bolígrafo** para anotar tu frase de restauración.",
"yourMnemonic": "tu frase de restauración",
"gecko_also_can_forget.png": "gecko_also_can_forget_es.png",
"didYouNoteMnemonicToBeSureTypeWord": "¿Anotaste bien tu frase de restauración? Para asegurarnos, escriba la **palabra #{}** de tu frase de restauración en el cuadro de abajo:",
"GeckoWillGenerateAPassword": "Ahora Ğecko te generará una contraseña corta que te permitirá acceder rápidamente a tus monederos, sin tener que escribir cada vez tu frase de recuperación.",
"myPassword": "Mi contraseña",
"thisPasswordProtectsYourWalletsInASecureChest": "Esta contraseña protege tus monederos en un cofre **del que sólo tú tienes acceso**, para que tus monederos no puedan ser utilizados por otros.",
"hereIsThePasswordKeepIt": "¡Y aquí está tu contraseña!\n\nMemorízala o anótala, porque Ğecko te la pedirá **cada vez** que quieras hacer un pago en este dispositivo.",
"chooseAnotherPassword": "Elige otra contraseña",
"iNotedMyPassword": "I noted my password",
"geckoWillCheckPassword": "Gecko will check with you if you have remembered your secret code.\n\n Type your secret code in the field below to check that you have written it down correctly.",
"yourChestAndWalletWereCreatedSuccessfully": "Super!\n\nYour chest and your first portfolio have been created with great success.\n\nCongratulations!",
"allGood": "That's all good!",
"areYouSureToDeleteWallet": "Are you sure you want to delete the chest \"{}\"?",
"areYouSureForgetAllChests": "Are you sure you want to forget all your chests?",
"areYouSureToForgetWallet": "Are you sure you wan to forget the wallet \"{}\"?",
"areYouSureYouWantToCertify": "Are you sure you want to certify the address:\n\n{}",
"yes": "Si",
"iNotedMyPassword": "He anotado mi contraseña",
"GeckoWillCheckPassword": "Ğecko comprobará contigo si has recordado tu contraseña. Escribe tu contraseña en el cuadro de abajo para comprobar que lo has apuntado correctamente.",
"yourChestAndWalletWereCreatedSuccessfully": "¡Genial!\n\nTu cofre y tu primer monedero han sido creados con éxito.\n\n¡Felicidades!",
"allGood": "¡Todo bien!",
"areYouSureToDeleteWallet": "¿Seguro de que quieres eliminar el cofre \"{}\"?",
"areYouSureForgetAllChests": "¿Seguro de que quieres olvidar todos tus cofres?",
"areYouSureToForgetWallet": "¿Seguro de que quieres olvidar el monedero \"{}\"?",
"areYouSureYouWantToCertify": "¿Seguro de que quiere certificar a la dirección\n\n{}?",
"areYouSureYouWantToCertify1": "¿Seguro de que quiere certificar a la identidad :",
"areYouSureYouWantToCertify2": " a la dirección :",
"yes": "Sí",
"no": "No",
"keepYourMnemonicSecret": "Try to keep this phrase a secret, as it allows anyone who knows it to access all your wallets.",
"iGeneratedYourMnemonicKeepItSecret": "I've generated your restoration phrase!\n Try to keep it a secret, as it allows anyone who knows it to access all your portfolios.",
"myMnemonic": "My mnemonic",
"close": "Close",
"toRestoreEnterMnemonic": "To restore your Gecko wallets, enter in the fields below the 12 words that constitute your restoration phrase:",
"pasteFromClipboard": "Paste from\nclipboard",
"restoreAChest": "Restore a chest",
"restoreThisChest": "Restore this chest",
"keepYourMnemonicSecret": "Intenta mantener esta frase de restauración en secreto, ya que permite a cualquiera que la conozca acceder a todas tus monederos.",
"iGeneratedYourMnemonicKeepItSecret": "¡He generado tu frase de restauración!\nIntenta mantenerla en secreto, ya que permite a cualquiera que la conozca acceder a todos tus monederos.",
"myMnemonic": "Mi frase de restauración",
"close": "Cerrar",
"toRestoreEnterMnemonic": "Para restaurar tus monederos Ğecko, introduce las 12 palabras que componen tu frase de restauración en los cuadros de abajo:",
"pasteFromClipboard": "Pegar del\nportapapeles",
"restoreAChest": "Restaurar un cofre",
"restoreThisChest": "Restaurar este cofre",
"continue": "Continuar",
"itsTheGoodWord": "It's the good word!",
"nthMnemonicWord": "word of your mnemonic",
"itsTheGoodWord": "¡Es la palabra correcta!",
"nthMnemonicWord": "palabra de tu mnemotecnia",
"1th": "Primera",
"2th": "Segunda",
"3th": "Tercera",
@ -98,17 +100,18 @@
"11th": "Undécima",
"12th": "Duodécima",
"yourPasswordLengthIsX": "La longitud de tu contraseña es {}",
"noIdentity": "No identity",
"noIdentity": "Ninguna identidad",
"identityCreated": "Identidad creada",
"identityConfirmed": "Identidad confirmada",
"identityExpired": "Identitdad caducada",
"identityExpired": "Identidad caducada",
"confirmYourIdentity": "Confirma tu identidad",
"noDuniterNodeAvailableTryLater": "No Duniter node available, please try again later",
"youAreConnectedToNode": "You are connected to node",
"noResult": "Ningún resultado",
"noDuniterNodeAvailableTryLater": "No hay ningún nodo Duniter disponible, por favor, inténtalo más tarde",
"youAreConnectedToNode": "Estás conectado al nodo",
"accountActivity": "Actividad de la cuenta",
"noNetworkNoHistory": "Network state does not allow\nto display account history",
"noDataToDisplay": "No data to be displayed.",
"noTransactionToDisplay": "No transaction to display",
"noNetworkNoHistory": "El estado de la red no permite\nmostrar el historial de la cuenta",
"noDataToDisplay": "No hay datos que mostrar.",
"noTransactionToDisplay": "No hay transacciónes a mostrar",
"month1": "Enero",
"month2": "Febrero",
"month3": "Marzo",
@ -124,76 +127,94 @@
"today": "Hoy",
"yesterday": "Ayer",
"thisWeek": "Esta semana",
"chestNotCompatibleMustReinstallGecko": "The version of your safes is no longer compatible with this version of Ğecko.\nAll your safes will be forgotten, you must import them again.",
"notConnectedToInternet": "No estas conectado a internet",
"researchResults": "Results of your research",
"resultsFor": "Results for ",
"forgetAllMyChests": "Forget all my chests",
"transaction": "Transaccion",
"certification": "Certificacion",
"identityConfirm": "Identity confirmation",
"revokeAdhesion": "Adhesion revocation",
"strangeTransaction": "Strange transaction",
"chestNotCompatibleMustReinstallGecko": "La versión de tus cofres no es compatible con esta versión de Ğecko.\nTodos tus cofres serán olvidados, debes importarlos de nuevo.",
"notConnectedToInternet": "No estás conectado a Internet",
"researchResults": "Resultados de tu búsqueda",
"resultsFor": "Resultados para ",
"forgetAllMyChests": "Olvida todos mis cofres",
"transaction": "Transacción",
"certification": "Certificación",
"identityConfirm": "Confirmación de la identidad",
"revokeAdhesion": "Revocación de adhesión",
"strangeTransaction": "Transacción extraña",
"sending": "Enviando...",
"propagating": "Propagando...",
"validating": "Validando...",
"anErrorOccurred": "Ocurrió un error",
"24hbetweenCerts": "You have to wait 24h between certs",
"canNotCertifySelf": "You can not certify yourself",
"nameAlreadyExist": "This name is already taken",
"2GDtoKeepAlive": "You have to keep at least 2ĞD to keep your account alive",
"youHaveToFeedThisAccountBeforeUsing": "You have to feed this account\nbefore using it.",
"execTimeoutOver": "Execution timeout is over",
"seeAWallet": "Ver una billetera",
"anErrorOccured": "Ocurrió un error",
"24hbetweenCerts": "Hay que esperar 24 horas entre certificaciones",
"canNotCertifySelf": "No puedes certificarte a ti mismo",
"nameAlreadyExist": "Este nombre ya está ocupado",
"2GDtoKeepAlive": "Tienes que mantener al menos 2ĞD para mantener tu cuenta viva",
"youHaveToFeedThisAccountBeforeUsing": "Tienes que nutrir el balance\nde esta cuenta antes de usarla.",
"execTimeoutOver": "Se ha agotado el tiempo de ejecución",
"seeAWallet": "Ver un monedero",
"mustWaitXBeforeCertify": "Tienes que esperar\n{} antes de\nvolver a certificar",
"mustConfirmHisIdentity": "This person must confirm\nhis identity before can be\ncertified",
"canRenewCertInX": "You can renew\nthis certification\nin {}",
"executeATransfer": "Execute a transfer",
"executeTheTransfer": "Execute the transfer",
"doATransfer" : "Execute a\ntransfer",
"mustConfirmHisIdentity": "Esta persona debe confirmar\nsu identidad antes de poder ser certificada",
"canRenewCertInX": "Podrás renovar\nla certificación\nen {}",
"executeATransfer": "Ejecutar una transacción",
"executeTheTransfer": "Ejecutar la transacción",
"doATransfer" : "Hacer una\ntransacción",
"seconds": "{} segundos",
"minutes": "{} minutos",
"hours": "{} horas {}",
"days": "{} dias",
"months": "{} meses",
"certify": "Certify",
"certify": "Certificar esta\nidentidad",
"from": "De:",
"to": "A:",
"amount": "Importe:",
"choiceOfSourceWallet": "Choose a source wallet",
"choiceOfSourceWallet": "Elige un monedero de origen",
"extrinsicInProgress": "{} en progreso",
"extrinsicValidated": "{} validado !",
"extrinsicValidated": "¡ {} validado !",
"fromMinus": "de",
"toMinus": "a",
"deleteThisWallet": "Delete this wallet",
"deleteThisWallet": "Borrar este monedero",
"cancel": "Cancelar",
"inBlockchainResult": "In {} blockchain",
"search": "Buscar",
"currencyNode": "{} nodo :",
"inBlockchainResult": "En la blockchain {}",
"search": "Buscar una identidad\no una dirección",
"currencyNode": "Nodo {} :",
"contactsManagementWithNbr": "Mis contactos ({})",
"contactsManagement": "Mis contactos",
"noContacts": "You don't have any contact",
"addContact": "Add\nto contacts",
"removeContact": "Remove\nthis contact",
"derivationsScanProgress": "Scan address {}/{}",
"youAreOffline": "You are offline...",
"importG1v1": "Import old G1v1 account",
"selectDestWallet": "Select a target wallet:",
"youMustWaitBeforeCashoutThisAccount": "You have to wait a few moment before migrate this account",
"thisAccountIsEmpty": "This account is empty",
"youCannotMigrateIdentityToExistingIdentity": "You cannot migrate an identity\nto an account that already has an identity",
"importOldAccount": "Import your old account",
"enterCesiumId": "Ingrese su ID de Cesium",
"enterCesiumPassword": "Ingrese su contraseña de Cesium",
"migrateAccount": "Migrate account",
"migrateIdentity": "Migrate identity",
"identityMigration": "Identity migration",
"areYouSureMigrateIdentity": "Are you sure you want to permanently migrate identity **{}** with balance of **{}** ?",
"someoneCreatedYourIdentity": "Someone created your {} identity !",
"noContacts": "No tienes ningún contacto",
"addContact": "Añadir\na contactos",
"removeContact": "Eliminar\neste contacto",
"derivationsScanProgress": "Escaneado de la dirección {}/{}",
"youAreOffline": "Estás desconectado...",
"importG1v1": "Importar la cuenta antigua de G1v1",
"selectDestWallet": "Selecciona un monedero destino:",
"youMustWaitBeforeCashoutThisAccount": "Tienes que esperar unos minutos antes de migrar esta cuenta",
"thisAccountIsEmpty": "Esta cuenta está vacía",
"youCannotMigrateIdentityToExistingIdentity": "No se puede migrar una identidad\na una cuenta que ya tiene una identidad",
"importOldAccount": "Importar antigua cuenta",
"enterCesiumId": "Ingresa tu frase secreta de Cesium",
"enterCesiumPassword": "Ingresa tu contraseña de Cesium",
"migrateAccount": "Migrar cuenta",
"migrateIdentity": "Migrar identidad",
"identityMigration": "Migración de la identidad",
"areYouSureMigrateIdentity": "¿Estás seguro de que quieres migrar permanentemente la identidad **{}** con saldo de **{}**?",
"someoneCreatedYourIdentity": "¡ Alguien ha creado tu {} identidad !",
"confirmMyIdentity": "Confirmar mi identidad",
"revokeMyIdentity": "Revocar mi identidad",
"youCannotRevokeThisIdentity": "You cannot revoke this identity while\nit is member of the blacksmiths web",
"showUdAmounts": "Show amounts in UD",
"ud": "{}UD",
"chooseATargetWallet": "Elija una billetera de destino"
"youCannotRevokeThisIdentity": "No puedes revocar esta identidad mientras\nseas miembro de la red de forjadores",
"showUdAmounts": "Mostrar importes en DU",
"ud": "{}DU",
"chooseATargetWallet": "Elige un monedero de destino",
"thisMnemonicHasBeenCopiedToClipboard": "This mnemonic has been copied to clipboard",
"smithCantMigrateIdentity":"You can't migrate this identity while you're member of smith web",
"received": "Received",
"sent": "Sent",
"createIdentity": "Create a new \nidentity",
"memberAccountOf": "Account of {}",
"pasteAddress": "Paste address from\nclipboard",
"historyStart" :"Beginning of history",
"blockchainStart": "Comienzo de la ĞDev",
"networkSettings": "Parametros de red",
"displaySettings": "Parametros interficie",
"indexer": "Indexer",
"anAutoNodeChoosed": "Se usará automáticamente un nodo seguro y valido desde una lista aleatoria.",
"rootWallet": "Monedero raíz",
"blockN": "bloque N°{}",
"thisIsNotAGoodCode": "Este codígo no es valido",
"youHaveToBeConnectedToValidateChest": "Tienes que tener conneción\npara validar tu cofre",
"thisIdentityAlreadyExist": "Esta identidad ya existe"
}

View File

@ -2,7 +2,7 @@
"searchWallet": "Rechercher un\nportefeuille",
"manageWallets": "Gérer mes\nportefeuilles",
"scanQRCode": "Scanner un\nQR code",
"wellConnectedToNode": "Vous êtes bien connecté aux noeud\n{}",
"wellConnectedToNode": "Vous êtes bien connecté au noeud\n{}",
"networkLost": "Le réseau a été perdu...",
"noDuniterEndointAvailable": "Aucun serveur disponible...",
"connectionPending": "Connexion en cours...",
@ -66,12 +66,13 @@
"chooseAnotherPassword": "Choisir un autre code secret",
"iNotedMyPassword": "J'ai noté mon code secret",
"geckoWillCheckPassword": "Gecko va vérifier avec vous si vous avez bien mémorisé votre code secret.\n\nTapez votre code secret dans le champ ci-dessous pour vérifier que vous lavez bien noté.",
"yourChestAndWalletWereCreatedSuccessfully": "Top !\n\nVotre coffre votre premier portefeuille ont été créés avec un immense succès.\n\nFélicitations !",
"yourChestAndWalletWereCreatedSuccessfully": "Top !\n\nVotre coffre et votre premier portefeuille ont été créés avec un immense succès.\n\nFélicitations !",
"allGood": "Cest tout bon !",
"areYouSureToDeleteWallet": "Êtes-vous sûr de vouloir supprimer le coffre \"{}\" ?",
"areYouSureForgetAllChests": "Êtes-vous sûr de vouloir oublier tous vos coffres ?",
"areYouSureToForgetWallet": "Êtes-vous sûr de vouloir oublier le portefeuille \"{}\" ?",
"areYouSureYouWantToCertify": "Êtes-vous certain de vouloir certifier l'adresse:\n\n{}",
"areYouSureYouWantToCertify1": "Êtes-vous certain de vouloir certifier l'identité :",
"areYouSureYouWantToCertify2": "ayant pour adresse :",
"yes": "Oui",
"no": "Non",
"keepYourMnemonicSecret": "Tâchez de garder cette phrase bien secrète, car elle permet à quiconque la connaît daccéder à tous vos portefeuilles.",
@ -157,19 +158,19 @@
"hours": "{} heures {}",
"days": "{} jours",
"months": "{} mois",
"certify": "Certifier",
"certify": "Certifier cette\nidentité",
"from": "Depuis:",
"to": "Vers:",
"amount": "Montant:",
"choiceOfSourceWallet": "Choix du portefeuille source",
"extrinsicInProgress": "{} en cours",
"extrinsicValidated": "{} validé !",
"extrinsicValidated": "{} validée !",
"fromMinus": "de",
"toMinus": "vers",
"deleteThisWallet": "Supprimer ce portefeuille",
"cancel": "Annuler",
"inBlockchainResult": "Dans la blockchain {}",
"search": "Rechercher",
"search": "Rechercher une identité\nou une adresse",
"currencyNode": "Noeud {} :",
"contactsManagementWithNbr": "Mes contacts ({})",
"contactsManagement": "Mes contacts",
@ -180,7 +181,7 @@
"youAreOffline": "Vous êtes hors ligne...",
"importG1v1": "Importer un ancien compte G1v1",
"selectDestWallet": "Sélectionnez un portefeuille cible:",
"youMustWaitBeforeCashoutThisAccount": "Vous devez attendre quelques minutes avant de pouvoir migrer ce compte",
"youMustWaitBeforeCashoutThisAccount": "Vous devez attendre quelques minutes\navant de pouvoir migrer ce compte",
"thisAccountIsEmpty": "Ce compte est vide",
"youCannotMigrateIdentityToExistingIdentity": "Vous ne pouvez pas migrer une identité\nvers un compte disposant déjà d'une identité",
"importOldAccount": "Importer son ancien compte",
@ -196,5 +197,23 @@
"youCannotRevokeThisIdentity": "Vous ne pouvez pas révoquer cette identité tant\nqu'elle fait partie de la toile forgerons",
"showUdAmounts": "Afficher les montants en DU",
"ud": "{}DU",
"chooseATargetWallet": "Choisissez un portefeuille cible"
}
"chooseATargetWallet": "Choisissez un portefeuille cible",
"thisMnemonicHasBeenCopiedToClipboard": "Cette phrase secrète viens d'être copié dans votre presse-papier.",
"smithCantMigrateIdentity":"Vous ne pouvez pas migrer cette identité\ntant que vous êtes dans la toile forgerons",
"received": "Reçus",
"sent": "Envoyés",
"createIdentity": "Créer sa nouvelle\nidentité",
"memberAccountOf": "Compte de {}",
"pasteAddress": "Coller l'adresse depuis\nle presse-papier",
"historyStart" :"Début de l'historique",
"blockchainStart": "Début de la ĞDev",
"networkSettings": "Connectivité réseau",
"displaySettings": "Affichage",
"indexer": "Indexer",
"anAutoNodeChoosed": "Un noeud sûr et valide sera choisi automatiquement parmis une liste aléatoire.",
"rootWallet": "Portefeuille racine",
"blockN": "bloc N°{}",
"thisIsNotAGoodCode": "Ce n'est pas le bon code",
"youHaveToBeConnectedToValidateChest": "Vous devez vous connecter à internet\npour valider votre coffre",
"thisIdentityAlreadyExist": "Cette identité existe déjà"
}

220
assets/translations/it.json Normal file
View File

@ -0,0 +1,220 @@
{
"searchWallet": "Cerca\nportafoglio",
"manageWallets": "Gestisci\nportafogli",
"scanQRCode": "Scannerizza un\ncodice QR",
"wellConnectedToNode": "Sei ben connesso al nodo\n{}",
"networkLost": "Rete persa...",
"noDuniterEndointAvailable": "Server non disponibile...",
"connectionPending": "Connessione in corso...",
"noLizard": "non ci sono lucertole ;-)",
"loading": "Caricando...",
"forgot_password.png": "forgot_password_es.png",
"warningForgotPassword": "In una catena di blocchi o blockchain, non ci sono procedure per recupero tramite email. Solo la tua frase di recupero puó permetterti di recuperare i tuoi Ğ1 in qualunque momento.",
"fastAppDescription": "L'applicazione di pagamento {}\npiú rapida che un rettile del Vietnam",
"createWallet": "Crea un portafoglio",
"restoreWallet": "Restaura miei portafogli",
"parameters": "Parametri",
"chooseAnotherMnemonic": "Scegli un'altra frase di recupero",
"iNotedMyMnemonic": "Ho annotato la mia frase di recupero",
"printMyMnemonic": "Stampa la mia frase di recupero",
"manageChest": "Configura questo scrigno",
"changeChest": "Cambia scrigno",
"GeckoChest": "Scrigno di Ğecko",
"toUnlockEnterPassword": "Per sbloccare il tuo scrigno, introduci la password, lontano da lucertole curiose:",
"rememberPassword": "Mantieni in memoria la mia password per 15 minuti",
"myRootWallet": "Il mio portafoglio principale",
"currentWallet": "Il mio scrigno attuale",
"wallet": "portafoglio",
"displayMnemonic": "Mostra la mia frase di recupero",
"changePassword": "Cambia la mia password",
"createDerivation": "Crea una nuova derivazione",
"createCustomDerivation": "Crea una nuova derivazione personalizzata",
"deleteChest": "Elimina questo scrigno",
"openThisChest": "Apri questo scrigno",
"createChest": "Crea un nuovo scrigno",
"importChest": "Importa uno scrigno",
"selectMyChest": "Seleziona scrigno",
"accessMyChest": "Accedi a scrigno",
"manageMembership": "Amministra affiliazione",
"chooseThisWallet": "Scegli questo portafoglio",
"thisWalletIsDefault": "portafoglio predefinito",
"defineWalletAsDefault": "Imposta come predefinito",
"displayActivity": "Visualizza attivitá",
"displayNActivity": "Visualizza\nattivitá",
"memberValidated": "Membro confermato!",
"copyAddress": "Copia\nl'indirizzo",
"copy": "Copia",
"thisAddressHasBeenCopiedToClipboard": "Questo indirizzo é stato copiato negli appunti",
"chooseWalletName": "Scegli un nuovo nome\nper il tuo portafoglio:",
"choosePassword": "Scegli una password casuale:",
"chooseDerivation": "Scegli una derivazione:",
"validate": "Valida",
"confirm": "Conferma",
"confirmPayment": "Conferma pagamento",
"GeckoGenerateYourWalletFromMnemonic": "Ğecko costruisce il tuo portafoglio da una **frase di recupero**. É come una mappa che permette ricostruire il tuo portafoglio.",
"keepThisMnemonicSecure": "Sii attento nel salvare e conservare questa frase, perché senza di essa Ğecko non potrá ricostruire il tuo portafoglio il giorno che cambierai dispositivo.",
"GeckoGeneratedYourMnemonicKeepItSecret": "Ğecko ha generato la tua frase di recupero! Mantienila segreta, perché chiunque che la sappia potrá accedere al tuo portafoglio.",
"newWallet": "Nuovo portafoglio",
"itsTimeToUseAPenAndPaper": "É il momento di prendere **carta e penna** per annotare la frase di recupero.",
"yourMnemonic": "la tua frase di recupero",
"gecko_also_can_forget.png": "gecko_also_can_forget_es.png",
"didYouNoteMnemonicToBeSureTypeWord": "Ti sei segnato bene la frase di recupero? Per assicurarcene, scrivi la **parola {}** della tua frase di recupero:",
"GeckoWillGenerateAPassword": "Ora Ğecko ti creerá una password corta che ti permetterá accedere rapidamente ai tuoi portafogli, senza dover ogni volta inserire la frase di recupero.",
"myPassword": "La mia password",
"thisPasswordProtectsYourWalletsInASecureChest": "Questa password protegge i tuo portafogli e uno scrigno **di cui solo tu hai accesso**, cosicché i tuoi portafogli non possano essere usati da altri.",
"hereIsThePasswordKeepIt": "Ecco la tua password!\n\nMemorizzala e annotala, perché Ğecko te la chiederá **ogni volta** che si voglia effettuare una pagamento da questo dispositivo.",
"chooseAnotherPassword": "Scegli un'altra password",
"iNotedMyPassword": "Ho annotato la password",
"GeckoWillCheckPassword": "Ğecko controllará insieme a te se ti ricordi la password. Scrivi la password per controllare che l'hai appuntata correttamente.",
"yourChestAndWalletWereCreatedSuccessfully": "Fantastico!\n\nIl tuo scrigno e il primo portafoglio sono stati creati con successo.\n\nCongratulazioni!",
"allGood": "Tutto bene!",
"areYouSureToDeleteWallet": "Sicuro che vuoi eliminare lo scrigno \"{}\"?",
"areYouSureForgetAllChests": "Sicuro che vuoi dimenticare tutti i tuoi scrigni?",
"areYouSureToForgetWallet": "Sicuro che vuoi dimenticare il tuo portafoglio \"{}\"?",
"areYouSureYouWantToCertify": "Sicuro che vuoi certificare l'indirizzo\n\n{}?",
"areYouSureYouWantToCertify1": "Sicuro che vuoi certificare l'identitá :",
"areYouSureYouWantToCertify2": " all'indirizzo :",
"yes": "Sí",
"no": "No",
"keepYourMnemonicSecret": "Cerca di mantenere questa frase di recupero segreta, essa permette a chiunque la conosca di accedere a tutti i tuoi portafogli.",
"iGeneratedYourMnemonicKeepItSecret": "La tua frase di recupero é stata creata!\nCerca di mantenere questa frase di recupero segreta, essa permette a chiunque la conosca di accedere a tutti i tuoi portafogli.",
"myMnemonic": "la mia frase di recupero",
"close": "Chiudi",
"toRestoreEnterMnemonic": "Per recuperare i tuoi portafogli Ğecko, introduci le 12 parole che compongono la tua frase di recupero:",
"pasteFromClipboard": "Incolla dagli\nappunti",
"restoreAChest": "Recupera uno scrigno",
"restoreThisChest": "Recupera questo scrigno",
"continue": "Continua",
"itsTheGoodWord": "É la parola corretta!",
"nthMnemonicWord": "parola della tua mnemotecnia",
"1th": "Prima",
"2th": "Seconda",
"3th": "Terza",
"4th": "Quarta",
"5th": "Quinta",
"6th": "Sesta",
"7th": "Settima",
"8th": "Ottava",
"9th": "Nona",
"10th": "Decima",
"11th": "Undicesima",
"12th": "Dodicesima",
"yourPasswordLengthIsX": "La lunghezza della tua password é {}",
"noIdentity": "Nessuna identitá",
"identityCreated": "Identitá creata",
"identityConfirmed": "Identitá confermata",
"identityExpired": "Identitá scaduta",
"confirmYourIdentity": "Conferma identitá",
"noResult": "Nessun risultato",
"noDuniterNodeAvailableTryLater": "Non ci sono nodi Duniter disponibili, per favore, riprova piú tardi",
"youAreConnectedToNode": "Sei connesso al nodo",
"accountActivity": "Attivitá del conto",
"noNetworkNoHistory": "Lo stato della rete non lo permette\nmostra lo storico del conto",
"noDataToDisplay": "Non ci sono dati da mostrare.",
"noTransactionToDisplay": "Non ci sono transazioni da mostrare",
"month1": "Gennaio",
"month2": "Febbraio",
"month3": "Marzo",
"month4": "Aprile",
"month5": "Maggio",
"month6": "Giugno",
"month7": "Luglio",
"month8": "Agosto",
"month9": "Settembre",
"month10": "Ottobre",
"month11": "Novembre",
"month12": "Dicembre",
"today": "Oggi",
"yesterday": "Ieri",
"thisWeek": "Questa settimana",
"chestNotCompatibleMustReinstallGecko": "la versione dei tuoi scrigni non é compatibile con questa versione di Ğecko.\nTutti i tuoi scrigni saranno dimenticati, dovrai importarli di nuovo.",
"notConnectedToInternet": "Non connesso ad Internet",
"researchResults": "Risultati ricerca",
"resultsFor": "Risultati per ",
"forgetAllMyChests": "Dimentica tutti i miei scrigni",
"transaction": "Transazione",
"certification": "Certificazione",
"identityConfirm": "Conferma di identitá",
"revokeAdhesion": "Revocazione di adesione",
"strangeTransaction": "Transazione 'strana'",
"sending": "Inviando...",
"propagating": "Propagando...",
"validating": "Validando...",
"anErrorOccured": "Si é verificato un errore",
"24hbetweenCerts": "Bisogna aspettare 24 ore fra le certificazioni",
"canNotCertifySelf": "Non puoi certificare te stesso",
"nameAlreadyExist": "Nome giá in uso",
"2GDtoKeepAlive": "Devi mantenere almeno 2ĞD per mantenere il conto vivo",
"youHaveToFeedThisAccountBeforeUsing": "Devi incrementare il saldo\ndi questo conto prima di usarlo.",
"execTimeoutOver": "Tempo di esecuzione terminato",
"seeAWallet": "Vedi un portafoglio",
"mustWaitXBeforeCertify": "Devi aspettare\n{} prima di\ncertificare di nuovo",
"mustConfirmHisIdentity": "Questa persona deve confermare\nla sua identitá prima di essere certificata",
"canRenewCertInX": "Potrai rinnovare\nla certificazione\nin {}",
"executeATransfer": "Esegui una transazione",
"executeTheTransfer": "Esegui la transazione",
"doATransfer" : "Esegui una\ntransazione",
"seconds": "{} secondi",
"minutes": "{} minuti",
"hours": "{} ore {}",
"days": "{} giorni",
"months": "{} mesi",
"certify": "Certifica questa\nidentitá",
"from": "Da:",
"to": "A:",
"amount": "Importo:",
"choiceOfSourceWallet": "Scegli un portafoglio sorgente",
"extrinsicInProgress": "{} in corso",
"extrinsicValidated": "¡ {} validato !",
"fromMinus": "da",
"toMinus": "a",
"deleteThisWallet": "Elimina questo portafoglio",
"cancel": "Annulla",
"inBlockchainResult": "Nella blockchain {}",
"search": "Cerca una identitá\no un indirizzo",
"currencyNode": "Nodo {} :",
"contactsManagementWithNbr": "I miei contatti ({})",
"contactsManagement": "I miei contatti",
"noContacts": "Non ci sono contatti salvati",
"addContact": "Aggiungi\nun contatto",
"removeContact": "Elimina\nquesto contatto",
"derivationsScanProgress": "Scannerizzando l'indirizzo {}/{}",
"youAreOffline": "Disconnesso...",
"importG1v1": "Importa il conto antico da G1v1, versione precedente",
"selectDestWallet": "Seleziona un portafoglio di destinazione:",
"youMustWaitBeforeCashoutThisAccount": "Devi aspettare qualche minuto prima di migrare questo conto",
"thisAccountIsEmpty": "Questo conto é vuoto",
"youCannotMigrateIdentityToExistingIdentity": "Non si puó migrare un'identitá\na un conto che ne ha giá una",
"importOldAccount": "Importa conto precedente",
"enterCesiumId": "Inserisci la tua frase segreta di Cesium",
"enterCesiumPassword": "Inserisci la tua password di Cesium",
"migrateAccount": "Migra conto",
"migrateIdentity": "Migra identitá",
"identityMigration": "Migrazione dell'identitá",
"areYouSureMigrateIdentity": "Sei sicuro che vuoi permanentemente migrare l'identitá **{}** con saldo di **{}**?",
"someoneCreatedYourIdentity": "Qualcuno ha creato la tua {} identitá !",
"confirmMyIdentity": "Conferma la mia identitá",
"revokeMyIdentity": "Revoca la mia identitá",
"youCannotRevokeThisIdentity": "Non puoi revocare questa identitá fintanto che\nappartieni alla rete di forgiatori",
"showUdAmounts": "Mostra importi in DU",
"ud": "{}DU",
"chooseATargetWallet": "Scegli un portafoglio di destinazione",
"thisMnemonicHasBeenCopiedToClipboard": "Questo mnemonic é statocopiato negli appunti",
"smithCantMigrateIdentity":"Non puoi migrare questa identitá fintanto che\nappartieni alla rete di forgiatori",
"received": "Ricevuto",
"sent": "Inviato",
"createIdentity": "Crea una nuova \nidentitá",
"memberAccountOf": "Conto di {}",
"pasteAddress": "Incolla l'indirizzo \ndagli appunti",
"historyStart" :"Inizio della storia",
"blockchainStart": "Inizio di ĞDev",
"networkSettings": "Impostazioni di rete",
"displaySettings": "Impostazioni interfaccia",
"indexer": "Indexer",
"anAutoNodeChoosed": "Un nodo sicuro e valido sará automaticamente scelto da una lista casuale.",
"rootWallet": "Portafoglio radice",
"blockN": "blocco N°{}",
"thisIsNotAGoodCode": "Questo codice non é valido",
"youHaveToBeConnectedToValidateChest": "Vous devez vous connecter à internet\npour valider votre coffre",
"thisIdentityAlreadyExist": "Identitá giá esistente"
}

View File

@ -1,3 +1,4 @@
[
"wss://gdev.librelois.fr/ws"
"wss://gdev.p2p.legal/ws",
"wss://gdev.trentesaux.fr/ws"
]

View File

@ -0,0 +1 @@
7bd0907a4984e1ab7899edce63b2e286e8f3daad5a8e2bff40cee61ca6b036cd

View File

@ -51,7 +51,7 @@ Future payTest2() async {
await tapKey(keyConfirmPayment);
spawnBlock(duration: 500);
await waitFor('validé !', timeout: const Duration(seconds: 1));
await waitFor('validée !', timeout: const Duration(seconds: 1));
await tapKey(keyCloseTransactionScreen, duration: 0);
await waitFor('12.14');
spawnBlock(duration: 500);
@ -64,7 +64,7 @@ Future certifyTest5() async {
await tapKey(keyCertify);
await tapKey(keyConfirm);
spawnBlock(duration: 500);
await waitFor('validé !', timeout: const Duration(seconds: 1));
await waitFor('validée !', timeout: const Duration(seconds: 1));
await tapKey(keyCloseTransactionScreen);
await waitFor('Identité créée');
@ -77,7 +77,7 @@ Future certifyTest5() async {
await enterText(keyEnterIdentityUsername, test5.name);
await tapKey(keyConfirm);
spawnBlock(duration: 500);
await waitFor('validé !', timeout: const Duration(seconds: 1));
await waitFor('validée !', timeout: const Duration(seconds: 1));
await tapKey(keyCloseTransactionScreen);
await waitFor('Identité confirmée');
humanRead(2);
@ -103,7 +103,7 @@ Future certifyTest5() async {
await tapKey(keyCertify);
await tapKey(keyConfirm);
spawnBlock(duration: 500);
await waitFor('validé !', timeout: const Duration(seconds: 1));
await waitFor('validée !', timeout: const Duration(seconds: 1));
await tapKey(keyCloseTransactionScreen);
await waitFor('2');
@ -118,7 +118,7 @@ Future certifyTest5() async {
await tapKey(keyCertify);
await tapKey(keyConfirm);
spawnBlock(duration: 500);
await waitFor('validé !', timeout: const Duration(seconds: 1));
await waitFor('validée !', timeout: const Duration(seconds: 1));
await tapKey(keyCloseTransactionScreen);
await waitFor('Vous devez attendre');

View File

@ -39,7 +39,7 @@ void main() async {
await tapKey(keyRevokeIdty);
await tapKey(keyConfirm);
spawnBlock(duration: 2000);
await waitFor('validé !', timeout: const Duration(seconds: 4));
await waitFor('validée !', timeout: const Duration(seconds: 4));
await tapKey(keyCloseTransactionScreen, duration: 0);
await waitFor('Aucune identité', exactMatch: true);
await sleep();
@ -60,7 +60,7 @@ void main() async {
// await waitForButtonEnabled(keyConfirm);
// await tapKey(keyConfirm, duration: 500);
// await spawnBlock(duration: 2000);
// await waitFor('validé !');
// await waitFor('validée !');
// await tapKey(keyCloseTransactionScreen, duration: 0);
// await sleep(5000);
}, timeout: testTimeout());

View File

@ -26,7 +26,7 @@ void main() async {
await tapKey(keyImportG1v1);
await enterText(keyCesiumId, 'test');
await enterText(keyCesiumPassword, 'test');
await waitFor(cesiumTest1.shortAddress());
await waitFor('DCovzCEnQm9GUWe6mr8u42JR1JAuoj3HbQUGdCkfTzSr');
await waitFor('100.0');
await waitFor('3', exactMatch: true);
@ -43,7 +43,7 @@ void main() async {
await waitForButtonEnabled(keyConfirm);
await tapKey(keyConfirm);
spawnBlock(duration: 2000);
await waitFor('validé !');
await waitFor('validée !');
await tapKey(keyCloseTransactionScreen, duration: 0);
await tapKey(keyOpenWallet(test6.address), duration: 300);

View File

@ -1,3 +1,4 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_test/flutter_test.dart';
@ -66,7 +67,7 @@ Future restoreChest() async {
await enterText(keyPinForm, 'AAAAA', 0);
// Check if string "Accéder à mon coffre" is present in screen
await waitFor('Accéder à mon coffre');
await waitFor('accessMyChest'.tr());
// Go to wallets home
await tapKey(keyGoWalletsHome, duration: 0);
@ -84,7 +85,7 @@ Future restoreChest() async {
await tapKey(keyCopyAddress);
// Check if string "Cette adresse a été copié" is present in screen
await waitFor('Cette adresse a été copié');
await waitFor('thisAddressHasBeenCopiedToClipboard'.tr());
// Pop screen 2 time to go back home
await goBack();
@ -126,7 +127,7 @@ Future onboardingNewChest() async {
final askedWord = mnemonic[askedWordNumber - 1];
await enterText(keyInputWord, askedWord);
await waitFor('Continuer', exactMatch: true);
await waitFor('continue'.tr(), exactMatch: true);
await tapKey(keyGoNext);
await tapKey(keyGoNext);
await tapKey(keyGoNext);
@ -143,13 +144,13 @@ Future onboardingNewChest() async {
await enterText(keyPinForm, 'AAAAA', 0);
// Check if string "Accéder à mon coffre" is present in screen
await waitFor('Accéder à mon coffre');
await waitFor('accessMyChest'.tr());
// Go to wallets home
await tapKey(keyGoWalletsHome, duration: 0);
// Check if string "Mon portefeuille co" is present in screen
await waitFor('Mon portefeuille co');
await waitFor('currentWallet'.tr());
await waitFor('0.0', exactMatch: true);
// await waitFor('Scanner un');
}

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:gecko/globals.dart';
@ -135,7 +136,7 @@ Future<void> waitFor(String text,
Finder finder = exactMatch ? find.text(text) : find.textContaining(text);
log.d('INTEGRATION TEST: Wait for: $text');
final String searchType = reverse ? 'reversed text' : 'text';
final searchType = reverse ? 'reversed text' : 'text';
do {
if (DateTime.now().isAfter(end)) {
@ -258,14 +259,14 @@ Future<WalletData> _addImportAccount(
final address = await sub.importAccount(
mnemonic: mnemonic, derivePath: '//$derivation', password: 'AAAAA');
final myWallet = WalletData(
version: dataVersion,
chest: chest,
address: address,
number: number,
name: name,
derivation: derivation,
imageDefaultPath: '${number % 4}.png');
await walletBox.add(myWallet);
imageDefaultPath: '${number % 4}.png',
isOwned: true);
await walletBox.put(myWallet.address, myWallet);
return myWallet;
}

View File

@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>8.0</string>
<string>11.0</string>
</dict>
</plist>

140
ios/Podfile.lock Normal file
View File

@ -0,0 +1,140 @@
PODS:
- barcode_scan2 (0.0.1):
- Flutter
- MTBBarcodeScanner
- SwiftProtobuf
- connectivity_plus (0.0.1):
- Flutter
- ReachabilitySwift
- Flutter (1.0.0)
- flutter_aes_ecb_pkcs5 (0.0.1):
- Flutter
- flutter_inappwebview (0.0.1):
- Flutter
- flutter_inappwebview/Core (= 0.0.1)
- OrderedSet (~> 5.0)
- flutter_inappwebview/Core (0.0.1):
- Flutter
- OrderedSet (~> 5.0)
- image_cropper (0.0.4):
- Flutter
- TOCropViewController (~> 2.6.1)
- image_picker_ios (0.0.1):
- Flutter
- integration_test (0.0.1):
- Flutter
- MTBBarcodeScanner (5.0.11)
- OrderedSet (5.0.0)
- package_info_plus (0.4.5):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- permission_handler_apple (9.0.4):
- Flutter
- printing (1.0.0):
- Flutter
- ReachabilitySwift (5.0.0)
- Sentry/HybridSDK (7.31.5)
- sentry_flutter (0.0.1):
- Flutter
- FlutterMacOS
- Sentry/HybridSDK (= 7.31.5)
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- SwiftProtobuf (1.21.0)
- TOCropViewController (2.6.1)
- url_launcher_ios (0.0.1):
- Flutter
- webview_flutter_wkwebview (0.0.1):
- Flutter
DEPENDENCIES:
- barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- Flutter (from `Flutter`)
- flutter_aes_ecb_pkcs5 (from `.symlinks/plugins/flutter_aes_ecb_pkcs5/ios`)
- flutter_inappwebview (from `.symlinks/plugins/flutter_inappwebview/ios`)
- image_cropper (from `.symlinks/plugins/image_cropper/ios`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- integration_test (from `.symlinks/plugins/integration_test/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- printing (from `.symlinks/plugins/printing/ios`)
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
SPEC REPOS:
trunk:
- MTBBarcodeScanner
- OrderedSet
- ReachabilitySwift
- Sentry
- SwiftProtobuf
- TOCropViewController
EXTERNAL SOURCES:
barcode_scan2:
:path: ".symlinks/plugins/barcode_scan2/ios"
connectivity_plus:
:path: ".symlinks/plugins/connectivity_plus/ios"
Flutter:
:path: Flutter
flutter_aes_ecb_pkcs5:
:path: ".symlinks/plugins/flutter_aes_ecb_pkcs5/ios"
flutter_inappwebview:
:path: ".symlinks/plugins/flutter_inappwebview/ios"
image_cropper:
:path: ".symlinks/plugins/image_cropper/ios"
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
integration_test:
:path: ".symlinks/plugins/integration_test/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/ios"
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
printing:
:path: ".symlinks/plugins/printing/ios"
sentry_flutter:
:path: ".symlinks/plugins/sentry_flutter/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
webview_flutter_wkwebview:
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
SPEC CHECKSUMS:
barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0
connectivity_plus: 413a8857dd5d9f1c399a39130850d02fe0feaf7e
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_aes_ecb_pkcs5: fb682a7bb13f29cfbb33f88f7e1ed2211eacf5db
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721
image_cropper: 60c2789d1f1a78c873235d4319ca0c34a69f2d98
image_picker_ios: b786a5dcf033a8336a657191401bfdf12017dabb
integration_test: a1e7d09bd98eca2fc37aefd79d4f41ad37bdbbe5
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
printing: eafa00acb682c0ca029d4d98d0798f55a1e27102
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
Sentry: 4c9babff9034785067c896fd580b1f7de44da020
sentry_flutter: b10ae7a5ddcbc7f04648eeb2672b5747230172f1
shared_preferences_foundation: 297b3ebca31b34ec92be11acd7fb0ba932c822ca
SwiftProtobuf: afced68785854575756db965e9da52bbf3dc45e7
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
url_launcher_ios: ae1517e5e344f5544fb090b079e11f399dfbe4d2
webview_flutter_wkwebview: b7e70ef1ddded7e69c796c7390ee74180182971f
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
COCOAPODS: 1.11.3

View File

@ -13,6 +13,7 @@
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
FE317B9470ED5615CA3CB087 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B6BDF717F540F951CBCF3B0 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -29,12 +30,15 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0B6BDF717F540F951CBCF3B0 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
4C6E3D6B3826D9CF6FE74C71 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9715B8CB8C4BB6B1549A4B43 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -42,6 +46,7 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B7B5EAF367303889DDE6246F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -49,6 +54,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FE317B9470ED5615CA3CB087 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -72,6 +78,8 @@
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
F45015BCA13948A291A8C8E9 /* Pods */,
ADA8E12261C2D5AFC64EEABC /* Frameworks */,
);
sourceTree = "<group>";
};
@ -98,6 +106,25 @@
path = Runner;
sourceTree = "<group>";
};
ADA8E12261C2D5AFC64EEABC /* Frameworks */ = {
isa = PBXGroup;
children = (
0B6BDF717F540F951CBCF3B0 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
F45015BCA13948A291A8C8E9 /* Pods */ = {
isa = PBXGroup;
children = (
B7B5EAF367303889DDE6246F /* Pods-Runner.debug.xcconfig */,
9715B8CB8C4BB6B1549A4B43 /* Pods-Runner.release.xcconfig */,
4C6E3D6B3826D9CF6FE74C71 /* Pods-Runner.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -105,12 +132,14 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
BF832FA7B2681D407FBCCD35 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
C7115DDDD9D931A7B2E38D5D /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -127,7 +156,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1020;
LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@ -197,6 +226,45 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
BF832FA7B2681D407FBCCD35 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
C7115DDDD9D931A7B2E38D5D /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -272,7 +340,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@ -295,7 +363,10 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
@ -355,7 +426,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@ -404,7 +475,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@ -428,7 +499,10 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
@ -456,7 +530,10 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",

View File

@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
location = "self:">
</FileRef>
</Workspace>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -4,4 +4,7 @@
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@ -1,122 +1,122 @@
{
"images" : [
"images": [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
"filename": "Icon-App-20x20@2x.png",
"idiom": "iphone",
"scale": "2x",
"size": "20x20"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
"filename": "Icon-App-20x20@3x.png",
"idiom": "iphone",
"scale": "3x",
"size": "20x20"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
"filename": "Icon-App-29x29@1x.png",
"idiom": "iphone",
"scale": "1x",
"size": "29x29"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
"filename": "Icon-App-29x29@2x.png",
"idiom": "iphone",
"scale": "2x",
"size": "29x29"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
"filename": "Icon-App-29x29@3x.png",
"idiom": "iphone",
"scale": "3x",
"size": "29x29"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
"filename": "Icon-App-40x40@2x.png",
"idiom": "iphone",
"scale": "2x",
"size": "40x40"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
"filename": "Icon-App-40x40@3x.png",
"idiom": "iphone",
"scale": "3x",
"size": "40x40"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
"filename": "Icon-App-60x60@2x.png",
"idiom": "iphone",
"scale": "2x",
"size": "60x60"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
"filename": "Icon-App-60x60@3x.png",
"idiom": "iphone",
"scale": "3x",
"size": "60x60"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
"filename": "Icon-App-20x20@1x.png",
"idiom": "ipad",
"scale": "1x",
"size": "20x20"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
"filename": "Icon-App-20x20@2x.png",
"idiom": "ipad",
"scale": "2x",
"size": "20x20"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
"filename": "Icon-App-29x29@1x.png",
"idiom": "ipad",
"scale": "1x",
"size": "29x29"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
"filename": "Icon-App-29x29@2x.png",
"idiom": "ipad",
"scale": "2x",
"size": "29x29"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
"filename": "Icon-App-40x40@1x.png",
"idiom": "ipad",
"scale": "1x",
"size": "40x40"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
"filename": "Icon-App-40x40@2x.png",
"idiom": "ipad",
"scale": "2x",
"size": "40x40"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
"filename": "Icon-App-76x76@1x.png",
"idiom": "ipad",
"scale": "1x",
"size": "76x76"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
"filename": "Icon-App-76x76@2x.png",
"idiom": "ipad",
"scale": "2x",
"size": "76x76"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
"filename": "Icon-App-83.5x83.5@2x.png",
"idiom": "ipad",
"scale": "2x",
"size": "83.5x83.5"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
"filename": "Icon-App-1024x1024@1x.png",
"idiom": "ios-marketing",
"scale": "1x",
"size": "1024x1024"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"info": {
"author": "icons_launcher",
"version": 1
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -47,5 +47,7 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
</dict>
</plist>

View File

@ -1,4 +1,5 @@
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/g1_wallets_list.dart';
@ -7,7 +8,7 @@ import 'package:hive_flutter/hive_flutter.dart';
import 'package:logger/logger.dart';
// Version of box data
const int dataVersion = 4;
const int dataVersion = 6;
late String appVersion;
const int pinLength = 5;
@ -50,3 +51,24 @@ const debugPin = true;
String indexerEndpoint = '';
late double balanceRatio;
late int udValue;
// Indexer
late DateTime startBlockchainTime;
bool startBlockchainInitialized = false;
late int currentUdIndex;
final Map<int, String> monthsInYear = {
1: "month1".tr(),
2: "month2".tr(),
3: "month3".tr(),
4: "month4".tr(),
5: "month5".tr(),
6: "month6".tr(),
7: "month7".tr(),
8: "month8".tr(),
9: "month9".tr(),
10: "month10".tr(),
11: "month11".tr(),
12: "month12".tr()
};

View File

@ -18,10 +18,11 @@ import 'dart:io';
import 'package:flutter/services.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/cesium_plus.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/providers/chest_provider.dart';
import 'package:gecko/models/g1_wallets_list.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/cesium_plus.dart';
import 'package:gecko/providers/chest_provider.dart';
import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/providers/settings_provider.dart';
@ -30,7 +31,6 @@ import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/providers/home.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/search.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/screens/home.dart';
import 'package:flutter/material.dart';
@ -57,13 +57,12 @@ Future<void> main() async {
HomeProvider homeProvider = HomeProvider();
// DuniterIndexer _duniterIndexer = DuniterIndexer();
await initHiveForFlutter();
await homeProvider.initHive();
appVersion = await homeProvider.getAppVersion();
configBox = await Hive.openBox("configBox");
// Reset GraphQL cache
// final cache = HiveStore();
// cache.reset();
appVersion = await homeProvider.getAppVersion();
// Configure Hive and open boxes
Hive.registerAdapter(WalletDataAdapter());
@ -71,19 +70,11 @@ Future<void> main() async {
Hive.registerAdapter(G1WalletsListAdapter());
Hive.registerAdapter(IdAdapter());
walletBox = await Hive.openBox<WalletData>("walletBox");
chestBox = await Hive.openBox<ChestData>("chestBox");
configBox = await Hive.openBox("configBox");
await Hive.deleteBoxFromDisk('g1WalletsBox');
g1WalletsBox = await Hive.openBox<G1WalletsList>("g1WalletsBox");
contactsBox = await Hive.openBox<G1WalletsList>("contactsBox");
await homeProvider.getValidEndpoints();
// await configBox.delete('isCacheChecked');
if (configBox.get('isCacheChecked') == null) {
configBox.put('isCacheChecked', false);
}
// log.d(await configBox.get('endpoint'));
// Reset GraphQL cache
// final cache = HiveStore();
// cache.reset();
HttpOverrides.global = MyHttpOverrides();
@ -98,31 +89,42 @@ Future<void> main() async {
// // ]);
// Catcher(rootWidget: Gecko(endPointGVA, _store), debugConfig: debugOptions);
await SentryFlutter.init(
(options) {
options.dsn =
'https://c09587b46eaa42e8b9fda28d838ed180@o496840.ingest.sentry.io/5572110';
},
appRunner: () => runApp(
EasyLocalization(
supportedLocales: const [Locale('en'), Locale('fr'), Locale('es')],
path: 'assets/translations',
fallbackLocale: const Locale('en'),
child: const Gecko(),
),
),
);
await SentryFlutter.init((options) {
options.dsn =
'https://c09587b46eaa42e8b9fda28d838ed180@o496840.ingest.sentry.io/5572110';
},
appRunner: () => SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp]).then((_) {
runApp(EasyLocalization(
supportedLocales: const [
Locale('en'),
Locale('fr'),
Locale('es'),
Locale('it')
],
path: 'assets/translations',
fallbackLocale: const Locale('en'),
child: const Gecko(),
));
}));
} else {
log.i('Debug mode enabled: No sentry alerte');
log.i('Debug mode enabled: No sentry alert');
runApp(
EasyLocalization(
supportedLocales: const [Locale('en'), Locale('fr'), Locale('es')],
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
.then((_) {
runApp(EasyLocalization(
// test, force locale :: startLocale: Locale.fromSubtags(languageCode: 'it'),
supportedLocales: const [
Locale('en'),
Locale('fr'),
Locale('es'),
Locale('it')
],
path: 'assets/translations',
fallbackLocale: const Locale('en'),
child: const Gecko(),
),
);
));
});
}
}
@ -131,8 +133,6 @@ class Gecko extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
// To configure multi_endpoints GraphQLProvider: https://stackoverflow.com/q/70656513/8301867
return MultiProvider(
@ -172,8 +172,8 @@ class Gecko extends StatelessWidget {
),
primaryColor: const Color(0xffFFD58D),
textTheme: const TextTheme(
bodyText1: TextStyle(fontSize: 16),
bodyText2: TextStyle(fontSize: 18),
bodyLarge: TextStyle(fontSize: 16),
bodyMedium: TextStyle(fontSize: 18),
).apply(
bodyColor: const Color(0xFF000000),
),

View File

@ -1,7 +1,5 @@
import 'dart:io';
import 'package:hive_flutter/hive_flutter.dart';
part 'chest_data.g.dart';
@HiveType(typeId: 1)

View File

@ -56,5 +56,43 @@ query ($address: String!, $number: Int!, $cursor: String) {
}
''';
// To parse indexer date format
// log.d(DateTime.parse("2022-06-13T16:51:24.001+00:00").toString());
const String getCertsReceived = r'''
query ($address: String!) {
certification(where: {receiver: {pubkey: {_eq: $address}}}) {
issuer {
pubkey
name
}
created_at
}
}
''';
const String getCertsSent = r'''
query ($address: String!) {
certification(where: {issuer: {pubkey: {_eq: $address}}}) {
receiver {
pubkey
name
}
created_at
}
}
''';
const String isIdtyExistQ = r'''
query ($name: String!) {
identity(where: {name: {_eq: $name}}) {
name
}
}
''';
const String getBlockchainStartQ = r'''
query {
block(limit: 1) {
created_at
number
}
}
''';

View File

@ -1,23 +0,0 @@
import 'package:flutter/material.dart';
class StatefulWrapper extends StatefulWidget {
final Function onInit;
final Widget child;
const StatefulWrapper({Key? key, required this.onInit, required this.child})
: super(key: key);
@override
StatefulWrapperState createState() => StatefulWrapperState();
}
class StatefulWrapperState extends State<StatefulWrapper> {
@override
void initState() {
widget.onInit();
super.initState();
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}

View File

@ -4,38 +4,42 @@ part 'wallet_data.g.dart';
@HiveType(typeId: 0)
class WalletData extends HiveObject {
@HiveField(0)
int? version;
String address;
@HiveField(1)
int? chest;
@HiveField(2)
String? address;
@HiveField(3)
int? number;
@HiveField(4)
@HiveField(3)
String? name;
@HiveField(5)
@HiveField(4)
int? derivation;
@HiveField(6)
@HiveField(5)
String? imageDefaultPath;
@HiveField(7)
@HiveField(6)
String? imageCustomPath;
@HiveField(7)
bool isOwned;
@HiveField(8)
bool isMember;
WalletData(
{this.version,
{required this.address,
this.chest,
this.address,
this.number,
this.name,
this.derivation,
this.imageDefaultPath,
this.imageCustomPath});
this.imageCustomPath,
this.isOwned = false,
this.isMember = false});
// representation of WalletData when debugging
@override

View File

@ -17,37 +17,40 @@ class WalletDataAdapter extends TypeAdapter<WalletData> {
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return WalletData(
version: fields[0] as int?,
address: fields[0] as String,
chest: fields[1] as int?,
address: fields[2] as String?,
number: fields[3] as int?,
name: fields[4] as String?,
derivation: fields[5] as int?,
imageDefaultPath: fields[6] as String?,
imageCustomPath: fields[7] as String?,
number: fields[2] as int?,
name: fields[3] as String?,
derivation: fields[4] as int?,
imageDefaultPath: fields[5] as String?,
imageCustomPath: fields[6] as String?,
isOwned: fields[7] as bool,
isMember: fields[8] as bool,
);
}
@override
void write(BinaryWriter writer, WalletData obj) {
writer
..writeByte(8)
..writeByte(9)
..writeByte(0)
..write(obj.version)
..write(obj.address)
..writeByte(1)
..write(obj.chest)
..writeByte(2)
..write(obj.address)
..writeByte(3)
..write(obj.number)
..writeByte(4)
..writeByte(3)
..write(obj.name)
..writeByte(5)
..writeByte(4)
..write(obj.derivation)
..writeByte(6)
..writeByte(5)
..write(obj.imageDefaultPath)
..writeByte(6)
..write(obj.imageCustomPath)
..writeByte(7)
..write(obj.imageCustomPath);
..write(obj.isOwned)
..writeByte(8)
..write(obj.isMember);
}
@override

View File

@ -61,6 +61,9 @@ const keyCloseTransactionScreen = Key('keyCloseTransactionScreen');
const keyListTransactions = Key('keyListTransactions');
const keyActivityScreen = Key('keyActivityScreen');
// Certification view
const keyCertsReceived = Key('keyCertsReceived');
// Unlock wallet
const keyUnlockWallet = Key('keyUnlockWallet');
const keyPinForm = Key('keyPinForm');

View File

@ -8,8 +8,6 @@ import 'package:path_provider/path_provider.dart';
class CesiumPlusProvider with ChangeNotifier {
TextEditingController cesiumName = TextEditingController();
Image defaultAvatar(double size) =>
Image.asset(('assets/icon_user.png'), height: size);
CancelToken avatarCancelToken = CancelToken();
@ -156,3 +154,6 @@ class CesiumPlusProvider with ChangeNotifier {
return finalAvatar;
}
}
Image defaultAvatar(double size) =>
Image.asset(('assets/icon_user.png'), height: size);

View File

@ -16,11 +16,11 @@ class ChestProvider with ChangeNotifier {
Future deleteChest(context, ChestData chest) async {
final bool? answer = await (_confirmDeletingChest(context, chest.name));
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
if (answer ?? false) {
await sub.deleteAccounts(getChestWallets(chest));
await chestBox.delete(chest.key);
MyWalletsProvider myWalletProvider =
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
myWalletProvider.pinCode = '';
@ -45,7 +45,7 @@ class ChestProvider with ChangeNotifier {
log.d(chest.key);
walletBox.toMap().forEach((key, WalletData value) {
if (value.chest == chest.key) {
toDelete.add(value.address!);
toDelete.add(value.address);
}
});
return toDelete;

View File

@ -5,28 +5,18 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/g1_wallets_list.dart';
import 'package:gecko/models/queries_indexer.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/cesium_plus.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/screens/wallet_view.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:provider/provider.dart';
import 'package:truncate/truncate.dart';
class DuniterIndexer with ChangeNotifier {
Map<String, String?> walletNameIndexer = {};
String? fetchMoreCursor;
Map? pageInfo;
int nPage = 1;
int nRepositories = 20;
List? transBC;
List listIndexerEndpoints = [];
bool isLoadingIndexer = false;
Map<String, String> idtyStatusCache = {};
void reload() {
notifyListeners();
@ -41,7 +31,7 @@ class DuniterIndexer with ChangeNotifier {
final request = await client.postUrl(Uri.parse('$endpoint/v1/graphql'));
final response = await request.close();
if (response.statusCode != 200) {
log.d('INDEXER IS OFFILINE');
log.d('INDEXER IS OFFLINE');
indexerEndpoint = '';
isLoadingIndexer = false;
notifyListeners();
@ -57,7 +47,7 @@ class DuniterIndexer with ChangeNotifier {
return true;
}
} catch (e) {
log.d('INDEXER IS OFFILINE');
log.d('INDEXER IS OFFLINE');
indexerEndpoint = '';
isLoadingIndexer = false;
notifyListeners();
@ -93,7 +83,6 @@ class DuniterIndexer with ChangeNotifier {
if (configBox.containsKey('customIndexer')) {
return configBox.get('customIndexer');
// listIndexerEndpoints.insert(0, configBox.get('customIndexer'));
}
if (configBox.containsKey('indexerEndpoint')) {
@ -155,210 +144,8 @@ class DuniterIndexer with ChangeNotifier {
return indexerEndpoint;
}
Widget getNameByAddress(BuildContext context, String address,
[WalletData? wallet,
double size = 20,
bool canEdit = false,
Color color = Colors.black,
FontWeight fontWeight = FontWeight.w400,
FontStyle fontStyle = FontStyle.italic]) {
WalletOptionsProvider walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
if (indexerEndpoint == '') {
if (wallet == null) {
return const SizedBox();
} else {
if (canEdit) {
return walletOptions.walletName(context, wallet, size, color);
} else {
return walletOptions.walletNameController(context, wallet, size);
}
}
}
final httpLink = HttpLink(
'$indexerEndpoint/v1/graphql',
);
final client = ValueNotifier(
GraphQLClient(
cache: GraphQLCache(store: HiveStore()),
link: httpLink,
),
);
return GraphQLProvider(
client: client,
child: Query(
options: QueryOptions(
document: gql(
getNameByAddressQ), // this is the query string you just created
variables: {
'address': address,
},
// pollInterval: const Duration(seconds: 10),
),
builder: (QueryResult result,
{VoidCallback? refetch, FetchMore? fetchMore}) {
if (result.hasException) {
return Text(result.exception.toString());
}
if (result.isLoading) {
return const Text('Loading');
}
walletNameIndexer[address] =
result.data?['account_by_pk']?['identity']?['name'];
g1WalletsBox.put(
address,
G1WalletsList(
address: address, username: walletNameIndexer[address]));
// log.d(g1WalletsBox.toMap().values.first.username);
if (walletNameIndexer[address] == null) {
if (wallet == null) {
return const SizedBox();
} else {
if (canEdit) {
return walletOptions.walletName(context, wallet, size, color);
} else {
return walletOptions.walletNameController(
context, wallet, size);
}
}
}
return Text(
color == Colors.grey[700]!
? '(${walletNameIndexer[address]!})'
: truncate(walletNameIndexer[address]!, 20),
style: TextStyle(
fontSize: size,
color: color,
fontWeight: fontWeight,
fontStyle: fontStyle,
),
);
}),
);
}
Widget searchIdentity(BuildContext context, String name) {
// WalletOptionsProvider _walletOptions =
// Provider.of<WalletOptionsProvider>(context, listen: false);
CesiumPlusProvider cesiumPlusProvider =
Provider.of<CesiumPlusProvider>(context, listen: false);
WalletsProfilesProvider walletsProfiles =
Provider.of<WalletsProfilesProvider>(context, listen: false);
if (indexerEndpoint == '') {
return const Text('Aucun résultat');
}
log.d(indexerEndpoint);
final httpLink = HttpLink(
'$indexerEndpoint/v1/graphql',
);
final client = ValueNotifier(
GraphQLClient(
cache: GraphQLCache(
store: HiveStore()), // GraphQLCache(store: HiveStore())
link: httpLink,
),
);
return GraphQLProvider(
client: client,
child: Query(
options: QueryOptions(
document: gql(
searchAddressByNameQ), // this is the query string you just created
variables: {
'name': name,
},
// pollInterval: const Duration(seconds: 10),
),
builder: (QueryResult result,
{VoidCallback? refetch, FetchMore? fetchMore}) {
if (result.hasException) {
return Text(result.exception.toString());
}
if (result.isLoading) {
return Text('loading'.tr());
}
final List identities = result.data?['search_identity'] ?? [];
if (identities.isEmpty) {
return Text('noResult'.tr());
}
double avatarSize = 55;
return Expanded(
child: ListView(children: <Widget>[
for (Map profile in identities)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: ListTile(
key: keySearchResult(profile['pubkey']),
horizontalTitleGap: 40,
contentPadding: const EdgeInsets.all(5),
leading: cesiumPlusProvider.defaultAvatar(avatarSize),
title: Row(children: <Widget>[
Text(getShortPubkey(profile['pubkey']),
style: const TextStyle(
fontSize: 18,
fontFamily: 'Monospace',
fontWeight: FontWeight.w500),
textAlign: TextAlign.center),
]),
trailing: SizedBox(
width: 110,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
balance(context, profile['pubkey'], 16),
]),
]),
),
subtitle: Row(children: <Widget>[
Text(profile['name'] ?? '',
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.w500),
textAlign: TextAlign.center),
]),
dense: false,
isThreeLine: false,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
walletsProfiles.address = profile['pubkey'];
return WalletViewScreen(
address: profile['pubkey'],
username: g1WalletsBox
.get(profile['pubkey'])
?.id
?.username,
avatar:
g1WalletsBox.get(profile['pubkey'])?.avatar,
);
}),
);
}),
),
]),
);
}),
);
}
List parseHistory(blockchainTX, pubkey) {
var transBC = [];
List transBC = [];
int i = 0;
for (final trans in blockchainTX) {
@ -369,8 +156,8 @@ class DuniterIndexer with ChangeNotifier {
transBC.add(i);
transBC[i] = [];
transBC[i].add(DateTime.parse(transaction['created_at']));
final int amountBrut = transaction['amount'];
final double amount = removeDecimalZero(amountBrut / 100);
final amountBrut = transaction['amount'];
final amount = removeDecimalZero(amountBrut / 100);
if (direction == "RECEIVED") {
transBC[i].add(transaction['issuer_pubkey']);
transBC[i].add(transaction['issuer']['identity']?['name'] ?? '');
@ -380,32 +167,21 @@ class DuniterIndexer with ChangeNotifier {
}
transBC[i].add(amount);
transBC[i].add(direction);
// transBC[i].add(''); //transaction comment
i++;
}
return transBC;
}
FetchMoreOptions? checkQueryResult(result, opts, pubkey) {
FetchMoreOptions? mergeQueryResult(result, opts, pubkey, nRepositories) {
final List<dynamic>? blockchainTX =
(result.data['transaction_connection']['edges'] as List<dynamic>?);
// final List<dynamic> mempoolTX =
// (result.data['txsHistoryMp']['receiving'] as List<dynamic>);
pageInfo = result.data['transaction_connection']['pageInfo'];
fetchMoreCursor = pageInfo!['endCursor'];
if (fetchMoreCursor == null) nPage = 1;
log.d(fetchMoreCursor);
if (nPage == 1) {
nRepositories = 40;
} else if (nPage == 2) {
nRepositories = 100;
}
// nRepositories = 10;
nPage++;
final hasNextPage = pageInfo!['hasNextPage'];
final hasPreviousPage = pageInfo!['hasPreviousPage'];
log.d('endCursor: $fetchMoreCursor $hasNextPage $hasPreviousPage');
if (fetchMoreCursor != null) {
opts = FetchMoreOptions(
@ -418,18 +194,12 @@ class DuniterIndexer with ChangeNotifier {
as List<dynamic>
];
log.d('repos: $previousResultData');
log.d('repos: $fetchMoreResultData');
log.d('repos: $repos');
fetchMoreResultData['transaction_connection']['edges'] = repos;
return fetchMoreResultData;
},
);
}
log.d(
"###### DEBUG H Parse blockchainTX list. Cursor: $fetchMoreCursor ######");
if (fetchMoreCursor != null) {
transBC = parseHistory(blockchainTX, pubkey);
} else {
@ -443,7 +213,124 @@ class DuniterIndexer with ChangeNotifier {
String result = n.toStringAsFixed(n.truncateToDouble() == n ? 0 : 2);
return double.parse(result);
}
// checkHistoryResult(
// QueryResult<Object?> result, FetchMoreOptions options, String address) {}
}
//// Manuals queries
Future<bool> isIdtyExist(String name) async {
final variables = <String, dynamic>{
'name': name,
};
final result = await _execQuery(isIdtyExistQ, variables);
return result.data!['identity']?.isEmpty ?? false ? false : true;
}
Future<DateTime> getBlockStart() async {
final result = await _execQuery(getBlockchainStartQ, {});
if (!result.hasException) {
startBlockchainTime =
DateTime.parse(result.data!['block'][0]['created_at']);
startBlockchainInitialized = true;
return startBlockchainTime;
}
return DateTime(0, 0, 0, 0, 0);
}
Future<QueryResult> _execQuery(
String query, Map<String, dynamic> variables) async {
final httpLink = HttpLink(
'$indexerEndpoint/v1/graphql',
);
final GraphQLClient client = GraphQLClient(
cache: GraphQLCache(),
link: httpLink,
);
final QueryOptions options =
QueryOptions(document: gql(query), variables: variables);
return await client.query(options);
}
Map computeHistoryView(repository) {
bool isTody = false;
bool isYesterday = false;
bool isThisWeek = false;
bool isMigrationTime = false;
String? dateDelimiter;
DateTime now = DateTime.now();
final bool isUdUnit = configBox.get('isUdUnit') ?? false;
late double amount;
late String finalAmount;
DateTime date = repository[0];
String dateForm;
bool isDelimiter = true;
if ({4, 10, 11, 12}.contains(date.month)) {
dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, 3)}";
} else if ({1, 2, 7, 9}.contains(date.month)) {
dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, 4)}";
} else {
dateForm = "${date.day} ${monthsInYear[date.month]}";
}
final transactionDate = DateTime(date.year, date.month, date.day);
final todayDate = DateTime(now.year, now.month, now.day);
final yesterdayDate = DateTime(now.year, now.month, now.day - 1);
if (transactionDate == todayDate && !isTody) {
dateDelimiter = "today".tr();
isTody = true;
} else if (transactionDate == yesterdayDate && !isYesterday) {
dateDelimiter = "yesterday".tr();
isYesterday = true;
} else if (weekNumber(date) == weekNumber(now) &&
date.year == now.year &&
transactionDate != yesterdayDate &&
transactionDate != todayDate &&
!isThisWeek) {
dateDelimiter = "thisWeek".tr();
isThisWeek = true;
} else if (dateDelimiter != "${monthsInYear[date.month]} ${date.year}" &&
transactionDate != todayDate &&
transactionDate != yesterdayDate &&
!(weekNumber(date) == weekNumber(now) && date.year == now.year)) {
if (date.year == now.year) {
dateDelimiter = monthsInYear[date.month];
} else {
dateDelimiter = "${monthsInYear[date.month]} ${date.year}";
}
} else {
isDelimiter = false;
}
amount = repository[4] == 'RECEIVED' ? repository[3] : repository[3] * -1;
if (isUdUnit) {
amount = round(amount / balanceRatio);
finalAmount = 'ud'.tr(args: ['$amount ']);
} else {
finalAmount = '$amount $currencyName';
}
if (startBlockchainInitialized && date.compareTo(startBlockchainTime) < 0) {
isMigrationTime = true;
} else {
isMigrationTime = false;
}
return {
'finalAmount': finalAmount,
'isMigrationTime': isMigrationTime,
'dateDelimiter': dateDelimiter ?? '',
'isDelimiter': isDelimiter,
'dateForm': dateForm,
};
}
int weekNumber(DateTime date) {
int dayOfYear = int.parse(DateFormat("D").format(date));
return ((dayOfYear - date.weekday + 10) / 7).floor();
}

View File

@ -1,6 +1,7 @@
import 'dart:math';
import 'package:durt/durt.dart' as durt;
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
@ -88,8 +89,7 @@ class GenerateWalletsProvider with ChangeNotifier {
log.i("Is $expectedWord equal to input $normInputWord ?");
if (expectedWord == normInputWord ||
inputWord == 'triche' ||
inputWord == '3.14') {
(kDebugMode && inputWord == 'triche')) {
log.d('Word is OK');
isAskedWordValid = true;
askedWordColor = Colors.green[600];
@ -249,7 +249,7 @@ class GenerateWalletsProvider with ChangeNotifier {
}
Future<List<String>> generateWordList(BuildContext context) async {
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
generatedMnemonic = await sub.generateMnemonic(lang: appLang);
List<String> wordsList = [];
@ -369,7 +369,7 @@ class GenerateWalletsProvider with ChangeNotifier {
}
Future<bool> scanDerivations(BuildContext context) async {
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final currentChestNumber = configBox.get('currentChest');
bool isAlive = false;
scanedValidWalletNumber = 0;
@ -414,14 +414,14 @@ class GenerateWalletsProvider with ChangeNotifier {
password: pin.text);
WalletData myWallet = WalletData(
version: dataVersion,
chest: currentChestNumber,
address: addressData.address!,
number: scanedValidWalletNumber,
name: walletName,
derivation: derivationNbr,
imageDefaultPath: '${scanedValidWalletNumber % 4}.png');
await walletBox.add(myWallet);
imageDefaultPath: '${scanedValidWalletNumber % 4}.png',
isOwned: true);
await walletBox.put(myWallet.address, myWallet);
scanedValidWalletNumber = scanedValidWalletNumber + 1;
}
scanedWalletNumber = scanedWalletNumber + 1;
@ -445,6 +445,8 @@ class GenerateWalletsProvider with ChangeNotifier {
onTimeout: () => {},
);
log.d(balance);
log.d(
"${addressData.address!}: ${balance['transferableBalance']} $currencyName");
if (balance['transferableBalance'] != 0) {
@ -452,14 +454,14 @@ class GenerateWalletsProvider with ChangeNotifier {
await sub.importAccount(mnemonic: generatedMnemonic!, password: pin.text);
WalletData myWallet = WalletData(
version: dataVersion,
chest: currentChestNumber,
address: addressData.address!,
number: 0,
name: walletName,
derivation: -1,
imageDefaultPath: '0.png');
await walletBox.add(myWallet);
imageDefaultPath: '0.png',
isOwned: true);
await walletBox.put(myWallet.address, myWallet);
return true;
} else {
return false;

View File

@ -8,17 +8,11 @@ import 'dart:math';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:async';
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/substrate_sdk.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:gecko/screens/myWallets/wallets_home.dart';
import 'package:gecko/screens/search.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:flutter/foundation.dart' show kDebugMode, kIsWeb;
import 'package:path_provider/path_provider.dart' as pp;
@ -33,6 +27,7 @@ class HomeProvider with ChangeNotifier {
Widget appBarTitle = Text('Ğecko', style: TextStyle(color: Colors.grey[850]));
String homeMessage = "loading".tr();
String defaultMessage = "noLizard".tr();
bool isWalletBoxInit = false;
Future<void> initHive() async {
late Directory hivePath;
@ -67,9 +62,11 @@ class HomeProvider with ChangeNotifier {
Future changeCurrencyUnit(BuildContext context) async {
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
final bool isUdUnit = configBox.get('isUdUnit') ?? false;
await configBox.put('isUdUnit', !isUdUnit);
balanceCache = {};
walletOptions.balanceCache = {};
sub.getBalanceRatio();
notifyListeners();
}
@ -122,114 +119,11 @@ class HomeProvider with ChangeNotifier {
return list[i];
}
void handleSearchStart() {
isSearching = true;
notifyListeners();
}
// void playSound(String customSound, double volume) async {
// await player.play('$customSound.wav',
// volume: volume, mode: PlayerMode.LOW_LATENCY, stayAwake: false);
// }
Widget bottomAppBar(BuildContext context) {
MyWalletsProvider myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
WalletsProfilesProvider historyProvider =
Provider.of<WalletsProfilesProvider>(context, listen: false);
final size = MediaQuery.of(context).size;
const bool showBottomBar = true;
return Visibility(
visible: showBottomBar,
child: Container(
color: yellowC,
width: size.width,
height: 80,
child:
// Stack(
// children: [
// // CustomPaint(
// // size: Size(size.width, 110),
// // painter: CustomRoundedButton(),
// // ),
Row(mainAxisAlignment: MainAxisAlignment.start, children: [
// SizedBox(width: 0),
const Spacer(),
const SizedBox(width: 11),
IconButton(
key: keyAppBarSearch,
iconSize: 40,
icon: const Image(image: AssetImage('assets/loupe-noire.png')),
onPressed: () {
Navigator.popUntil(
context,
ModalRoute.withName('/'),
);
Navigator.push(
context,
MaterialPageRoute(builder: (homeContext) {
return const SearchScreen();
}),
);
},
),
const SizedBox(width: 22),
const Spacer(),
IconButton(
key: keyAppBarQrcode,
iconSize: 70,
icon: const Image(image: AssetImage('assets/qrcode-scan.png')),
onPressed: () async {
Navigator.popUntil(
context,
ModalRoute.withName('/'),
);
historyProvider.scan(homeContext);
},
),
const Spacer(),
const SizedBox(width: 15),
IconButton(
key: keyAppBarChest,
iconSize: 60,
icon: const Image(image: AssetImage('assets/wallet.png')),
onPressed: () async {
WalletData? defaultWallet = myWalletProvider.getDefaultWallet();
String? pin;
if (myWalletProvider.pinCode == '') {
pin = await Navigator.push(
context,
MaterialPageRoute(
builder: (homeContext) {
return UnlockingWallet(wallet: defaultWallet);
},
),
);
}
if (pin != null || myWalletProvider.pinCode != '') {
Navigator.popUntil(
context,
ModalRoute.withName('/'),
);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const WalletsHome();
}),
);
}
},
),
const Spacer(),
]),
),
);
}
void reload() {
notifyListeners();
}

View File

@ -4,7 +4,7 @@ import 'dart:async';
import 'package:gecko/globals.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/widgets/commons/common_elements.dart';
import 'package:provider/provider.dart';
class MyWalletsProvider with ChangeNotifier {
@ -15,6 +15,8 @@ class MyWalletsProvider with ChangeNotifier {
bool isNewDerivationLoading = false;
String lastFlyBy = '';
String dragAddress = '';
bool isPinValid = false;
bool isPinLoading = true;
int getCurrentChest() {
if (configBox.get('currentChest') == null) {
@ -26,7 +28,7 @@ class MyWalletsProvider with ChangeNotifier {
bool checkIfWalletExist() {
if (chestBox.isEmpty) {
log.i('No wallets detected');
// log.i('No wallets detected');
return false;
} else {
return true;
@ -46,7 +48,7 @@ class MyWalletsProvider with ChangeNotifier {
}
WalletData? getWalletDataById(List<int?> id) {
if (id.isEmpty) return WalletData();
if (id.isEmpty) return WalletData(address: '', isOwned: true);
int? chest = id[0];
int? nbr = id[1];
WalletData? targetedWallet;
@ -76,18 +78,18 @@ class MyWalletsProvider with ChangeNotifier {
WalletData getDefaultWallet([int? chest]) {
if (chestBox.isEmpty) {
return WalletData(chest: 0, number: 0);
return WalletData(address: '', chest: 0, number: 0, isOwned: true);
} else {
chest ??= getCurrentChest();
int? defaultWalletNumber = chestBox.get(chest)!.defaultWallet;
return getWalletDataById([chest, defaultWalletNumber]) ??
WalletData(chest: chest, number: 0);
WalletData(address: '', chest: chest, number: 0, isOwned: true);
}
}
Future<int> deleteAllWallet(context) async {
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
MyWalletsProvider myWalletProvider =
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
try {
log.w('DELETE ALL WALLETS ?');
@ -124,30 +126,30 @@ class MyWalletsProvider with ChangeNotifier {
int? chest = getCurrentChest();
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
WalletData defaultWallet = getDefaultWallet();
final address = await sub.derive(
context, defaultWallet.address!, newDerivationNbr, pinCode);
context, defaultWallet.address, newDerivationNbr, pinCode);
WalletData newWallet = WalletData(
version: dataVersion,
chest: chest,
address: address,
number: newWalletNbr,
name: name,
derivation: newDerivationNbr,
imageDefaultPath: '${newWalletNbr % 4}.png');
imageDefaultPath: '${newWalletNbr % 4}.png',
isOwned: true);
await walletBox.add(newWallet);
await walletBox.put(newWallet.address, newWallet);
isNewDerivationLoading = false;
notifyListeners();
}
Future<void> generateRootWallet(context, String name) async {
MyWalletsProvider myWalletProvider =
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
isNewDerivationLoading = true;
@ -156,29 +158,32 @@ class MyWalletsProvider with ChangeNotifier {
int? chest = getCurrentChest();
List<WalletData> walletConfig = readAllWallets(chest);
walletConfig.sort((p1, p2) {
return Comparable.compare(p1.number!, p2.number!);
});
if (walletConfig.isEmpty) {
newWalletNbr = 0;
} else {
newWalletNbr = walletConfig.last.number! + 1;
}
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
WalletData defaultWallet = myWalletProvider.getDefaultWallet();
final address =
await sub.generateRootKeypair(defaultWallet.address!, pinCode);
await sub.generateRootKeypair(defaultWallet.address, pinCode);
WalletData newWallet = WalletData(
version: dataVersion,
chest: chest,
address: address,
number: newWalletNbr,
name: name,
derivation: -1,
imageDefaultPath: '${newWalletNbr % 4}.png');
imageDefaultPath: '${newWalletNbr % 4}.png',
isOwned: true);
await walletBox.add(newWallet);
await walletBox.put(newWallet.address, newWallet);
isNewDerivationLoading = false;
notifyListeners();
@ -192,6 +197,9 @@ class MyWalletsProvider with ChangeNotifier {
chestNumber ??= getCurrentChest();
List<WalletData> walletConfig = readAllWallets(chestNumber);
walletConfig.sort((p1, p2) {
return Comparable.compare(p1.number!, p2.number!);
});
if (walletConfig.isEmpty) {
newDerivationNbr = 2;

View File

@ -7,6 +7,7 @@ class SearchProvider with ChangeNotifier {
List searchResult = [];
final cacheDuring = 20 * 60 * 1000; //First number is minutes
int cacheTime = 0;
int resultLenght = 0;
void reload() {
notifyListeners();
@ -68,8 +69,7 @@ class SearchProvider with ChangeNotifier {
// }
Future<List<G1WalletsList>> searchAddress() async {
final WalletsProfilesProvider walletProfiles =
WalletsProfilesProvider('pubkey');
final walletProfiles = WalletsProfilesProvider('pubkey');
if (walletProfiles.isAddress(searchController.text)) {
G1WalletsList wallet = G1WalletsList(address: searchController.text);

View File

@ -1,6 +1,7 @@
// ignore_for_file: use_build_context_synchronously
// ignore_for_file: use_build_context_synchronously, body_might_complete_normally_catch_error
import 'package:easy_localization/easy_localization.dart';
import 'package:fast_base58/fast_base58.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
@ -10,6 +11,7 @@ import 'package:gecko/providers/home.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:pinenacl/ed25519.dart';
import 'package:polkawallet_sdk/api/apiKeyring.dart';
import 'package:polkawallet_sdk/api/types/networkParams.dart';
import 'package:polkawallet_sdk/api/types/txInfoData.dart';
@ -39,9 +41,11 @@ class SubstrateSdk with ChangeNotifier {
TextEditingController csSalt = TextEditingController();
TextEditingController csPassword = TextEditingController();
String g1V1NewAddress = '';
String g1V1OldPubkey = '';
bool isCesiumIDVisible = false;
bool isCesiumAddresLoading = false;
late int udValue;
Map<String, List<int>> certsCounterCache = {};
/////////////////////////////////////
////////// 1: API METHODS ///////////
@ -84,13 +88,27 @@ class SubstrateSdk with ChangeNotifier {
}
Future _getStorage(String call) async {
return await sdk.webView!.evalJavascript('api.query.$call');
try {
return await sdk.webView!.evalJavascript('api.query.$call');
} catch (e) {
log.i("catched _getStorage error");
return Future(() {});
}
}
Future _getStorageConst(String call) async {
return (await sdk.webView!
Future<int> _getStorageConst(String call) async {
final result = (await sdk.webView!
.evalJavascript('api.consts.$call', wrapPromise: false) ??
[null])[0];
return checkInt(result) ?? 0;
}
int? checkInt(dynamic value) {
if (value is int) return value;
if (value is double) return value.toInt();
if (value is String) return int.tryParse(value);
return null;
}
Future<TxSenderData> _setSender(String address) async {
@ -122,12 +140,25 @@ class SubstrateSdk with ChangeNotifier {
return await _getStorage('identity.identityIndexOf("$address")') ?? 0;
}
Future<List<int>> getCerts(String address) async {
Future<List<int>> getCertsCounter(String address) async {
final idtyIndex = await _getIdentityIndexOf(address);
final certsReceiver =
await _getStorage('cert.storageIdtyCertMeta($idtyIndex)') ?? [];
return [certsReceiver['receivedCount'], certsReceiver['issuedCount']];
if (certsCounterCache[address] == null) {
certsCounterCache.putIfAbsent(address, () => []);
}
try {
certsCounterCache.update(
address,
(value) => [
certsReceiver['receivedCount'] as int,
certsReceiver['issuedCount'] as int
]);
} catch (e) {
// catching String to int error .. network error?
}
return certsCounterCache[address]!;
}
Future<int> getCertValidityPeriod(String from, String to) async {
@ -168,8 +199,6 @@ class SubstrateSdk with ChangeNotifier {
}
Future<Map<String, double>> getBalance(String address) async {
// log.d('currencyParameters: $currencyParameters');
if (!nodeConnected) {
return {
'transferableBalance': 0,
@ -186,13 +215,11 @@ class SubstrateSdk with ChangeNotifier {
final Map? idtyData = idtyIndex == null
? null
: await _getStorage('identity.identities($idtyIndex)');
final int currentUdIndex =
int.parse(await _getStorage('universalDividend.currentUdIndex()'));
final List pastReevals =
await _getStorage('universalDividend.pastReevals()');
// Compute amount of claimable UDs
final int unclaimedUds = _computeUnclaimUds(currentUdIndex,
final int unclaimedUds = _computeUnclaimUds(
idtyData?['data']?['firstEligibleUd'] ?? 0, pastReevals);
// Calculate transferable and potential balance
@ -210,12 +237,13 @@ class SubstrateSdk with ChangeNotifier {
};
// log.i(finalBalances);
log.d(
'${getShortPubkey(address)} --- BALANCE: ${finalBalances['transferableBalance']}');
return finalBalances;
}
int _computeUnclaimUds(
int currentUdIndex, int firstEligibleUd, List pastReevals) {
int _computeUnclaimUds(int firstEligibleUd, List pastReevals) {
int totalAmount = 0;
if (firstEligibleUd == 0) return 0;
@ -239,8 +267,13 @@ class SubstrateSdk with ChangeNotifier {
return totalAmount;
}
Future<bool> isMemberGet(String address) async {
return await idtyStatus(address) == 'Validated';
Future<bool> isMember(String address) async {
final isMember = await idtyStatus(address) == 'Validated';
final walletData = walletBox.get(address) ?? WalletData(address: address);
walletData.isMember = isMember;
walletBox.put(address, walletData);
// notifyListeners();
return isMember;
}
Future<bool> isSmithGet(String address) async {
@ -260,7 +293,7 @@ class SubstrateSdk with ChangeNotifier {
Map<String, int> result = {};
final toStatus = await idtyStatus(to);
if (from != to && await isMemberGet(from)) {
if (from != to && await isMember(from)) {
final removableOn = await getCertValidityPeriod(from, to);
final certMeta = await getCertMeta(from);
final int nextIssuableOn = certMeta['nextIssuableOn'] ?? 0;
@ -275,6 +308,9 @@ class SubstrateSdk with ChangeNotifier {
result.putIfAbsent('certDelay', () => certDelayDuration);
} else if (toStatus == 'Created') {
result.putIfAbsent('toStatus', () => 1);
} else if (toStatus == 'noid') {
result.putIfAbsent('toStatus', () => 2);
result.putIfAbsent('canCert', () => 0);
} else {
result.putIfAbsent('canCert', () => 0);
}
@ -295,7 +331,7 @@ class SubstrateSdk with ChangeNotifier {
}
Future<String> idtyStatus(String address) async {
// WalletOptionsProvider walletOptions =
// final walletOptions =
// Provider.of<WalletOptionsProvider>(homeContext, listen: false);
var idtyIndex = await _getIdentityIndexOf(address);
@ -319,6 +355,15 @@ class SubstrateSdk with ChangeNotifier {
}
}
Future<bool> isSmith(String address) async {
var idtyIndex = await _getIdentityIndexOf(address);
if (idtyIndex == 0) return false;
final isSmith =
await _getStorage('smithsMembership.membership($idtyIndex)');
return isSmith == null ? false : true;
}
Future<String> getGenesisHash() async {
final String genesisHash = await sdk.webView!.evalJavascript(
'api.genesisHash.toHex()',
@ -344,21 +389,24 @@ class SubstrateSdk with ChangeNotifier {
// }
Future initCurrencyParameters() async {
currencyParameters['ss58'] =
await _getStorageConst('system.ss58Prefix.words');
currencyParameters['minCertForMembership'] =
await _getStorageConst('wot.minCertForMembership.words');
currencyParameters['newAccountPrice'] =
await _getStorageConst('account.newAccountPrice.words');
currencyParameters['existentialDeposit'] =
await _getStorageConst('balances.existentialDeposit.words');
currencyParameters['certPeriod'] =
await _getStorageConst('cert.certPeriod.words');
currencyParameters['certMaxByIssuer'] =
await _getStorageConst('cert.maxByIssuer.words');
currencyParameters['certValidityPeriod'] =
await _getStorageConst('cert.validityPeriod.words');
try {
currencyParameters['ss58'] =
await _getStorageConst('system.ss58Prefix.words');
currencyParameters['minCertForMembership'] =
await _getStorageConst('wot.minCertForMembership.words');
currencyParameters['newAccountPrice'] =
await _getStorageConst('account.newAccountPrice.words');
currencyParameters['existentialDeposit'] =
await _getStorageConst('balances.existentialDeposit.words');
currencyParameters['certPeriod'] =
await _getStorageConst('cert.certPeriod.words');
currencyParameters['certMaxByIssuer'] =
await _getStorageConst('cert.maxByIssuer.words');
currencyParameters['certValidityPeriod'] =
await _getStorageConst('cert.validityPeriod.words');
} catch (e) {
log.i('error while getting storageVals (network?) :: $e');
}
log.i('currencyParameters: $currencyParameters');
}
@ -380,6 +428,77 @@ class SubstrateSdk with ChangeNotifier {
return estimateFees.partialFee / 100;
}
int hexStringToUint16(String input) {
// Slice the string in 2-char substrings and parse it from hex to decimal
final bytes = sliceString(input, 2).map((s) => int.parse(s, radix: 16));
// Create a Uint8 from the 2-bytes list
final u8list = Uint8List.fromList(bytes.toList());
// Return a Uint16 little endian representation
return ByteData.view(u8list.buffer).getUint16(0, Endian.little);
}
List<String> sliceString(String input, int count) {
if (input.isEmpty) return [];
if (input.length % count != 0) {
throw ArgumentError("Cannot slice $input in $count slices.");
}
// final slices = List<String>(count);
var slices = List<String>.filled(count, '');
int len = input.length;
int sliceSize = len ~/ count;
for (var i = 0; i < count; i++) {
var start = i * sliceSize;
slices[i] = input.substring(start, start + sliceSize);
}
return List.unmodifiable(slices);
}
Future<DateFormat> getBlockchainStart() async {
////// Manu indexer
//// Extract block date. Ugly, I can't find a better way to get the date of the block ?
//// The only polkadot issue for that : https://github.com/polkadot-js/api/issues/2603
// const created_at = new Date(
// signedBlock.block.extrinsics
// .filter(
// ({ method: { section, method } }) =>
// section === 'timestamp' && method === 'set'
// )[0]
// .args[0].toNumber()
// )
//// manu rpc
// genesis: api.genesisHash.toHex(),
// chain: await api.rpc.chain.getHeader(),
// chainInfo: await api.registry.getChainProperties(),
// test: await api.rpc.state.getPairs('0x')
// query block finalisé qui ne change jamais.
// api.rpc.chain.subscribeFinalizedHeads
// events: await api.rpc.state.getStorage('0x26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7'),
// lastFinalizedBlock: await api.rpc.chain.getFinalizedHead()
// get block
// api.rpc.chain.getFinalizedHead
// shit
// final blockHash =
// await sdk.webView!.evalJavascript('api.rpc.chain.getBlockHash(1)');
// final Map blockContent = await sdk.webView!
// .evalJavascript('api.rpc.chain.getBlock("$blockHash")');
// final String dateBrut = blockContent['block']['extrinsics'][0];
// final dateTextByte = hex.decode(dateBrut.substring(2));
// final dateText = await sdk.webView!
// .evalJavascript('api.tx($dateTextByte)', wrapPromise: false);
// log.d('aaaaaaaaaaaaaaaaaaaaa: $dateText');
return DateFormat();
}
/////////////////////////////////////
////// 3: SUBSTRATE CONNECTION //////
/////////////////////////////////////
@ -400,9 +519,8 @@ class SubstrateSdk with ChangeNotifier {
}
Future<void> connectNode(BuildContext ctx) async {
HomeProvider homeProvider = Provider.of<HomeProvider>(ctx, listen: false);
MyWalletsProvider myWalletProvider =
Provider.of<MyWalletsProvider>(ctx, listen: false);
final homeProvider = Provider.of<HomeProvider>(ctx, listen: false);
final myWalletProvider = Provider.of<MyWalletsProvider>(ctx, listen: false);
homeProvider.changeMessage("connectionPending".tr(), 0);
@ -442,8 +560,8 @@ class SubstrateSdk with ChangeNotifier {
}
notifyListeners();
});
await initCurrencyParameters();
currentUdIndex =
int.parse(await _getStorage('universalDividend.currentUdIndex()'));
await getBalanceRatio();
notifyListeners();
@ -568,7 +686,7 @@ class SubstrateSdk with ChangeNotifier {
Future<KeyPairData?> changePassword(BuildContext context, String address,
String passOld, String passNew) async {
final account = getKeypair(address);
MyWalletsProvider myWalletProvider =
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
keyring.setCurrent(account);
myWalletProvider.resetPinCode();
@ -604,7 +722,7 @@ class SubstrateSdk with ChangeNotifier {
await chestBox.put(currentChestNumber, newChestData);
try {
final acc = getKeypair(wallet.address!);
final acc = getKeypair(wallet.address);
keyring.setCurrent(acc);
return acc.address!;
} catch (e) {
@ -680,6 +798,9 @@ class SubstrateSdk with ChangeNotifier {
cryptoType: CryptoType.ed25519,
rawSeed: rawSeedHex);
SigningKey rootKey = SigningKey(seed: rawSeed);
g1V1OldPubkey = Base58Encode(rootKey.publicKey);
g1V1NewAddress = newAddress.address!;
notifyListeners();
return g1V1NewAddress;
@ -695,8 +816,15 @@ class SubstrateSdk with ChangeNotifier {
final fromHasConsumer =
fromAddress == '' ? false : await hasAccountConsumers(fromAddress);
final toIdtyStatus = await idtyStatus(toAddress);
final isSmithData = await isSmith(fromAddress);
return [fromBalance, fromIdtyStatus, toIdtyStatus, fromHasConsumer];
return [
fromBalance,
fromIdtyStatus,
toIdtyStatus,
fromHasConsumer,
isSmithData
];
}
//////////////////////////////////////
@ -779,7 +907,7 @@ class SubstrateSdk with ChangeNotifier {
List txOptions = [];
String? rawParams;
final toCerts = await getCerts(destAddress);
final toCerts = await getCertsCounter(destAddress);
// log.d('debug: ${currencyParameters['minCertForMembership']}');
@ -1007,7 +1135,7 @@ void snackNode(BuildContext context, bool isConnected) {
if (!isConnected) {
message = "noDuniterNodeAvailableTryLater".tr();
} else {
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
message =
"${"youAreConnectedToNode".tr()}\n${sub.getConnectedEndpoint()!.split('//')[1]}";

View File

@ -11,14 +11,12 @@ import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/screens/animated_text.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/widgets/commons/common_elements.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:gecko/screens/transaction_in_progress.dart';
import 'package:image_picker/image_picker.dart';
import 'package:provider/provider.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:truncate/truncate.dart';
class WalletOptionsProvider with ChangeNotifier {
TextEditingController address = TextEditingController();
@ -28,12 +26,11 @@ class WalletOptionsProvider with ChangeNotifier {
TextEditingController newPin = TextEditingController();
bool isEditing = false;
bool isBalanceBlur = false;
FocusNode walletNameFocus = FocusNode();
TextEditingController nameController = TextEditingController();
late bool isDefaultWallet;
bool canValidateNameBool = false;
Map<String, String> idtyStatusCache = {};
Future<NewWallet>? get badWallet => null;
Map<String, double> balanceCache = {};
int getPinLenght(walletNbr) {
return pinLength;
@ -51,27 +48,27 @@ class WalletOptionsProvider with ChangeNotifier {
}
Future<int> deleteWallet(context, WalletData wallet) async {
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final bool? answer = await (confirmPopup(
context, 'areYouSureToForgetWallet'.tr(args: [wallet.name!])));
if (answer ?? false) {
//Check if balance is null
final balance = await sub.getBalance(wallet.address!);
final balance = await sub.getBalance(wallet.address);
if (balance != {}) {
MyWalletsProvider myWalletProvider =
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
final defaultWallet = myWalletProvider.getDefaultWallet();
log.d(defaultWallet.address);
sub.pay(
fromAddress: wallet.address!,
destAddress: defaultWallet.address!,
fromAddress: wallet.address,
destAddress: defaultWallet.address,
amount: -1,
password: myWalletProvider.pinCode);
}
await walletBox.delete(wallet.key);
await sub.deleteAccounts([wallet.address!]);
await sub.deleteAccounts([wallet.address]);
Navigator.pop(context);
}
@ -132,98 +129,17 @@ class WalletOptionsProvider with ChangeNotifier {
}
}
Widget idtyStatus(BuildContext context, String address,
{bool isOwner = false, Color color = Colors.black}) {
DuniterIndexer duniterIndexer =
Provider.of<DuniterIndexer>(context, listen: false);
showText(String text,
[double size = 18, bool bold = false, bool smooth = true]) {
log.d('$address $text');
return AnimatedFadeOutIn<String>(
data: text,
duration: Duration(milliseconds: smooth ? 200 : 0),
builder: (value) => Text(
value,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: size,
color: bold ? color : Colors.black,
fontWeight: bold ? FontWeight.w500 : FontWeight.w400),
),
);
}
return Consumer<SubstrateSdk>(builder: (context, sub, _) {
return FutureBuilder(
future: sub.idtyStatus(address),
initialData: '',
builder: (context, snapshot) {
idtyStatusCache[address] = snapshot.data.toString();
switch (snapshot.data.toString()) {
case 'noid':
{
return showText('noIdentity'.tr());
}
case 'Created':
{
return showText('identityCreated'.tr());
}
case 'ConfirmedByOwner':
{
return isOwner
? showText('identityConfirmed'.tr())
: duniterIndexer.getNameByAddress(
context,
address,
null,
20,
true,
Colors.grey[700]!,
FontWeight.w500,
FontStyle.italic);
}
case 'Validated':
{
return isOwner
? showText('memberValidated'.tr(), 18, true)
: duniterIndexer.getNameByAddress(
context,
address,
null,
20,
true,
Colors.black,
FontWeight.w600,
FontStyle.normal);
}
case 'expired':
{
return showText('identityExpired'.tr());
}
}
return SizedBox(
child: showText('', 18, false, false),
);
});
});
}
Future<bool> isMember(BuildContext context, String address) async {
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
return await sub.idtyStatus(address) == 'Validated';
}
Future<String?> confirmIdentityPopup(BuildContext context) async {
TextEditingController idtyName = TextEditingController();
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
WalletOptionsProvider walletOptions =
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
MyWalletsProvider myWalletProvider =
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
bool canValidate = false;
bool idtyExist = false;
return showDialog<String>(
context: context,
barrierDismissible: true, // user must tap button!
@ -240,7 +156,16 @@ class WalletOptionsProvider with ChangeNotifier {
const SizedBox(height: 20),
TextField(
key: keyEnterIdentityUsername,
onChanged: (_) => notifyListeners(),
onChanged: (_) async {
idtyExist = await isIdtyExist(idtyName.text);
canValidate = !idtyExist &&
!await isIdtyExist(idtyName.text) &&
idtyName.text.length >= 2 &&
idtyName.text.length <= 32;
log.d('aaaaaaaaaa: $canValidate');
notifyListeners();
},
inputFormatters: <TextInputFormatter>[
// FilteringTextInputFormatter.allow(RegExp("[0-9a-zA-Z]")),
FilteringTextInputFormatter.deny(RegExp(r'^ ')),
@ -250,7 +175,12 @@ class WalletOptionsProvider with ChangeNotifier {
autofocus: true,
controller: idtyName,
style: const TextStyle(fontSize: 19),
)
),
const SizedBox(height: 10),
Consumer<WalletOptionsProvider>(builder: (context, wOptions, _) {
return Text(idtyExist ? "thisIdentityAlreadyExist".tr() : '',
style: TextStyle(color: Colors.red[500]));
})
]),
),
actions: <Widget>[
@ -261,61 +191,65 @@ class WalletOptionsProvider with ChangeNotifier {
builder: (context, wOptions, _) {
return TextButton(
key: keyConfirm,
onPressed: canValidate
? () async {
idtyName.text =
idtyName.text.trim().replaceAll(' ', '');
if (idtyName.text.length.clamp(3, 32) ==
idtyName.text.length) {
WalletData? defaultWallet =
myWalletProvider.getDefaultWallet();
String? pin;
if (myWalletProvider.pinCode == '') {
pin = await Navigator.push(
context,
MaterialPageRoute(
builder: (homeContext) {
return UnlockingWallet(
wallet: defaultWallet);
},
),
);
}
if (pin != null ||
myWalletProvider.pinCode != '') {
final wallet = myWalletProvider
.getWalletDataByAddress(address.text);
await sub.setCurrentWallet(wallet!);
sub.confirmIdentity(walletOptions.address.text,
idtyName.text, myWalletProvider.pinCode);
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return TransactionInProgress(
transType: 'comfirmIdty',
fromAddress:
getShortPubkey(wallet.address),
toAddress: getShortPubkey(wallet.address),
);
}),
);
}
}
}
: null,
child: Text(
"validate".tr(),
style: TextStyle(
fontSize: 21,
color: idtyName.text.length.clamp(3, 64) ==
idtyName.text.length
? const Color(0xffD80000)
: Colors.grey,
),
fontSize: 21,
color: canValidate
? const Color(0xffD80000)
: Colors.grey[500]),
),
onPressed: () async {
idtyName.text = idtyName.text.trim().replaceAll(' ', '');
if (idtyName.text.length.clamp(3, 64) ==
idtyName.text.length) {
WalletData? defaultWallet =
myWalletProvider.getDefaultWallet();
String? pin;
if (myWalletProvider.pinCode == '') {
pin = await Navigator.push(
context,
MaterialPageRoute(
builder: (homeContext) {
return UnlockingWallet(wallet: defaultWallet);
},
),
);
}
if (pin != null || myWalletProvider.pinCode != '') {
final wallet = myWalletProvider
.getWalletDataByAddress(address.text);
await sub.setCurrentWallet(wallet!);
sub.confirmIdentity(walletOptions.address.text,
idtyName.text, myWalletProvider.pinCode);
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return TransactionInProgress(
transType: 'comfirmIdty',
fromAddress: getShortPubkey(wallet.address!),
toAddress: getShortPubkey(wallet.address!),
);
}),
);
}
}
},
);
})
],
),
const SizedBox(height: 20)
const SizedBox(height: 5)
],
);
},
@ -371,7 +305,7 @@ class WalletOptionsProvider with ChangeNotifier {
if (canValidateNameBool) {
nameController.text = walletName.text;
_renameWallet(wID, walletName.text, isCesium: false);
// notifyListeners();
notifyListeners();
Navigator.pop(context);
}
},
@ -405,7 +339,7 @@ class WalletOptionsProvider with ChangeNotifier {
}
bool canValidateName(BuildContext context, TextEditingController walletName) {
MyWalletsProvider myWalletProvider =
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
bool isNameValid = walletName.text.length >= 2 &&
@ -441,7 +375,7 @@ class WalletOptionsProvider with ChangeNotifier {
String? addressGet;
walletBox.toMap().forEach((key, value) {
if (value.chest == chest && value.derivation == derivation) {
addressGet = value.address!;
addressGet = value.address;
return;
}
});
@ -450,190 +384,4 @@ class WalletOptionsProvider with ChangeNotifier {
return addressGet;
}
Widget walletNameController(BuildContext context, WalletData wallet,
[double size = 20]) {
nameController.text = wallet.name!;
return SizedBox(
width: 260,
child: Stack(children: <Widget>[
TextField(
key: keyWalletName,
autofocus: false,
focusNode: walletNameFocus,
enabled: isEditing,
controller: nameController,
minLines: 1,
maxLines: 3,
textAlign: TextAlign.center,
decoration: const InputDecoration(
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
disabledBorder: InputBorder.none,
contentPadding: EdgeInsets.all(15.0),
),
style: TextStyle(
fontSize: isTall ? size : size * 0.9,
color: Colors.black,
fontWeight: FontWeight.w400,
),
),
Positioned(
right: 0,
child: InkWell(
key: keyRenameWallet,
onTap: () async {
// _isNewNameValid =
// walletProvider.editWalletName(wallet.id(), isCesium: false);
await editWalletName(context, wallet.id());
await Future.delayed(const Duration(milliseconds: 30));
walletNameFocus.requestFocus();
},
child: ClipRRect(
child: Image.asset(
isEditing
? 'assets/walletOptions/android-checkmark.png'
: 'assets/walletOptions/edit.png',
width: 25,
height: 25),
),
),
),
]),
);
}
Widget walletName(BuildContext context, WalletData wallet,
[double size = 20, Color color = Colors.black]) {
double newSize = wallet.name!.length <= 15 ? size : size - 2;
return Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
Text(
truncate(wallet.name!, 20),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: isTall ? newSize : newSize * 0.9,
color: color,
fontWeight: FontWeight.w400,
fontStyle: FontStyle.italic,
),
softWrap: false,
overflow: TextOverflow.ellipsis,
),
]);
}
}
Map<String, double> balanceCache = {};
Widget balance(BuildContext context, String address, double size,
[Color color = Colors.black,
Color loadingColor = const Color(0xffd07316)]) {
return Column(children: <Widget>[
Consumer<SubstrateSdk>(builder: (context, sdk, _) {
return FutureBuilder(
future: sdk.getBalance(address),
builder: (BuildContext context,
AsyncSnapshot<Map<String, double>> globalBalance) {
if (globalBalance.connectionState != ConnectionState.done ||
globalBalance.hasError) {
if (balanceCache[address] != null &&
balanceCache[address] != -1) {
return Row(children: [
Text(balanceCache[address]!.toString(),
style: TextStyle(
fontSize: isTall ? size : size * 0.9, color: color)),
const SizedBox(width: 5),
udUnitDisplay(size, color),
]);
} else {
return SizedBox(
height: 15,
width: 15,
child: CircularProgressIndicator(
color: loadingColor,
strokeWidth: 2,
),
);
}
}
balanceCache[address] = globalBalance.data!['transferableBalance']!;
if (balanceCache[address] != -1) {
return Row(children: [
Text(
balanceCache[address]!.toString(),
style: TextStyle(
fontSize: isTall ? size : size * 0.9,
color: color,
),
),
const SizedBox(width: 5),
udUnitDisplay(size, color),
]);
} else {
return const Text('');
}
});
}),
]);
}
Widget getCerts(BuildContext context, String address, double size,
[Color color = Colors.black]) {
return Column(children: <Widget>[
Consumer<SubstrateSdk>(builder: (context, sdk, _) {
return FutureBuilder(
future: sdk.getCerts(address),
builder: (BuildContext context, AsyncSnapshot<List<int>> certs) {
// log.d(_certs.data);
return certs.data?[0] != 0 && certs.data != null
? Row(
children: [
Image.asset('assets/medal.png', height: 20),
const SizedBox(width: 1),
Text(certs.data?[0].toString() ?? '0',
style: const TextStyle(fontSize: 20)),
const SizedBox(width: 5),
Text(
"(${certs.data?[1].toString() ?? '0'})",
style: const TextStyle(fontSize: 14),
)
],
)
: const Text('');
});
}),
]);
}
Widget udUnitDisplay(double size, [Color color = Colors.black]) {
final bool isUdUnit = configBox.get('isUdUnit') ?? false;
return isUdUnit
? Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
'ud'.tr(args: ['']),
style:
TextStyle(fontSize: isTall ? size : size * 0.9, color: color),
),
Column(
children: [
Text(
currencyName,
style: TextStyle(
fontSize: (isTall ? size : size * 0.9) * 0.7,
fontWeight: FontWeight.w500,
color: color),
),
const SizedBox(height: 15)
],
)
],
)
: Text(currencyName,
style: TextStyle(fontSize: isTall ? size : size * 0.9, color: color));
}

View File

@ -1,20 +1,13 @@
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/g1_wallets_list.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/cesium_plus.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/wallet_view.dart';
import 'package:jdenticon_dart/jdenticon_dart.dart';
import 'package:permission_handler/permission_handler.dart';
// import 'package:qrscan/qrscan.dart' as scanner;
import 'package:barcode_scan2/barcode_scan2.dart';
import 'package:provider/provider.dart';
class WalletsProfilesProvider with ChangeNotifier {
WalletsProfilesProvider(this.address);
@ -37,14 +30,17 @@ class WalletsProfilesProvider with ChangeNotifier {
try {
barcode = await BarcodeScanner.scan();
} catch (e) {
log.e(e);
log.e("BarcodeScanner ERR: $e");
return 'false';
}
if (isAddress(barcode.rawContent)) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return WalletViewScreen(address: barcode!.rawContent);
return WalletViewScreen(
address: barcode!.rawContent,
username: '',
);
}),
);
} else {
@ -129,102 +125,6 @@ class WalletsProfilesProvider with ChangeNotifier {
return _balance;
}
Widget headerProfileView(
BuildContext context, String address, String? username) {
const double avatarSize = 140;
WalletOptionsProvider walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
CesiumPlusProvider cesiumPlusProvider =
Provider.of<CesiumPlusProvider>(context, listen: false);
// SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
return Stack(children: <Widget>[
Consumer<SubstrateSdk>(builder: (context, sub, _) {
bool isAccountExist = balanceCache[address] != 0;
return Container(
height: 180,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
isAccountExist ? yellowC : Colors.grey[400]!,
isAccountExist ? const Color(0xFFE7811A) : Colors.grey[600]!,
],
),
));
}),
Padding(
padding: const EdgeInsets.only(left: 30, right: 40),
child: Row(children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
height: 10,
color: yellowC, // Colors.grey[400],
),
Row(children: [
GestureDetector(
key: keyCopyAddress,
onTap: () {
Clipboard.setData(ClipboardData(text: address));
snackCopyKey(context);
},
child: Text(
getShortPubkey(address),
style: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.w800,
),
),
),
]),
const SizedBox(height: 25),
balance(context, address, 22),
const SizedBox(height: 10),
walletOptions.idtyStatus(context, address,
isOwner: false, color: Colors.black),
getCerts(context, address, 14),
// if (username == null &&
// g1WalletsBox.get(address)?.username != null)
// SizedBox(
// width: 230,
// child: Text(
// g1WalletsBox.get(address)?.username ?? '',
// style: const TextStyle(
// fontSize: 27,
// color: Color(0xff814C00),
// ),
// ),
// ),
// if (username != null)
// SizedBox(
// width: 230,
// child: Text(
// username,
// style: const TextStyle(
// fontSize: 27,
// color: Color(0xff814C00),
// ),
// ),
// ),
const SizedBox(height: 55),
]),
const Spacer(),
Column(children: <Widget>[
ClipOval(
child: cesiumPlusProvider.defaultAvatar(avatarSize),
),
const SizedBox(height: 25),
]),
]),
),
CommonElements().offlineInfo(context),
]);
}
bool isContact(String address) {
return contactsBox.containsKey(address);
}
@ -244,6 +144,15 @@ class WalletsProfilesProvider with ChangeNotifier {
}
}
snackMessage(context,
{required String message, int duration = 2, double fontSize = 16}) {
final snackBar = SnackBar(
padding: const EdgeInsets.all(20),
content: Text(message, style: TextStyle(fontSize: fontSize)),
duration: Duration(seconds: duration));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
snackCopyKey(context) {
final snackBar = SnackBar(
padding: const EdgeInsets.all(20),
@ -252,3 +161,12 @@ snackCopyKey(context) {
duration: const Duration(seconds: 2));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
snackCopySeed(context) {
final snackBar = SnackBar(
padding: const EdgeInsets.all(20),
content: Text("thisMnemonicHasBeenCopiedToClipboard".tr(),
style: const TextStyle(fontSize: 17)),
duration: const Duration(seconds: 4));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}

View File

@ -1,44 +1,24 @@
// ignore_for_file: must_be_immutable
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/queries_indexer.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/cesium_plus.dart';
import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/home.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:flutter/material.dart';
import 'package:gecko/screens/wallet_view.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:provider/provider.dart';
import 'package:gecko/widgets/bottom_app_bar.dart';
import 'package:gecko/widgets/header_profile.dart';
import 'package:gecko/widgets/history_query.dart';
class ActivityScreen extends StatelessWidget with ChangeNotifier {
ActivityScreen({required this.address, required this.avatar, this.username})
: super(key: keyActivityScreen);
final ScrollController scrollController = ScrollController();
final double avatarsSize = 80;
final String address;
final String? username;
final Image avatar;
FetchMore? fetchMore;
FetchMoreOptions? opts;
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
WalletsProfilesProvider walletProfile =
Provider.of<WalletsProfilesProvider>(context, listen: false);
HomeProvider homeProvider =
Provider.of<HomeProvider>(context, listen: false);
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
elevation: 0,
toolbarHeight: 60 * ratio,
@ -47,319 +27,10 @@ class ActivityScreen extends StatelessWidget with ChangeNotifier {
child: Text('accountActivity'.tr()),
),
),
bottomNavigationBar: homeProvider.bottomAppBar(context),
bottomNavigationBar: const GeckoBottomAppBar(),
body: Column(children: <Widget>[
walletProfile.headerProfileView(context, address, username),
historyQuery(context),
HeaderProfile(address: address, username: username),
HistoryQuery(address: address),
]));
}
Widget historyQuery(context) {
DuniterIndexer duniterIndexer =
Provider.of<DuniterIndexer>(context, listen: false);
if (indexerEndpoint == '') {
Column(children: <Widget>[
const SizedBox(height: 50),
Text(
"noNetworkNoHistory".tr(),
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 18),
)
]);
}
final httpLink = HttpLink(
'$indexerEndpoint/v1beta1/relay',
);
final client = ValueNotifier(
GraphQLClient(
cache: GraphQLCache(),
link: httpLink,
),
);
return GraphQLProvider(
client: client,
child: Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Query(
options: QueryOptions(
document: gql(getHistoryByAddressQ),
variables: <String, dynamic>{
'address': address,
'number': 20,
'cursor': null
},
),
builder: (QueryResult result, {fetchMore, refetch}) {
if (result.isLoading && result.data == null) {
return const Center(
child: CircularProgressIndicator(),
);
}
if (result.hasException) {
log.e('Error Indexer: ${result.exception}');
return Column(children: <Widget>[
const SizedBox(height: 50),
Text(
"noNetworkNoHistory".tr(),
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 18),
)
]);
} else if (result
.data?['transaction_connection']?['edges'].isEmpty) {
return Column(children: <Widget>[
const SizedBox(height: 50),
Text(
"noDataToDisplay".tr(),
style: const TextStyle(fontSize: 18),
)
]);
}
if (result.isNotLoading) {
// log.d(result.data);
opts = duniterIndexer.checkQueryResult(result, opts, address);
}
// Build history list
return NotificationListener(
child: Builder(
builder: (context) => Expanded(
child: ListView(
key: keyListTransactions,
controller: scrollController,
children: <Widget>[historyView(context, result)],
),
),
),
onNotification: (dynamic t) {
if (t is ScrollEndNotification &&
scrollController.position.pixels >=
scrollController.position.maxScrollExtent * 0.7 &&
duniterIndexer.pageInfo!['hasNextPage'] &&
result.isNotLoading) {
fetchMore!(opts!);
}
return true;
});
},
),
],
)),
);
}
Widget historyView(context, result) {
DuniterIndexer duniterIndexer =
Provider.of<DuniterIndexer>(context, listen: false);
return duniterIndexer.transBC == null
? Column(children: <Widget>[
const SizedBox(height: 50),
Text(
"noTransactionToDisplay".tr(),
style: const TextStyle(fontSize: 18),
)
])
: Column(children: <Widget>[
getTransactionTile(context, duniterIndexer),
if (result.isLoading && duniterIndexer.pageInfo!['hasPreviousPage'])
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
CircularProgressIndicator(),
],
),
if (!duniterIndexer.pageInfo!['hasNextPage'])
Column(
children: const <Widget>[
SizedBox(height: 15),
Text("Début de l'historique.",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20)),
SizedBox(height: 15)
],
)
]);
}
Widget getTransactionTile(
BuildContext context, DuniterIndexer duniterIndexer) {
CesiumPlusProvider cesiumPlusProvider =
Provider.of<CesiumPlusProvider>(context, listen: false);
int keyID = 0;
String? dateDelimiter;
String? lastDateDelimiter;
const double avatarSize = 200;
bool isTody = false;
bool isYesterday = false;
bool isThisWeek = false;
final Map<int, String> monthsInYear = {
1: "month1".tr(),
2: "month2".tr(),
3: "month3".tr(),
4: "month4".tr(),
5: "month5".tr(),
6: "month6".tr(),
7: "month7".tr(),
8: "month8".tr(),
9: "month9".tr(),
10: "month10".tr(),
11: "month11".tr(),
12: "month12".tr()
};
return Column(
children: duniterIndexer.transBC!.map((repository) {
// log.d('bbbbbbbbbbbbbbbbbbbbbb: ' + repository.toString());
DateTime now = DateTime.now();
DateTime date = repository[0];
String dateForm;
if ({4, 10, 11, 12}.contains(date.month)) {
dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, 3)}.";
} else if ({1, 2, 7, 9}.contains(date.month)) {
dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, 4)}.";
} else {
dateForm = "${date.day} ${monthsInYear[date.month]}";
}
int weekNumber(DateTime date) {
int dayOfYear = int.parse(DateFormat("D").format(date));
return ((dayOfYear - date.weekday + 10) / 7).floor();
}
final transactionDate = DateTime(date.year, date.month, date.day);
final todayDate = DateTime(now.year, now.month, now.day);
final yesterdayDate = DateTime(now.year, now.month, now.day - 1);
if (transactionDate == todayDate && !isTody) {
dateDelimiter = lastDateDelimiter = "today".tr();
isTody = true;
} else if (transactionDate == yesterdayDate && !isYesterday) {
dateDelimiter = lastDateDelimiter = "yesterday".tr();
isYesterday = true;
} else if (weekNumber(date) == weekNumber(now) &&
date.year == now.year &&
lastDateDelimiter != "thisWeek".tr() &&
transactionDate != yesterdayDate &&
transactionDate != todayDate &&
!isThisWeek) {
dateDelimiter = lastDateDelimiter = "thisWeek".tr();
isThisWeek = true;
} else if (lastDateDelimiter != monthsInYear[date.month] &&
lastDateDelimiter != "${monthsInYear[date.month]} ${date.year}" &&
transactionDate != todayDate &&
transactionDate != yesterdayDate &&
!(weekNumber(date) == weekNumber(now) && date.year == now.year)) {
if (date.year == now.year) {
dateDelimiter = lastDateDelimiter = monthsInYear[date.month];
} else {
dateDelimiter =
lastDateDelimiter = "${monthsInYear[date.month]} ${date.year}";
}
} else {
dateDelimiter = null;
}
final bool isUdUnit = configBox.get('isUdUnit') ?? false;
late double amount;
late String finalAmount;
amount = repository[4] == 'RECEIVED' ? repository[3] : repository[3] * -1;
if (isUdUnit) {
amount = round(amount / balanceRatio);
finalAmount = 'ud'.tr(args: ['$amount ']);
} else {
finalAmount = '$amount $currencyName';
}
return Column(children: <Widget>[
if (dateDelimiter != null)
Padding(
padding: const EdgeInsets.symmetric(vertical: 30),
child: Text(
dateDelimiter!,
style: const TextStyle(
fontSize: 23, color: orangeC, fontWeight: FontWeight.w300),
),
),
Padding(
padding: const EdgeInsets.only(right: 0),
child:
// Row(children: [Column(children: [],)],)
ListTile(
key: keyTransaction(keyID++),
contentPadding: const EdgeInsets.only(
left: 20, right: 30, top: 15, bottom: 15),
leading: ClipOval(
child: cesiumPlusProvider.defaultAvatar(avatarSize),
),
title: Padding(
padding: const EdgeInsets.only(bottom: 5),
child: Text(getShortPubkey(repository[1]),
style: const TextStyle(
fontSize: 18, fontFamily: 'Monospace')),
),
subtitle: RichText(
text: TextSpan(
style: TextStyle(
fontSize: 16,
color: Colors.grey[700],
),
children: <TextSpan>[
TextSpan(
text: dateForm,
),
if (repository[2] != '')
TextSpan(
text: ' · ',
style: TextStyle(
fontSize: 20,
color: Colors.grey[550],
),
),
TextSpan(
text: repository[2],
style: TextStyle(
fontStyle: FontStyle.italic,
color: Colors.grey[600],
),
),
],
),
),
trailing: Text(finalAmount,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.w500),
textAlign: TextAlign.justify),
dense: false,
isThreeLine: false,
onTap: () {
duniterIndexer.nPage = 1;
// _cesiumPlusProvider.avatarCancelToken.cancel('cancelled');
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return WalletViewScreen(address: repository[1]);
}),
);
// Navigator.pop(context);
}),
),
]);
}).toList());
}
}

View File

@ -0,0 +1,76 @@
import 'package:accordion/controllers.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
import 'package:gecko/widgets/certs_received.dart';
import 'package:gecko/widgets/certs_counter.dart';
import 'package:gecko/widgets/certs_sent.dart';
import 'package:accordion/accordion.dart';
class CertificationsScreen extends StatelessWidget {
const CertificationsScreen(
{Key? key, required this.address, required this.username})
: super(key: key);
final String address;
final String username;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
elevation: 0,
toolbarHeight: 60 * ratio,
title: SizedBox(
height: 22,
child: Text('Certifications de $username'),
)),
body: SafeArea(
child: Accordion(
paddingListTop: 10,
paddingListBottom: 10,
maxOpenSections: 1,
headerBackgroundColorOpened: orangeC,
scaleWhenAnimating: true,
openAndCloseAnimation: true,
headerPadding:
const EdgeInsets.symmetric(vertical: 7, horizontal: 15),
sectionOpeningHapticFeedback: SectionHapticFeedback.heavy,
sectionClosingHapticFeedback: SectionHapticFeedback.light,
children: [
AccordionSection(
isOpen: true,
leftIcon:
const Icon(Icons.insights_rounded, color: Colors.black),
headerBackgroundColor: yellowC,
headerBackgroundColorOpened: orangeC,
header: Row(children: [
Text('received'.tr()),
const SizedBox(width: 5),
CertsCounter(address: address)
]),
content: CertsReceived(address: address),
contentHorizontalPadding: 0,
contentBorderWidth: 1,
),
AccordionSection(
isOpen: false,
leftIcon:
const Icon(Icons.insights_rounded, color: Colors.black),
headerBackgroundColor: yellowC,
headerBackgroundColorOpened: orangeC,
header: Row(children: [
Text('sent'.tr()),
const SizedBox(width: 5),
CertsCounter(address: address, isSent: true)
]),
content: CertsSent(address: address),
contentHorizontalPadding: 20,
contentBorderWidth: 1,
// onOpenSection: () => print('onOpenSection ...'),
// onCloseSection: () => print('onCloseSection ...'),
),
]),
));
}
}

View File

@ -1,338 +0,0 @@
import 'package:dots_indicator/dots_indicator.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:provider/provider.dart';
class CommonElements {
// Exemple de Widget
Widget exemple(String data) {
return const Text('Coucou');
}
Widget buildImage(String assetName,
[double boxHeight = 440, double imageWidth = 350]) {
return Container(
padding: const EdgeInsets.all(0),
width: 440,
height: isTall ? boxHeight : boxHeight * 0.9,
decoration: BoxDecoration(
gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xffd2d4cf),
Color(0xffeaeae7),
],
),
border: Border.all(color: Colors.grey[900]!)),
child: Image.asset('assets/onBoarding/$assetName', width: imageWidth));
}
Widget buildText(String text, [double size = 20, bool isMd = false]) {
final mdStyle = MarkdownStyleSheet(
p: TextStyle(
fontSize: isTall ? size : size * 0.9,
color: Colors.black,
letterSpacing: 0.3),
textAlign: WrapAlignment.spaceBetween,
);
return Container(
padding: const EdgeInsets.all(12),
width: 440,
decoration: BoxDecoration(
color: Colors.white, border: Border.all(color: Colors.grey[900]!)),
child: isMd
? MarkdownBody(data: text, styleSheet: mdStyle)
: Text(text,
textAlign: TextAlign.justify,
style: TextStyle(
fontSize: isTall ? size : size * 0.9,
color: Colors.black,
letterSpacing: 0.3)),
);
}
Widget nextButton(
BuildContext context, String text, nextScreen, bool isFast) {
return SizedBox(
width: 380 * ratio,
height: 60 * ratio,
child: ElevatedButton(
key: keyGoNext,
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, backgroundColor: orangeC,
elevation: 4, // foreground
),
onPressed: () {
Navigator.push(
context, FaderTransition(page: nextScreen, isFast: isFast));
},
child: Text(
text,
style: TextStyle(fontSize: 23 * ratio, fontWeight: FontWeight.w600),
),
),
);
}
Widget buildProgressBar(double pagePosition) {
return DotsIndicator(
dotsCount: 10,
position: pagePosition,
decorator: DotsDecorator(
spacing: const EdgeInsets.symmetric(horizontal: 10),
color: Colors.grey[300]!, // Inactive color
activeColor: orangeC,
),
);
}
Widget infoIntro(
BuildContext context,
String text,
String assetName,
String buttonText,
nextScreen,
double pagePosition, {
bool isMd = false,
bool isFast = false,
double boxHeight = 440,
double imageWidth = 350,
double textSize = 20,
}) {
return Column(children: <Widget>[
SizedBox(height: isTall ? 40 : 20),
buildProgressBar(pagePosition),
SizedBox(height: isTall ? 40 : 20),
buildText(text, textSize, isMd),
buildImage(assetName, boxHeight, imageWidth),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: nextButton(context, buttonText, nextScreen, false),
),
),
// const SizedBox(height: 40),
SizedBox(height: isTall ? 40 : 20),
]);
}
Widget roundButton(
AssetImage image,
ontap,
isAsync,
double imgHight,
EdgeInsets padding,
) {
return Container(
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey,
blurRadius: 4.0,
offset: Offset(2.0, 2.5),
spreadRadius: 0.5)
],
),
child: ClipOval(
child: Material(
color: const Color(0xffFFD58D), // button color
child: InkWell(
splashColor: orangeC, // inkwell color
child: Padding(
padding: padding,
child: Image(image: image, height: imgHight)),
onTap: () async {
await ontap;
}),
),
),
);
}
Widget offlineInfo(BuildContext context) {
final double screenWidth = MediaQuery.of(homeContext).size.width;
return Consumer<SubstrateSdk>(builder: (context, sub, _) {
return Visibility(
visible: !sub.nodeConnected,
child: Positioned(
top: 0,
child: Container(
height: 30,
width: screenWidth,
color: Colors.grey[800],
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'youAreOffline'.tr(),
style: TextStyle(color: Colors.grey[50]),
textAlign: TextAlign.center,
),
],
)),
),
);
});
}
}
class SmoothTransition extends PageRouteBuilder {
final Widget page;
SmoothTransition({required this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
TweenAnimationBuilder(
duration: const Duration(seconds: 5),
tween: Tween(begin: 200, end: 200),
builder: (BuildContext context, dynamic value, Widget? child) {
return page;
},
),
);
}
class FaderTransition extends PageRouteBuilder {
final Widget page;
final bool isFast;
FaderTransition({required this.page, required this.isFast})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
FadeTransition(
opacity:
Tween(begin: 0.0, end: isFast ? 3.0 : 1.0).animate(animation),
child: child,
),
);
}
Future<bool?> confirmPopup(BuildContext context, String title) async {
return showDialog<bool>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
backgroundColor: backgroundColor,
content: Text(
title,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
),
actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
key: keyConfirm,
child: Text(
"yes".tr(),
style: const TextStyle(
fontSize: 21,
color: Color(0xffD80000),
),
),
onPressed: () {
Navigator.pop(context, true);
},
),
const SizedBox(width: 20),
TextButton(
child: Text(
"no".tr(),
style: const TextStyle(fontSize: 21),
),
onPressed: () {
Navigator.pop(context, false);
},
),
const SizedBox(height: 120)
],
)
],
);
},
);
}
Future<void> infoPopup(BuildContext context, String title) async {
return showDialog<void>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
backgroundColor: backgroundColor,
content: Text(
title,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
),
actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
key: keyInfoPopup,
child: const Text(
"D'accord",
style: TextStyle(
fontSize: 21,
color: Color(0xffD80000),
),
),
onPressed: () {
Navigator.pop(context, true);
},
),
],
)
],
);
},
);
}
// Widget geckoAppBar() {
// return AppBar(
// toolbarHeight: 60 * ratio,
// elevation: 0,
// leading: IconButton(
// icon: const Icon(Icons.arrow_back, color: Colors.black),
// onPressed: () {
// _walletOptions.isEditing = false;
// _walletOptions.isBalanceBlur = false;
// Navigator.pop(context);
// }),
// title: SizedBox(
// height: 22,
// child: Consumer<WalletOptionsProvider>(
// builder: (context, walletProvider, _) {
// return Text(_walletOptions.nameController.text);
// }),
// ),
// );
// }

View File

@ -3,8 +3,10 @@
import 'package:bubble/bubble.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/stateful_wrapper.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/g1_wallets_list.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/chest_provider.dart';
import 'package:gecko/providers/duniter_indexer.dart';
@ -14,30 +16,124 @@ import 'package:gecko/providers/wallets_profiles.dart';
import 'package:flutter/material.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/screens/animated_text.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/widgets/commons/animated_text.dart';
import 'package:gecko/widgets/commons/common_elements.dart';
import 'package:gecko/screens/myWallets/restore_chest.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:gecko/screens/myWallets/wallets_home.dart';
import 'package:gecko/screens/onBoarding/1.dart';
import 'package:gecko/screens/search.dart';
import 'package:gecko/screens/settings.dart';
import 'package:flutter/services.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:provider/provider.dart';
import 'package:gecko/screens/my_contacts.dart';
class HomeScreen extends StatelessWidget {
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) async {
final homeProviderInit =
Provider.of<HomeProvider>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final duniterIndexer =
Provider.of<DuniterIndexer>(context, listen: false);
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
final bool isWalletsExists = myWalletProvider.checkIfWalletExist();
// Check if versionData non compatible, drop everything
if (configBox.get('dataVersion') == null) {
configBox.put('dataVersion', dataVersion);
}
if (isWalletsExists && (configBox.get('dataVersion')) < dataVersion) {
if (!sub.sdkReady && !sub.sdkLoading) sub.initApi();
await infoPopup(context, "chestNotCompatibleMustReinstallGecko".tr());
await Hive.deleteBoxFromDisk('walletBox');
await Hive.deleteBoxFromDisk('chestBox');
chestBox = await Hive.openBox<ChestData>("chestBox");
await configBox.delete('defaultWallet');
if (!sub.sdkReady && !sub.sdkLoading) await sub.initApi();
await sub.deleteAllAccounts();
configBox.put('dataVersion', dataVersion);
myWalletProvider.reload();
} else {
if (!sub.sdkReady && !sub.sdkLoading) await sub.initApi();
}
if (sub.sdkReady && !sub.nodeConnected) {
walletBox = await Hive.openBox<WalletData>("walletBox");
await Hive.deleteBoxFromDisk('g1WalletsBox');
g1WalletsBox = await Hive.openBox<G1WalletsList>("g1WalletsBox");
contactsBox = await Hive.openBox<G1WalletsList>("contactsBox");
homeProviderInit.isWalletBoxInit = true;
myWalletProvider.reload();
duniterIndexer.getValidIndexerEndpoint();
await homeProviderInit.getValidEndpoints();
// await configBox.delete('isCacheChecked');
if (configBox.get('isCacheChecked') == null) {
configBox.put('isCacheChecked', false);
}
// log.d(await configBox.get('endpoint'));
// var connectivityResult =
// await (Connectivity().checkConnectivity());
// if (connectivityResult != ConnectivityResult.mobile &&
// connectivityResult != ConnectivityResult.wifi) {
// homeProvider.changeMessage(
// "notConnectedToInternet".tr(), 0);
// sub.nodeConnected = false;
// }
// Améliore ce code car il y a un bug: parfois l'app se croit hors ligne, alors que c'est faux, le téléphone est bien connecté à internet
// (GPT vscode extension fixed it for my...)
HomeProvider homeProvider =
Provider.of<HomeProvider>(context, listen: false);
Connectivity()
.onConnectivityChanged
.listen((ConnectivityResult result) async {
log.d('Network changed: $result');
if (result == ConnectivityResult.none) {
sub.nodeConnected = false;
await sub.sdk.api.setting.unsubscribeBestNumber();
homeProvider.changeMessage("notConnectedToInternet".tr(), 0);
sub.reload();
} else {
// Check if the phone is actually connected to the internet
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult != ConnectivityResult.none) {
await sub.connectNode(context);
// Currency parameters
await sub.initCurrencyParameters();
// Indexer Blockchain start
getBlockStart();
}
}
});
// await sub.connectNode(ctx);
}
// _duniterIndexer.checkIndexerEndpointBackground();
});
super.initState();
}
@override
Widget build(BuildContext context) {
homeContext = context;
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
MyWalletsProvider myWalletProvider =
Provider.of<MyWalletsProvider>(context);
Provider.of<ChestProvider>(context);
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final myWalletProvider = Provider.of<MyWalletsProvider>(context);
Provider.of<ChestProvider>(context);
final bool isWalletsExists = myWalletProvider.checkIfWalletExist();
isTall = false;
@ -47,148 +143,85 @@ class HomeScreen extends StatelessWidget {
ratio = 1.125;
}
return Scaffold(
resizeToAvoidBottomInset: false,
drawer: Drawer(
child: Column(
children: <Widget>[
Expanded(
child: ListView(padding: EdgeInsets.zero, children: <Widget>[
DrawerHeader(
decoration: const BoxDecoration(
color: orangeC,
resizeToAvoidBottomInset: false,
drawer: Drawer(
child: Column(
children: <Widget>[
Expanded(
child: ListView(padding: EdgeInsets.zero, children: <Widget>[
DrawerHeader(
decoration: const BoxDecoration(
color: orangeC,
),
child: Column(children: const <Widget>[
SizedBox(height: 0),
Image(
image: AssetImage('assets/icon/gecko_final.png'),
height: 130),
]),
),
child: Column(children: const <Widget>[
SizedBox(height: 0),
Image(
image: AssetImage('assets/icon/gecko_final.png'),
height: 130),
]),
),
ListTile(
key: keyParameters,
title: Text('parameters'.tr()),
onTap: () {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return SettingsScreen();
}),
);
},
),
ListTile(
key: keyContacts,
title: Text('contactsManagement'.tr()),
onTap: () {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const ContactsScreen();
}),
);
},
),
])),
Align(
ListTile(
key: keyParameters,
title: Text('parameters'.tr()),
onTap: () {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return SettingsScreen();
}),
);
},
),
if (isWalletsExists)
ListTile(
key: keyContacts,
title: Text('contactsManagement'.tr()),
onTap: () {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const ContactsScreen();
}),
);
},
),
])),
Align(
alignment: FractionalOffset.bottomCenter,
child: Text('Ğecko v$appVersion')),
const SizedBox(height: 20)
],
child: InkWell(
key: keyCopyAddress,
splashColor: orangeC,
child: Padding(
padding: const EdgeInsets.all(20),
child: Text('Ğecko v$appVersion')),
onTap: () {
Clipboard.setData(
ClipboardData(text: 'Ğecko v$appVersion'));
snackMessage(context,
message:
'Le numéro de version de Ğecko a été copié dans votre presse papier',
duration: 4);
}),
),
const SizedBox(height: 20)
],
),
),
),
// bottomNavigationBar: _homeProvider.bottomBar(context, 1),
backgroundColor: const Color(0xffF9F9F1),
body: Builder(
builder: (ctx) => StatefulWrapper(
onInit: () {
WidgetsBinding.instance.addPostFrameCallback((_) async {
DuniterIndexer duniterIndexer =
Provider.of<DuniterIndexer>(ctx, listen: false);
duniterIndexer.getValidIndexerEndpoint();
if (!sub.sdkReady && !sub.sdkLoading) await sub.initApi();
if (sub.sdkReady && !sub.nodeConnected) {
// Check if versionData non compatible, drop everything
if (walletBox.isNotEmpty &&
walletBox.getAt(0)!.version! < dataVersion) {
await infoPopup(
context, "chestNotCompatibleMustReinstallGecko".tr());
await walletBox.clear();
await chestBox.clear();
await configBox.delete('defaultWallet');
await sub.deleteAllAccounts();
myWalletProvider.reload();
}
// var connectivityResult =
// await (Connectivity().checkConnectivity());
// if (connectivityResult != ConnectivityResult.mobile &&
// connectivityResult != ConnectivityResult.wifi) {
// homeProvider.changeMessage(
// "notConnectedToInternet".tr(), 0);
// sub.nodeConnected = false;
// }
// TODO: fix random bad network status on startup
HomeProvider homeProvider =
Provider.of<HomeProvider>(ctx, listen: false);
Connectivity()
.onConnectivityChanged
.listen((ConnectivityResult result) async {
log.d('Network changed: $result');
if (result == ConnectivityResult.none) {
sub.nodeConnected = false;
await sub.sdk.api.setting.unsubscribeBestNumber();
homeProvider.changeMessage(
"notConnectedToInternet".tr(), 0);
sub.reload();
} else {
await sub.connectNode(ctx);
}
});
// await sub.connectNode(ctx);
}
// _duniterIndexer.checkIndexerEndpointBackground();
});
},
child: isWalletsExists ? geckHome(context) : welcomeHome(context)
// bottomNavigationBar: BottomNavigationBar(
// backgroundColor: backgroundColor,
// fixedColor: Colors.grey[850],
// unselectedItemColor: const Color(0xffBD935C),
// type: BottomNavigationBarType.fixed,
// onTap: (index) {
// _homeProvider.currentIndex = index;
// },
// currentIndex: _homeProvider.currentIndex,
// items: [
// BottomNavigationBarItem(
// icon: Image.asset('assets/block-space-disabled.png', height: 26),
// activeIcon: Image.asset('assets/blockchain.png', height: 26),
// label: 'Explorateur',
// ),
// const BottomNavigationBarItem(
// icon: Icon(Icons.lock),
// label: 'Mes portefeuilles',
// ),
// ],
// ),
),
),
);
backgroundColor: const Color(0xffF9F9F1),
body: isWalletsExists ? geckHome(context) : welcomeHome(context));
}
}
Widget geckHome(context) {
MyWalletsProvider myWalletProvider = Provider.of<MyWalletsProvider>(context);
final myWalletProvider = Provider.of<MyWalletsProvider>(context);
final homeProvider = Provider.of<HomeProvider>(context, listen: false);
Provider.of<ChestProvider>(context);
WalletsProfilesProvider historyProvider =
Provider.of<WalletsProfilesProvider>(context);
final double statusBarHeight = MediaQuery.of(context).padding.top;
final statusBarHeight = MediaQuery.of(context).padding.top;
return Container(
decoration: const BoxDecoration(
image: DecorationImage(
@ -330,42 +363,47 @@ Widget geckHome(context) {
child: ClipOval(
key: keyOpenWalletsHomme,
child: Material(
color: orangeC, // button color
color: homeProvider.isWalletBoxInit
? orangeC
: Colors.grey[500], // button color
child: InkWell(
onTap: !homeProvider.isWalletBoxInit
? null
: () async {
WalletData? defaultWallet =
myWalletProvider.getDefaultWallet();
String? pin;
if (myWalletProvider.pinCode == '') {
pin = await Navigator.push(
context,
MaterialPageRoute(
builder: (homeContext) {
return UnlockingWallet(
wallet: defaultWallet);
},
),
);
}
if (pin != null ||
myWalletProvider.pinCode != '') {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const WalletsHome();
}),
);
}
// log.d(_myWalletProvider.pinCode);
// Navigator.pushNamed(
// context, '/mywallets')));
},
child: Padding(
padding: const EdgeInsets.all(18),
child: Image(
image: const AssetImage(
'assets/home/wallet.png'),
height: 68 * ratio)),
onTap: () async {
WalletData? defaultWallet =
myWalletProvider.getDefaultWallet();
String? pin;
if (myWalletProvider.pinCode == '') {
pin = await Navigator.push(
context,
MaterialPageRoute(
builder: (homeContext) {
return UnlockingWallet(
wallet: defaultWallet);
},
),
);
}
if (pin != null || myWalletProvider.pinCode != '') {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const WalletsHome();
}),
);
}
// log.d(_myWalletProvider.pinCode);
// Navigator.pushNamed(
// context, '/mywallets')));
}),
height: 68 * ratio))),
),
),
),
@ -434,7 +472,7 @@ Widget geckHome(context) {
}
Widget welcomeHome(context) {
final double statusBarHeight = MediaQuery.of(context).padding.top;
final statusBarHeight = MediaQuery.of(context).padding.top;
return Container(
decoration: const BoxDecoration(

View File

@ -3,9 +3,8 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:durt/durt.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/stateful_wrapper.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
@ -13,7 +12,7 @@ import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:provider/provider.dart';
class ChangePinScreen extends StatelessWidget with ChangeNotifier {
class ChangePinScreen extends StatefulWidget with ChangeNotifier {
ChangePinScreen(
{Key? keyMyWallets,
required this.walletName,
@ -22,13 +21,23 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
final String? walletName;
final MyWalletsProvider walletProvider;
@override
State<ChangePinScreen> createState() => _ChangePinScreenState();
}
class _ChangePinScreenState extends State<ChangePinScreen> {
final TextEditingController newPin = TextEditingController();
@override
void initState() {
newPin.text = randomSecretCode(pinLength);
super.initState();
}
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
MyWalletsProvider myWalletProvider =
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
return WillPopScope(
@ -49,18 +58,12 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
}),
title: SizedBox(
height: 22,
child: Text(walletName!),
child: Text(widget.walletName!),
),
),
body: Center(
child: SafeArea(
child: Column(children: <Widget>[
StatefulWrapper(
onInit: () {
newPin.text = randomSecretCode(pinLength);
},
child: Container(),
),
const SizedBox(height: 80),
Text(
'choosePassword'.tr(),
@ -118,9 +121,9 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
);
}
if (pin != null || myWalletProvider.pinCode != '') {
await sub.changePassword(context, defaultWallet.address!,
walletProvider.pinCode, newPin.text);
walletProvider.pinCode = newPin.text;
await sub.changePassword(context, defaultWallet.address,
widget.walletProvider.pinCode, newPin.text);
widget.walletProvider.pinCode = newPin.text;
newPin.text = '';
Navigator.pop(context);
}

View File

@ -4,18 +4,17 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:flutter/services.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/chest_provider.dart';
import 'package:gecko/providers/home.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/myWallets/change_pin.dart';
import 'package:gecko/screens/myWallets/custom_derivations.dart';
import 'package:gecko/screens/myWallets/show_seed.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:gecko/widgets/bottom_app_bar.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
import 'package:provider/provider.dart';
class ChestOptions extends StatelessWidget {
@ -25,11 +24,7 @@ class ChestOptions extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
ChestProvider chestProvider =
Provider.of<ChestProvider>(context, listen: false);
HomeProvider homeProvider =
Provider.of<HomeProvider>(context, listen: false);
final chestProvider = Provider.of<ChestProvider>(context, listen: false);
ChestData currentChest = chestBox.get(configBox.get('currentChest'))!;
@ -52,7 +47,7 @@ class ChestOptions extends StatelessWidget {
height: 22,
child: Text(currentChest.name!),
)),
bottomNavigationBar: homeProvider.bottomAppBar(context),
bottomNavigationBar: const GeckoBottomAppBar(),
body: Stack(children: [
Builder(
builder: (ctx) => SafeArea(
@ -61,7 +56,7 @@ class ChestOptions extends StatelessWidget {
InkWell(
key: keyShowSeed,
onTap: () async {
MyWalletsProvider myWalletProvider =
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
WalletData? defaultWallet =
myWalletProvider.getDefaultWallet();
@ -110,26 +105,27 @@ class ChestOptions extends StatelessWidget {
Consumer<SubstrateSdk>(builder: (context, sub, _) {
return InkWell(
key: keyChangePin,
onTap: sub.nodeConnected
? () async {
// await _chestProvider.changePin(context, cesiumWallet);
String? pinResult = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return ChangePinScreen(
walletName: currentChest.name,
walletProvider: walletProvider,
);
},
),
);
onTap: null,
// sub.nodeConnected
// ? () async {
// // await _chestProvider.changePin(context, cesiumWallet);
// String? pinResult = await Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) {
// return ChangePinScreen(
// walletName: currentChest.name,
// walletProvider: walletProvider,
// );
// },
// ),
// );
if (pinResult != null) {
walletProvider.pinCode = pinResult;
}
}
: null,
// if (pinResult != null) {
// walletProvider.pinCode = pinResult;
// }
// }
// : null,
child: SizedBox(
height: 50,
child: Row(children: <Widget>[
@ -144,7 +140,7 @@ class ChestOptions extends StatelessWidget {
style: TextStyle(
fontSize: 20,
color: sub.nodeConnected
? Colors.black
? Colors.grey[500]
: Colors.grey[500]),
),
])),
@ -215,7 +211,7 @@ class ChestOptions extends StatelessWidget {
]),
),
),
CommonElements().offlineInfo(context),
const OfflineInfo(),
]),
);
}

View File

@ -1,7 +1,7 @@
// 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:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/my_wallets.dart';
@ -30,9 +30,7 @@ class _ChooseChestState extends State<ChooseChest> {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
MyWalletsProvider myWalletProvider =
Provider.of<MyWalletsProvider>(context);
final myWalletProvider = Provider.of<MyWalletsProvider>(context);
return Scaffold(
backgroundColor: backgroundColor,

View File

@ -3,15 +3,15 @@
import 'dart:io';
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/wallet_data.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/screens/myWallets/wallets_home.dart';
import 'package:gecko/widgets/balance.dart';
import 'package:provider/provider.dart';
// import 'package:gecko/models/home.dart';
// import 'package:provider/provider.dart';
@ -23,8 +23,7 @@ class ChooseWalletScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final int chest = configBox.get('currentChest');
return Scaffold(
@ -73,9 +72,7 @@ class ChooseWalletScreen extends StatelessWidget {
}
Widget myWalletsTiles(BuildContext context, int currentChest) {
MyWalletsProvider myWalletProvider =
Provider.of<MyWalletsProvider>(context);
// SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
final myWalletProvider = Provider.of<MyWalletsProvider>(context);
final bool isWalletsExists = myWalletProvider.checkIfWalletExist();
WalletData? defaultWallet = myWalletProvider.getDefaultWallet();
@ -97,8 +94,11 @@ class ChooseWalletScreen extends StatelessWidget {
]);
}
List listWallets = myWalletProvider.listWallets;
final double screenWidth = MediaQuery.of(context).size.width;
List<WalletData> listWallets = myWalletProvider.listWallets;
listWallets.sort((p1, p2) {
return Comparable.compare(p1.number!, p2.number!);
});
final screenWidth = MediaQuery.of(context).size.width;
int nTule = 2;
if (screenWidth >= 900) {
@ -116,11 +116,11 @@ class ChooseWalletScreen extends StatelessWidget {
crossAxisSpacing: 0,
mainAxisSpacing: 0,
children: <Widget>[
for (WalletData repository in listWallets as Iterable<WalletData>)
for (WalletData repository in listWallets)
Padding(
padding: const EdgeInsets.all(16),
child: GestureDetector(
key: keySelectThisWallet(repository.address!),
key: keySelectThisWallet(repository.address),
onTap: () {
selectedWallet = repository;
myWalletProvider.reload();
@ -169,8 +169,8 @@ class ChooseWalletScreen extends StatelessWidget {
),
),
)),
balanceBuilder(context, repository.address!,
selectedWallet!.address == repository.address!),
balanceBuilder(context, repository.address,
selectedWallet!.address == repository.address),
ListTile(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
@ -225,8 +225,10 @@ class ChooseWalletScreen extends StatelessWidget {
// style: TextStyle(color: isDefault ? Colors.white : Colors.black),
// ),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
balance(
context, address, 16, isDefault ? Colors.white : Colors.black),
Balance(
address: address,
size: 16,
color: isDefault ? Colors.white : Colors.black),
])
]),
),

View File

@ -1,7 +1,7 @@
// 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/wallet_data.dart';
@ -27,8 +27,7 @@ class _CustomDerivationState extends State<CustomDerivation> {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
MyWalletsProvider myWalletProvider =
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
final derivationList = <String>[
@ -130,7 +129,7 @@ class _CustomDerivationState extends State<CustomDerivation> {
'${'wallet'.tr()} ${myWalletProvider.listWallets.last.number! + 2}';
if (dropdownValue == 'root') {
await myWalletProvider.generateRootWallet(
context, 'Portefeuille racine');
context, 'rootWallet'.tr());
} else {
await myWalletProvider.generateNewDerivation(
context,

View File

@ -4,16 +4,18 @@ import 'dart:async';
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/wallet_data.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:gecko/screens/transaction_in_progress.dart';
import 'package:gecko/widgets/certifications.dart';
import 'package:gecko/widgets/idty_status.dart';
import 'package:provider/provider.dart';
class ImportG1v1 extends StatelessWidget {
@ -21,10 +23,7 @@ class ImportG1v1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
WalletOptionsProvider walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
MyWalletsProvider myWalletProvider =
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
Timer? debounce;
@ -57,7 +56,7 @@ class ImportG1v1 extends StatelessWidget {
child: Consumer<SubstrateSdk>(builder: (context, sub, _) {
return FutureBuilder(
future: sub.getBalanceAndIdtyStatus(
sub.g1V1NewAddress, selectedWallet.address!),
sub.g1V1NewAddress, selectedWallet.address),
builder: (BuildContext context, AsyncSnapshot<List> status) {
// log.d(_certs.data);
@ -83,6 +82,7 @@ class ImportG1v1 extends StatelessWidget {
final String idtyStatus = status.data?[1];
final String myIdtyStatus = status.data?[2];
final bool hasConsumer = status.data?[3] ?? false;
final bool isSmith = status.data?[4] ?? false;
// log.d('hasconsumer: $hasConsumer');
@ -92,7 +92,7 @@ class ImportG1v1 extends StatelessWidget {
} else {
canValidate = false;
validationStatus = hasConsumer
? 'youMustWaitBeforeCashoutThisAccount'.tr(args: ['X'])
? 'youMustWaitBeforeCashoutThisAccount'.tr()
: 'thisAccountIsEmpty'.tr();
}
@ -102,6 +102,11 @@ class ImportG1v1 extends StatelessWidget {
'youCannotMigrateIdentityToExistingIdentity'.tr();
}
if (isSmith) {
canValidate = false;
validationStatus = 'smithCantMigrateIdentity'.tr();
}
if (sub.g1V1NewAddress == '') {
validationStatus = '';
}
@ -185,13 +190,13 @@ class ImportG1v1 extends StatelessWidget {
key: keyCopyAddress,
onTap: () {
Clipboard.setData(
ClipboardData(text: sub.g1V1NewAddress));
ClipboardData(text: sub.g1V1OldPubkey));
snackCopyKey(context);
},
child: Text(
getShortPubkey(sub.g1V1NewAddress),
sub.g1V1OldPubkey,
style: const TextStyle(
fontSize: 20,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
@ -204,10 +209,12 @@ class ImportG1v1 extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
walletOptions.idtyStatus(context, sub.g1V1NewAddress,
isOwner: false, color: Colors.black),
IdentityStatus(
address: sub.g1V1NewAddress,
isOwner: false,
color: Colors.black),
const SizedBox(width: 10),
getCerts(context, sub.g1V1NewAddress, 14)
Certifications(address: sub.g1V1NewAddress, size: 14)
],
),
const SizedBox(height: 30),
@ -221,7 +228,7 @@ class ImportG1v1 extends StatelessWidget {
icon: const Icon(Icons.keyboard_arrow_down),
items: myWalletProvider.listWallets.map((wallet) {
return DropdownMenuItem(
key: keySelectThisWallet(wallet.address!),
key: keySelectThisWallet(wallet.address),
value: wallet,
child: Text(
wallet.name!,
@ -263,10 +270,8 @@ class ImportG1v1 extends StatelessWidget {
);
}
sub.migrateCsToV2(
sub.csSalt.text,
sub.csPassword.text,
selectedWallet.address!,
sub.migrateCsToV2(sub.csSalt.text,
sub.csPassword.text, selectedWallet.address,
destPassword:
pin ?? myWalletProvider.pinCode,
balance: balance,
@ -279,7 +284,7 @@ class ImportG1v1 extends StatelessWidget {
fromAddress:
getShortPubkey(sub.g1V1NewAddress),
toAddress: getShortPubkey(
selectedWallet.address!));
selectedWallet.address));
}),
);
resetScreen(context);
@ -308,7 +313,7 @@ class ImportG1v1 extends StatelessWidget {
}
void resetScreen(BuildContext context) {
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
sub.csSalt.text = '';
sub.csPassword.text = '';

View File

@ -1,14 +1,14 @@
// 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/wallet_data.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/widgets/commons/common_elements.dart';
import 'package:gecko/screens/myWallets/migrate_identity.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:gecko/screens/transaction_in_progress.dart';
@ -27,7 +27,6 @@ class ManageMembership extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
final sub = Provider.of<SubstrateSdk>(context);
return Scaffold(
@ -116,9 +115,9 @@ class ManageMembership extends StatelessWidget {
false;
if (answer) {
MyWalletsProvider myWalletProvider =
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
// MyWalletsProvider mw = MyWalletsProvider();
// final wallet = mw.getWalletDataByAddress(address);

View File

@ -1,7 +1,7 @@
// ignore_for_file: use_build_context_synchronously
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
@ -20,14 +20,12 @@ class MigrateIdentityScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
// HomeProvider _homeProvider = Provider.of<HomeProvider>(context);
WalletOptionsProvider walletOptions =
// final _homeProvider = Provider.of<HomeProvider>(context);
final walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
MyWalletsProvider myWalletProvider =
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
DuniterIndexer duniterIndexer =
Provider.of<DuniterIndexer>(context, listen: false);
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
final fromAddress = walletOptions.address.text;
final defaultWallet = myWalletProvider.getDefaultWallet();
@ -77,7 +75,7 @@ class MigrateIdentityScreen extends StatelessWidget {
child: Consumer<SubstrateSdk>(builder: (context, sub, _) {
return FutureBuilder(
future: sub.getBalanceAndIdtyStatus(
fromAddress, selectedWallet.address!),
fromAddress, selectedWallet.address),
builder: (BuildContext context, AsyncSnapshot<List> status) {
if (status.data == null) {
return Column(children: [
@ -103,12 +101,21 @@ class MigrateIdentityScreen extends StatelessWidget {
final String idtyStatus = status.data?[1];
final String myIdtyStatus = status.data?[2];
final bool hasConsumer = status.data?[3] ?? false;
final bool isSmith = status.data?[4] ?? false;
// log.d('hasconsumer: $hasConsumer');
if (balance['transferableBalance'] != 0 && !hasConsumer) {
if (isSmith) {
canValidate = false;
validationStatus = 'smithCantMigrateIdentity'.tr();
} else if (balance['transferableBalance'] != 0 &&
!hasConsumer) {
canValidate = true;
validationStatus = '';
} else if (idtyStatus != 'noid' && myIdtyStatus != 'noid') {
canValidate = false;
validationStatus =
'youCannotMigrateIdentityToExistingIdentity'.tr();
} else {
canValidate = false;
validationStatus = hasConsumer
@ -116,14 +123,8 @@ class MigrateIdentityScreen extends StatelessWidget {
: 'thisAccountIsEmpty'.tr();
}
if (idtyStatus != 'noid' && myIdtyStatus != 'noid') {
canValidate = false;
validationStatus =
'youCannotMigrateIdentityToExistingIdentity'.tr();
}
log.d(
'tatatata: ${sub.g1V1NewAddress}, ${selectedWallet.address!}, $balance, $idtyStatus, $myIdtyStatus');
'tatatata: ${sub.g1V1NewAddress}, ${selectedWallet.address}, $balance, $idtyStatus, $myIdtyStatus');
final walletsList = myWalletProvider.listWallets.toList();
@ -176,7 +177,7 @@ class MigrateIdentityScreen extends StatelessWidget {
icon: const Icon(Icons.keyboard_arrow_down),
items: walletsList.map((wallet) {
return DropdownMenuItem(
key: keySelectThisWallet(wallet.address!),
key: keySelectThisWallet(wallet.address),
value: wallet,
child: Text(
wallet.name!,
@ -221,7 +222,7 @@ class MigrateIdentityScreen extends StatelessWidget {
sub.migrateIdentity(
fromAddress: fromAddress,
destAddress: selectedWallet.address!,
destAddress: selectedWallet.address,
fromPassword: pin ?? myWalletProvider.pinCode,
destPassword: pin ?? myWalletProvider.pinCode,
withBalance: true,
@ -233,7 +234,7 @@ class MigrateIdentityScreen extends StatelessWidget {
transType: 'identityMigration',
fromAddress: getShortPubkey(fromAddress),
toAddress: getShortPubkey(
selectedWallet.address!));
selectedWallet.address));
}),
);
}

View File

@ -1,14 +1,17 @@
// ignore_for_file: use_build_context_synchronously
import 'package:bubble/bubble.dart';
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/generate_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/7.dart';
import 'package:gecko/screens/onBoarding/9.dart';
import 'package:gecko/widgets/commons/fader_transition.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
import 'package:provider/provider.dart';
// import 'package:gecko/models/home.dart';
// import 'package:provider/provider.dart';
@ -19,10 +22,8 @@ class RestoreChest extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GenerateWalletsProvider genW =
Provider.of<GenerateWalletsProvider>(context, listen: false);
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final genW = Provider.of<GenerateWalletsProvider>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
genW.actualWallet = null;
if (genW.isSentenceComplete(context)) {
@ -157,7 +158,7 @@ class RestoreChest extends StatelessWidget {
)
])
]),
CommonElements().offlineInfo(context),
const OfflineInfo(),
]),
),
),
@ -183,7 +184,7 @@ class RestoreChest extends StatelessWidget {
}
Widget arrayCell(BuildContext context, TextEditingController cellCtl) {
GenerateWalletsProvider generateWalletProvider =
final generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
return Container(

View File

@ -1,12 +1,14 @@
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/wallet_data.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/widgets/commons/build_text.dart';
import 'package:pdf/pdf.dart';
import 'package:printing/printing.dart';
import 'package:provider/provider.dart';
@ -23,12 +25,9 @@ class ShowSeed extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
MyWalletsProvider myWalletProvider =
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
CommonElements common = CommonElements();
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
WalletData defaultWallet = myWalletProvider.getDefaultWallet();
@ -45,7 +44,7 @@ class ShowSeed extends StatelessWidget {
const Spacer(flex: 1),
FutureBuilder(
future:
sub.getSeed(defaultWallet.address!, walletProvider.pinCode),
sub.getSeed(defaultWallet.address, walletProvider.pinCode),
builder: (BuildContext context, AsyncSnapshot<String?> seed) {
if (seed.connectionState != ConnectionState.done ||
seed.hasError) {
@ -65,7 +64,7 @@ class ShowSeed extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(children: [
common.buildText('keepYourMnemonicSecret'.tr()),
BuildText(text: 'keepYourMnemonicSecret'.tr()),
SizedBox(height: 35 * ratio),
sentanceArray(context, seed.data!.split(' ')),
const SizedBox(height: 20),
@ -83,7 +82,7 @@ class ShowSeed extends StatelessWidget {
onPressed: () {
Clipboard.setData(
ClipboardData(text: seed.data));
snackCopyKey(context);
snackCopySeed(context);
},
child: Row(children: <Widget>[
Image.asset(
@ -141,16 +140,6 @@ class ShowSeed extends StatelessWidget {
));
}
snackCopyKey(context) {
const snackBar = SnackBar(
padding: EdgeInsets.all(20),
content: Text(
"Votre phrase de restauration a été copié dans votre presse-papier.",
style: TextStyle(fontSize: 16)),
duration: Duration(seconds: 2));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
Widget sentanceArray(BuildContext context, List mnemonic) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 3),

View File

@ -3,7 +3,7 @@
import 'dart:async';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/substrate_sdk.dart';
@ -11,7 +11,7 @@ import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:flutter/material.dart';
import 'package:gecko/screens/myWallets/choose_chest.dart';
// import 'package:gecko/screens/myWallets/choose_chest.dart';
import 'package:pin_code_fields/pin_code_fields.dart';
import 'package:provider/provider.dart';
import 'package:gecko/globals.dart';
@ -22,6 +22,8 @@ class UnlockingWallet extends StatelessWidget {
late int currentChestNumber;
late ChestData currentChest;
bool canUnlock = true;
TextEditingController enterPin = TextEditingController();
FocusNode pinFocus = FocusNode(debugLabel: 'pinFocusNode');
// ignore: close_sinks
StreamController<ErrorAnimationType>? errorController;
@ -30,10 +32,10 @@ class UnlockingWallet extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
WalletOptionsProvider walletOptions =
Provider.of<WalletOptionsProvider>(context);
// final double statusBarHeight = MediaQuery.of(context).padding.top;
final walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
currentChestNumber = configBox.get('currentChest');
currentChest = chestBox.get(currentChestNumber)!;
@ -41,154 +43,168 @@ class UnlockingWallet extends StatelessWidget {
int pinLenght = walletOptions.getPinLenght(wallet.number);
errorController = StreamController<ErrorAnimationType>();
return Scaffold(
backgroundColor: backgroundColor,
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Stack(children: <Widget>[
Positioned(
top: 10, //statusBarHeight + 10,
left: 15,
child: Builder(
builder: (context) => IconButton(
key: keyPopButton,
icon: const Icon(
Icons.arrow_back,
color: Colors.black,
size: 30,
// if (enterPin.text == '') myWalletProvider.isPinLoading = true;
return WillPopScope(
onWillPop: () {
myWalletProvider.isPinValid = false;
myWalletProvider.isPinLoading = true;
return Future<bool>.value(true);
},
child: Scaffold(
backgroundColor: backgroundColor,
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Stack(children: <Widget>[
Positioned(
top: 10, //statusBarHeight + 10,
left: 15,
child: Builder(
builder: (context) => IconButton(
key: keyPopButton,
icon: const Icon(
Icons.arrow_back,
color: Colors.black,
size: 30,
),
onPressed: () {
myWalletProvider.isPinValid = false;
myWalletProvider.isPinLoading = true;
Navigator.pop(context);
},
),
onPressed: () => Navigator.pop(context),
),
),
),
Column(children: <Widget>[
SizedBox(height: isTall ? 100 : 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
currentChest.imageFile == null
? Image.asset(
'assets/chests/${currentChest.imageName}',
width: isTall ? 130 : 100,
)
: Image.file(
currentChest.imageFile!,
width: isTall ? 130 : 100,
),
const SizedBox(width: 5),
SizedBox(
width: 250,
child: Text(
currentChest.name!,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 25,
color: Colors.black,
fontWeight: FontWeight.w700),
)),
]),
SizedBox(height: 30 * ratio),
SizedBox(
width: 400,
child: Text(
'toUnlockEnterPassword'.tr(),
style: const TextStyle(
fontSize: 19,
color: Colors.black,
fontWeight: FontWeight.w400),
)),
SizedBox(height: 40 * ratio),
pinForm(context, pinLenght),
SizedBox(height: 3 * ratio),
if (canUnlock)
InkWell(
key: keyCachePassword,
onTap: () {
walletOptions.changePinCacheChoice();
},
child: Row(children: [
const SizedBox(height: 30),
const Spacer(),
Icon(
configBox.get('isCacheChecked')
? Icons.check_box
: Icons.check_box_outline_blank,
color: orangeC,
),
const SizedBox(width: 8),
Text(
'rememberPassword'.tr(),
style: TextStyle(
fontSize: 16, color: Colors.grey[700]),
),
const Spacer()
]),
),
const SizedBox(height: 10),
// if (canUnlock)
InkWell(
key: keyChangeChest,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const ChooseChest();
}),
);
},
child: SizedBox(
Column(children: <Widget>[
SizedBox(height: isTall ? 100 : 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
currentChest.imageFile == null
? Image.asset(
'assets/chests/${currentChest.imageName}',
width: isTall ? 130 : 100,
)
: Image.file(
currentChest.imageFile!,
width: isTall ? 130 : 100,
),
const SizedBox(width: 5),
SizedBox(
width: 250,
child: Text(
currentChest.name!,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 25,
color: Colors.black,
fontWeight: FontWeight.w700),
)),
]),
SizedBox(height: 30 * ratio),
SizedBox(
width: 400,
height: 50,
child: Center(
child: Text(
'changeChest'.tr(),
style: const TextStyle(
fontSize: 22,
color: orangeC,
fontWeight: FontWeight.w600),
child: Text(
'toUnlockEnterPassword'.tr(),
style: const TextStyle(
fontSize: 19,
color: Colors.black,
fontWeight: FontWeight.w400),
)),
SizedBox(height: 30 * ratio),
if (!myWalletProvider.isPinValid &&
!myWalletProvider.isPinLoading)
Text(
"thisIsNotAGoodCode".tr(),
style: const TextStyle(
color: Colors.red, fontWeight: FontWeight.w500),
),
SizedBox(height: 10 * ratio),
pinForm(context, pinLenght),
SizedBox(height: 3 * ratio),
if (canUnlock)
Consumer<WalletOptionsProvider>(
builder: (context, sub, _) {
return InkWell(
key: keyCachePassword,
onTap: () {
walletOptions.changePinCacheChoice();
},
child: Row(children: [
const SizedBox(height: 30),
const Spacer(),
Icon(
configBox.get('isCacheChecked')
? Icons.check_box
: Icons.check_box_outline_blank,
color: orangeC,
),
const SizedBox(width: 8),
Text(
'rememberPassword'.tr(),
style: TextStyle(
fontSize: 16, color: Colors.grey[700]),
),
const Spacer()
]),
);
}),
const SizedBox(height: 10),
// if (canUnlock)
InkWell(
key: keyChangeChest,
onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) {
// return const ChooseChest();
// }),
// );
},
child: SizedBox(
width: 400,
height: 50,
child: Center(
child: Text(
'changeChest'.tr(),
style: const TextStyle(
fontSize: 22,
color: Colors.grey, // orangeC
fontWeight: FontWeight.w600),
),
),
),
)),
)),
]),
]),
]),
]),
));
)),
);
}
Widget pinForm(context, pinLenght) {
// var _walletPin = '';
// ignore: close_sinks
StreamController<ErrorAnimationType> errorController =
StreamController<ErrorAnimationType>();
TextEditingController enterPin = TextEditingController();
WalletOptionsProvider walletOptions =
Provider.of<WalletOptionsProvider>(context);
MyWalletsProvider myWalletProvider =
Provider.of<MyWalletsProvider>(context);
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
FocusNode pinFocus = FocusNode();
final myWalletProvider = Provider.of<MyWalletsProvider>(context);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
WalletData defaultWallet = myWalletProvider.getDefaultWallet();
// defaultWallet.address = null;
if (defaultWallet.address == null) {
canUnlock = false;
return Text(
'Impossible de retrouver votre\nportefeuille par défaut.\nID: ${defaultWallet.id()}',
textAlign: TextAlign.center,
style: const TextStyle(
color: Colors.redAccent, fontWeight: FontWeight.w500),
);
}
// if (defaultWallet.address == null) {
// canUnlock = false;
// return Text(
// 'Impossible de retrouver votre\nportefeuille par défaut.\nID: ${defaultWallet.id()}',
// textAlign: TextAlign.center,
// style: const TextStyle(
// color: Colors.redAccent, fontWeight: FontWeight.w500),
// );
// }
return Form(
// key: keyPinForm,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 5 * ratio, horizontal: 30),
child: PinCodeTextField(
key: keyPinForm,
textCapitalization: TextCapitalization.characters,
focusNode: pinFocus,
autoFocus: true,
appContext: context,
@ -199,7 +215,8 @@ class UnlockingWallet extends StatelessWidget {
length: pinLenght,
obscureText: true,
obscuringCharacter: '*',
animationType: AnimationType.fade,
animationType: AnimationType.slide,
animationDuration: const Duration(milliseconds: 40),
validator: (v) {
if (v!.length < pinLenght) {
return "yourPasswordLengthIsX".tr(args: [pinLenght.toString()]);
@ -218,11 +235,9 @@ class UnlockingWallet extends StatelessWidget {
),
showCursor: kDebugMode ? false : true,
cursorColor: Colors.black,
animationDuration: const Duration(milliseconds: 300),
textStyle: const TextStyle(fontSize: 20, height: 1.6),
textStyle: const TextStyle(fontSize: 27, height: 1.6),
backgroundColor: const Color(0xffF9F9F1),
enableActiveFill: false,
errorAnimationController: errorController,
controller: enterPin,
keyboardType: TextInputType.visiblePassword,
boxShadows: const [
@ -233,28 +248,32 @@ class UnlockingWallet extends StatelessWidget {
)
],
onCompleted: (pin) async {
myWalletProvider.isPinLoading = true;
myWalletProvider.pinCode = pin.toUpperCase();
final isValid = await sub.checkPassword(
defaultWallet.address!, pin.toUpperCase());
defaultWallet.address, pin.toUpperCase());
if (!isValid) {
await Future.delayed(const Duration(milliseconds: 50));
errorController.add(ErrorAnimationType
.shake); // Triggering error shake animation
await Future.delayed(const Duration(milliseconds: 20));
pinColor = Colors.red[600];
myWalletProvider.isPinLoading = false;
myWalletProvider.isPinValid = false;
myWalletProvider.pinCode = myWalletProvider.mnemonic = '';
walletOptions.reload();
enterPin.text = '';
pinFocus.requestFocus();
} else {
myWalletProvider.isPinValid = true;
myWalletProvider.isPinLoading = false;
pinColor = Colors.green[400];
myWalletProvider.resetPinCode();
Navigator.pop(context, pin.toUpperCase());
}
},
onChanged: (value) {
if (enterPin.text != '') myWalletProvider.isPinLoading = true;
if (pinColor != const Color(0xFFA4B600)) {
pinColor = const Color(0xFFA4B600);
}
myWalletProvider.reload();
},
)),
);

View File

@ -2,21 +2,28 @@ import 'dart:async';
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/home.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/certifications.dart';
import 'package:gecko/screens/activity.dart';
import 'package:gecko/screens/myWallets/manage_membership.dart';
import 'package:gecko/screens/qrcode_fullscreen.dart';
import 'package:gecko/widgets/balance.dart';
import 'package:gecko/widgets/bottom_app_bar.dart';
import 'package:gecko/widgets/certifications.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
import 'package:gecko/widgets/idty_status.dart';
import 'package:gecko/widgets/name_by_address.dart';
import 'package:gecko/widgets/page_route_no_transition.dart';
import 'package:provider/provider.dart';
import 'package:flutter/services.dart';
import 'package:qr_flutter/qr_flutter.dart';
class WalletOptions extends StatelessWidget {
@ -26,25 +33,24 @@ class WalletOptions extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
WalletOptionsProvider walletOptions =
final walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
WalletsProfilesProvider historyProvider =
Provider.of<WalletsProfilesProvider>(context, listen: false);
MyWalletsProvider myWalletProvider =
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
HomeProvider homeProvider =
Provider.of<HomeProvider>(context, listen: false);
DuniterIndexer duniterIndexer =
Provider.of<DuniterIndexer>(context, listen: false);
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
// SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
// final sub = Provider.of<SubstrateSdk>(context, listen: false);
// sub.spawnBlock();
// sub.spawnBlock(0, 20);
log.d(walletOptions.address.text);
final int currentChest = myWalletProvider.getCurrentChest();
final currentChest = myWalletProvider.getCurrentChest();
bool isWalletNameIndexed =
duniterIndexer.walletNameIndexer[walletOptions.address.text] != null;
// final currentWallet = _myWalletProvider.getDefaultWallet();
// log.d(_walletOptions.getAddress(_currentChest, 3));
@ -76,7 +82,10 @@ class WalletOptions extends StatelessWidget {
height: 22,
child: Consumer<WalletOptionsProvider>(
builder: (context, walletProvider, _) {
return Text(wallet.name!);
return Text(isWalletNameIndexed
? duniterIndexer
.walletNameIndexer[walletOptions.address.text]!
: wallet.name!);
}),
),
actions: [
@ -99,7 +108,7 @@ class WalletOptions extends StatelessWidget {
),
],
),
bottomNavigationBar: homeProvider.bottomAppBar(context),
bottomNavigationBar: const GeckoBottomAppBar(),
body: Stack(children: [
Builder(
builder: (ctx) => SafeArea(
@ -120,44 +129,95 @@ class WalletOptions extends StatelessWidget {
backgroundColor,
],
)),
child: Row(
// mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
const Spacer(flex: 1),
avatar(walletProvider),
const Spacer(flex: 1),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
duniterIndexer.getNameByAddress(
context,
walletProvider.address.text,
wallet,
27,
false,
Colors.black,
FontWeight.w400,
FontStyle.normal),
// SizedBox(height: isTall ? 5 : 0),
SizedBox(height: isTall ? 5 : 0),
balance(
context, walletProvider.address.text, 21),
const SizedBox(width: 30),
Column(
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
walletOptions.idtyStatus(
context, walletOptions.address.text,
isOwner: true, color: orangeC),
getCerts(context,
walletProvider.address.text, 15),
]),
SizedBox(height: 10 * ratio),
]),
const Spacer(flex: 2),
]),
child: Row(children: <Widget>[
const Spacer(flex: 1),
avatar(walletProvider),
const Spacer(flex: 1),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Stack(children: [
SizedBox(
width: 250,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Consumer<WalletOptionsProvider>(
builder: (context, walletProvider, _) {
return NameByAddress(
wallet: wallet,
size: 27,
color: Colors.black,
fontWeight: wallet.isMember
? FontWeight.w500
: FontWeight.w400,
fontStyle: FontStyle.normal);
})
],
),
),
const SizedBox(width: 10),
if (duniterIndexer
.walletNameIndexer[wallet.address] ==
null)
Positioned(
right: 0,
child: InkWell(
key: keyRenameWallet,
onTap: () async {
await walletOptions.editWalletName(
context, wallet.id());
await Future.delayed(
const Duration(milliseconds: 30));
},
child: ClipRRect(
child: Image.asset(
walletOptions.isEditing
? 'assets/walletOptions/android-checkmark.png'
: 'assets/walletOptions/edit.png',
width: 25,
height: 25),
),
),
),
]),
SizedBox(height: isTall ? 5 : 0),
Balance(
address: walletProvider.address.text, size: 21),
const SizedBox(width: 30),
InkWell(
onTap: () => isWalletNameIndexed
? {
Navigator.push(
context,
PageNoTransit(builder: (context) {
return CertificationsScreen(
address:
walletProvider.address.text,
username: duniterIndexer
.walletNameIndexer[
walletProvider
.address.text]!);
}),
),
}
: null,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IdentityStatus(
address: walletOptions.address.text,
isOwner: true,
color: orangeC),
Certifications(
address: walletProvider.address.text,
size: 15)
]),
),
SizedBox(height: 10 * ratio),
]),
const Spacer(flex: 2),
]),
);
}),
Expanded(
@ -201,8 +261,8 @@ class WalletOptions extends StatelessWidget {
SizedBox(height: 17 * ratio),
// walletProvider.isMember(context, _walletOptions.address.text)
FutureBuilder(
future: walletProvider.isMember(
context, walletOptions.address.text),
future:
sub.isMember(walletOptions.address.text),
builder: (BuildContext context,
AsyncSnapshot<bool> isMember) {
if (isMember.connectionState !=
@ -229,7 +289,7 @@ class WalletOptions extends StatelessWidget {
]),
),
),
CommonElements().offlineInfo(context),
const OfflineInfo(),
]),
),
);
@ -302,7 +362,7 @@ class WalletOptions extends StatelessWidget {
foregroundColor: Colors.white, elevation: 4,
backgroundColor: orangeC, // foreground
),
onPressed: () {
onPressed: () async {
walletProvider.confirmIdentityPopup(context);
// Navigator.push(
// context,
@ -337,7 +397,7 @@ class WalletOptions extends StatelessWidget {
}
Widget pubkeyWidget(WalletOptionsProvider walletProvider, BuildContext ctx) {
final String shortPubkey = getShortPubkey(walletProvider.address.text);
final shortPubkey = getShortPubkey(walletProvider.address.text);
return GestureDetector(
key: keyCopyAddress,
onTap: () {
@ -404,7 +464,7 @@ class WalletOptions extends StatelessWidget {
// _historyProvider.nPage = 1;
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
PageNoTransit(builder: (context) {
return ActivityScreen(
address: walletProvider.address.text,
avatar: wallet.imageCustomPath == null
@ -437,7 +497,7 @@ class WalletOptions extends StatelessWidget {
}
Widget manageMembership(BuildContext context) {
WalletOptionsProvider walletOptions =
final walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
return InkWell(
key: keyManageMembership,
@ -469,8 +529,8 @@ class WalletOptions extends StatelessWidget {
Widget setDefaultWalletWidget(
BuildContext context,
WalletOptionsProvider walletProvider,
MyWalletsProvider myWalletProvider,
WalletOptionsProvider walletOptions,
final myWalletProvider,
final walletOptions,
int currentChest) {
return Consumer<MyWalletsProvider>(builder: (context, myWalletProvider, _) {
WalletData defaultWallet = myWalletProvider.getDefaultWallet();
@ -511,10 +571,10 @@ class WalletOptions extends StatelessWidget {
}
Future setDefaultWallet(BuildContext context, int currentChest) async {
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
MyWalletsProvider myWalletProvider =
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
WalletOptionsProvider walletOptions =
final walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
// WalletData defaultWallet = _myWalletProvider.getDefaultWallet()!;
@ -525,26 +585,26 @@ class WalletOptions extends StatelessWidget {
walletOptions.reload();
}
Widget deleteWallet(BuildContext context,
WalletOptionsProvider walletProvider, int currentChest) {
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
MyWalletsProvider myWalletProvider =
Widget deleteWallet(BuildContext context, WalletOptionsProvider walletOptions,
int currentChest) {
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
final defaultWallet = myWalletProvider.getDefaultWallet();
final bool isDefaultWallet =
walletProvider.address.text == defaultWallet.address;
walletOptions.address.text == defaultWallet.address;
// return Consumer<MyWalletsProvider>(
// builder: (context, _myWalletProvider, _) {
return FutureBuilder(
future: sub.hasAccountConsumers(wallet.address!),
future: sub.hasAccountConsumers(wallet.address),
builder: (BuildContext context, AsyncSnapshot<bool> hasConsumers) {
if (hasConsumers.connectionState != ConnectionState.done ||
hasConsumers.hasError) {
return const Text('');
}
final double balance =
balanceCache[walletProvider.address.text] ?? -1;
walletOptions.balanceCache[walletOptions.address.text] ?? -1;
final bool canDelete = !isDefaultWallet &&
!hasConsumers.data! &&
(balance > 2 || balance == 0);
@ -552,7 +612,7 @@ class WalletOptions extends StatelessWidget {
key: keyDeleteWallet,
onTap: canDelete
? () async {
await walletProvider.deleteWallet(context, wallet);
await walletOptions.deleteWallet(context, wallet);
WidgetsBinding.instance.addPostFrameCallback((_) {
myWalletProvider.listWallets =
myWalletProvider.readAllWallets(currentChest);

View File

@ -1,41 +1,78 @@
// ignore_for_file: use_build_context_synchronously
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/home.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:flutter/material.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/myWallets/chest_options.dart';
import 'package:gecko/screens/myWallets/choose_chest.dart';
import 'package:gecko/screens/myWallets/import_g1_v1.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:gecko/screens/myWallets/wallet_options.dart';
import 'package:gecko/screens/wallet_view.dart';
// import 'package:gecko/screens/myWallets/choose_chest.dart';
import 'package:gecko/widgets/balance.dart';
import 'package:gecko/widgets/bottom_app_bar.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
import 'package:gecko/widgets/commons/smooth_transition.dart';
import 'package:provider/provider.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:truncate/truncate.dart';
// import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';
class WalletsHome extends StatelessWidget {
class WalletsHome extends StatefulWidget {
const WalletsHome({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
MyWalletsProvider myWalletProvider =
Provider.of<MyWalletsProvider>(context);
HomeProvider homeProvider =
Provider.of<HomeProvider>(context, listen: false);
State<WalletsHome> createState() => _WalletsHomeState();
}
final int currentChestNumber = myWalletProvider.getCurrentChest();
class _WalletsHomeState extends State<WalletsHome> {
final safeKey = GlobalKey();
// List<TargetFocus> targets = [];
@override
void initState() {
// targets
// .add(TargetFocus(identify: "Target 1", keyTarget: safeKey, contents: [
// TargetContent(
// align: ContentAlign.right,
// child: Column(
// mainAxisSize: MainAxisSize.min,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: const <Widget>[
// Text(
// "Titulo lorem ipsum",
// style: TextStyle(
// fontWeight: FontWeight.bold,
// color: Colors.white,
// fontSize: 20.0),
// ),
// Padding(
// padding: EdgeInsets.only(top: 10.0),
// child: Text(
// "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin pulvinar tortor eget maximus iaculis.",
// style: TextStyle(color: Colors.white),
// ),
// )
// ],
// ))
// ]));
super.initState();
}
@override
Widget build(BuildContext context) {
final myWalletProvider = Provider.of<MyWalletsProvider>(context);
final currentChestNumber = myWalletProvider.getCurrentChest();
final ChestData currentChest = chestBox.get(currentChestNumber)!;
myWalletProvider.listWallets =
myWalletProvider.readAllWallets(currentChestNumber);
@ -61,17 +98,28 @@ class WalletsHome extends StatelessWidget {
ModalRoute.withName('/'),
);
}),
title: Text(currentChest.name!,
style: TextStyle(color: Colors.grey[850])),
title: Row(
children: [
Image.asset(
'assets/chests/${currentChest.imageName}',
height: 32,
),
const SizedBox(width: 17),
Text(currentChest.name!,
style: TextStyle(color: Colors.grey[850])),
],
),
backgroundColor: const Color(0xffFFD58D),
),
bottomNavigationBar: myWalletProvider.lastFlyBy == ''
? homeProvider.bottomAppBar(context)
? const GeckoBottomAppBar(
actualRoute: 'safeHome',
)
: dragInfo(context),
body: SafeArea(
child: Stack(children: [
myWalletsTiles(context, currentChestNumber),
CommonElements().offlineInfo(context),
const OfflineInfo(),
]),
),
),
@ -90,7 +138,7 @@ class WalletsHome extends StatelessWidget {
final bool isSameAddress =
myWalletProvider.dragAddress == myWalletProvider.lastFlyBy;
final double screenWidth = MediaQuery.of(homeContext).size.width;
final screenWidth = MediaQuery.of(homeContext).size.width;
return Container(
color: yellowC,
width: screenWidth,
@ -109,8 +157,7 @@ class WalletsHome extends StatelessWidget {
);
}
Widget chestOptions(
BuildContext context, MyWalletsProvider myWalletProvider) {
Widget chestOptions(BuildContext context, final myWalletProvider) {
return Column(children: [
const SizedBox(height: 50),
SizedBox(
@ -141,37 +188,48 @@ class WalletsHome extends StatelessWidget {
),
)),
const SizedBox(height: 30),
InkWell(
key: keyImportG1v1,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const ImportG1v1();
}),
);
},
child: SizedBox(
width: 400,
height: 60,
child: Center(
child: Text('importG1v1'.tr(),
style: TextStyle(
fontSize: 22,
color: Colors.blue[900],
fontWeight: FontWeight.w500))),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
'assets/cesium_bw2.svg',
semanticsLabel: 'CS',
height: 50,
),
const SizedBox(width: 5),
InkWell(
key: keyImportG1v1,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const ImportG1v1();
}),
);
},
child: SizedBox(
width: 350,
height: 60,
child: Center(
child: Text('importG1v1'.tr(),
style: TextStyle(
fontSize: 22,
color: Colors.blue[900],
fontWeight: FontWeight.w500))),
),
),
],
),
const SizedBox(height: 5),
const SizedBox(height: 20),
InkWell(
key: keyChangeChest,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const ChooseChest();
}),
);
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) {
// return const ChooseChest();
// }),
// );
},
child: SizedBox(
width: 400,
@ -180,7 +238,7 @@ class WalletsHome extends StatelessWidget {
child: Text('changeChest'.tr(),
style: const TextStyle(
fontSize: 22,
color: orangeC,
color: Colors.grey, //orangeC
fontWeight: FontWeight.w500))),
),
),
@ -189,12 +247,12 @@ class WalletsHome extends StatelessWidget {
}
Widget myWalletsTiles(BuildContext context, int currentChestNumber) {
MyWalletsProvider myWalletProvider =
Provider.of<MyWalletsProvider>(context);
WalletOptionsProvider walletOptions =
final myWalletProvider = Provider.of<MyWalletsProvider>(context);
final walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
final bool isWalletsExists = myWalletProvider.checkIfWalletExist();
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
if (!isWalletsExists) {
return const Text('');
@ -211,21 +269,31 @@ class WalletsHome extends StatelessWidget {
]));
}
List listWallets = myWalletProvider.listWallets;
// Get wallet list and sort by derivation number
List<WalletData> listWallets = myWalletProvider.listWallets;
listWallets.sort((p1, p2) {
return Comparable.compare(p1.number!, p2.number!);
});
WalletData? defaultWallet = myWalletProvider.getDefaultWallet();
final double screenWidth = MediaQuery.of(context).size.width;
int nTule = 2;
final screenWidth = MediaQuery.of(context).size.width;
int nTule;
if (screenWidth >= 900) {
nTule = 4;
} else if (screenWidth >= 650) {
nTule = 3;
} else {
nTule = 2;
}
// Offset followDragAnchorStrategy(
// Draggable<Object> d, BuildContext context, Offset point) {
// return Offset(d.feedbackOffset.dx - 30, d.feedbackOffset.dy - 0);
// }
// showTutorial();
// Future.delayed(const Duration(seconds: 1), showTutorial);
return CustomScrollView(slivers: <Widget>[
const SliverToBoxAdapter(child: SizedBox(height: 20)),
SliverGrid.count(
@ -235,17 +303,17 @@ class WalletsHome extends StatelessWidget {
crossAxisSpacing: 0,
mainAxisSpacing: 0,
children: <Widget>[
for (WalletData repository in listWallets as Iterable<WalletData>)
for (WalletData repository in listWallets)
LongPressDraggable<String>(
delay: const Duration(milliseconds: 200),
data: repository.address!,
data: repository.address,
dragAnchorStrategy:
(Draggable<Object> _, BuildContext __, Offset ___) =>
const Offset(0, 0),
// feedbackOffset: const Offset(-500, -500),
// dragAnchorStrategy: childDragAnchorStrategy,
onDragStarted: () =>
myWalletProvider.dragAddress = repository.address!,
myWalletProvider.dragAddress = repository.address,
onDragEnd: (_) {
myWalletProvider.lastFlyBy = '';
myWalletProvider.dragAddress = '';
@ -266,21 +334,21 @@ class WalletsHome extends StatelessWidget {
child: DragTarget<String>(
onAccept: (senderAddress) async {
log.d(
'INTERPAY: sender: $senderAddress --- receiver: ${repository.address!}');
'INTERPAY: sender: $senderAddress --- receiver: ${repository.address}');
final walletData = myWalletProvider
.getWalletDataByAddress(senderAddress);
await sub.setCurrentWallet(walletData!);
sub.reload();
paymentPopup(context, repository.address!);
paymentPopup(context, repository.address);
},
onMove: (details) {
if (repository.address! != myWalletProvider.lastFlyBy) {
myWalletProvider.lastFlyBy = repository.address!;
if (repository.address != myWalletProvider.lastFlyBy) {
myWalletProvider.lastFlyBy = repository.address;
myWalletProvider.reload();
}
},
onWillAccept: (senderAddress) =>
senderAddress != repository.address!,
senderAddress != repository.address,
builder: (
BuildContext context,
List<dynamic> accepted,
@ -289,7 +357,7 @@ class WalletsHome extends StatelessWidget {
return Padding(
padding: const EdgeInsets.all(16),
child: GestureDetector(
key: keyOpenWallet(repository.address!),
key: keyOpenWallet(repository.address),
onTap: () {
walletOptions.getAddress(
currentChestNumber, repository.derivation!);
@ -317,14 +385,15 @@ class WalletsHome extends StatelessWidget {
child: Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
gradient: RadialGradient(
radius: 0.6,
colors: [
Colors.green[400]!,
const Color(0xFFE7E7A6),
],
)),
decoration: const BoxDecoration(
gradient: RadialGradient(
radius: 0.8,
colors: [
Color.fromARGB(255, 255, 255, 211),
yellowC,
],
),
),
child:
// SvgPicture.asset('assets/chopp-gecko2.png',
// semanticsLabel: 'Gecko', height: 48),
@ -350,13 +419,46 @@ class WalletsHome extends StatelessWidget {
),
)),
Stack(children: <Widget>[
balanceBuilder(
context,
repository.address!,
repository.address ==
BalanceBuilder(
address: repository.address,
isDefault: repository.address ==
defaultWallet.address),
nameBuilder(context, repository,
defaultWallet, currentChestNumber),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
children: [
const SizedBox(height: 7),
Opacity(
opacity: 0.7,
child: Text(
duniterIndexer.walletNameIndexer[
repository.address] ??
truncate(
repository.name!, 20),
style: TextStyle(
fontSize: 20,
color:
defaultWallet.address ==
repository.address
? Colors.white
: Colors.black,
fontWeight: FontWeight.w500),
),
)
// NameByAddress(
// wallet: repository,
// address: repository.address,
// size: 20,
// color: defaultWallet.address ==
// repository.address
// ? Colors.white
// : Colors.black,
// ),
],
),
],
),
]),
]),
),
@ -375,69 +477,8 @@ class WalletsHome extends StatelessWidget {
]);
}
Widget balanceBuilder(context, String address, bool isDefault) {
return Container(
width: double.infinity,
color: isDefault ? orangeC : yellowC,
child: Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 38),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
balance(
context,
address,
15,
isDefault ? Colors.white : Colors.black,
isDefault ? yellowC : orangeC)
],
)),
);
}
Widget nameBuilder(BuildContext context, WalletData repository,
WalletData defaultWallet, int currentChestNumber) {
WalletOptionsProvider walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
DuniterIndexer duniterIndexer =
Provider.of<DuniterIndexer>(context, listen: false);
return ListTile(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(bottom: Radius.circular(12))),
tileColor: repository.address == defaultWallet.address
? orangeC
: const Color(0xffFFD58D),
title: Center(
child: Padding(
padding: const EdgeInsets.only(left: 5, right: 5, bottom: 35, top: 5),
child: duniterIndexer.getNameByAddress(
context,
repository.address!,
repository,
20,
true,
repository.id()[1] == defaultWallet.id()[1]
? const Color(0xffF9F9F1)
: Colors.black),
),
),
onTap: () {
walletOptions.getAddress(currentChestNumber, repository.derivation!);
Navigator.push(
context,
SmoothTransition(
page: WalletOptions(
wallet: repository,
),
),
);
},
);
}
Widget addNewDerivation(context) {
MyWalletsProvider myWalletProvider =
Provider.of<MyWalletsProvider>(context);
final myWalletProvider = Provider.of<MyWalletsProvider>(context);
String newDerivationName =
'${'wallet'.tr()} ${myWalletProvider.listWallets.last.number! + 2}';
@ -497,6 +538,41 @@ class WalletsHome extends StatelessWidget {
}
}
class BalanceBuilder extends StatelessWidget {
const BalanceBuilder({
Key? key,
required this.address,
required this.isDefault,
}) : super(key: key);
final String address;
final bool isDefault;
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
color: isDefault ? orangeC : yellowC,
child: Padding(
padding:
const EdgeInsets.only(left: 5, right: 5, top: 38, bottom: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Opacity(
opacity: 0.7,
child: Balance(
address: address,
size: 16,
color: isDefault ? Colors.white : Colors.black,
loadingColor: isDefault ? yellowC : orangeC),
)
],
)),
);
}
}
class CustomClipperOval extends CustomClipper<Rect> {
@override
Rect getClip(Size size) {

View File

@ -1,17 +1,12 @@
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/cesium_plus.dart';
import 'package:gecko/models/g1_wallets_list.dart';
import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/home.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/wallet_view.dart';
import 'package:gecko/widgets/bottom_app_bar.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
import 'package:gecko/widgets/contacts_list.dart';
import 'package:provider/provider.dart';
class ContactsScreen extends StatelessWidget {
@ -19,24 +14,12 @@ class ContactsScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
CesiumPlusProvider cesiumPlusProvider =
Provider.of<CesiumPlusProvider>(context, listen: false);
WalletsProfilesProvider walletsProfilesClass =
Provider.of<WalletsProfilesProvider>(context, listen: true);
HomeProvider homeProvider =
Provider.of<HomeProvider>(context, listen: false);
DuniterIndexer duniterIndexer =
Provider.of<DuniterIndexer>(context, listen: false);
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
double avatarSize = 55;
final myContacts = contactsBox.toMap().values.toList();
// for (var element in myContacts) {
// log.d('yooo: ${element.pubkey} ${element.username}');
// }
myContacts.sort((p1, p2) {
return Comparable.compare(p1.username?.toLowerCase() ?? 'zz',
p2.username?.toLowerCase() ?? 'zz');
@ -53,87 +36,15 @@ class ContactsScreen extends StatelessWidget {
'contactsManagementWithNbr'.tr(args: ['${myContacts.length}'])),
),
),
bottomNavigationBar: homeProvider.bottomAppBar(context),
bottomNavigationBar: const GeckoBottomAppBar(),
body: SafeArea(
child: Stack(children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const SizedBox(height: 20),
if (myContacts.isEmpty)
Text('noContacts'.tr())
else
Expanded(
child: ListView(children: <Widget>[
for (G1WalletsList g1Wallet in myContacts)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: ListTile(
key: keySearchResult('keyID++'),
horizontalTitleGap: 40,
contentPadding: const EdgeInsets.all(5),
leading: cesiumPlusProvider
.defaultAvatar(avatarSize),
title: Row(children: <Widget>[
Text(getShortPubkey(g1Wallet.address),
style: const TextStyle(
fontSize: 18,
fontFamily: 'Monospace',
fontWeight: FontWeight.w500),
textAlign: TextAlign.center),
]),
trailing: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 110,
child: Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
Column(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
balance(context,
g1Wallet.address, 16),
]),
]),
),
]),
subtitle: Row(children: <Widget>[
duniterIndexer.getNameByAddress(
context, g1Wallet.address)
]),
dense: false,
isThreeLine: false,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
walletsProfilesClass.address =
g1Wallet.address;
return WalletViewScreen(
address: g1Wallet.address,
username: g1WalletsBox
.get(g1Wallet.address)
?.id
?.username,
avatar: g1WalletsBox
.get(g1Wallet.address)
?.avatar,
);
}),
);
}),
),
]),
)
]),
),
CommonElements().offlineInfo(context),
ContactsList(
myContacts: myContacts,
avatarSize: avatarSize,
walletsProfilesClass: walletsProfilesClass,
duniterIndexer: duniterIndexer),
const OfflineInfo(),
]),
),
);

View File

@ -1,18 +1,17 @@
// ignore_for_file: file_names
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/2.dart';
import 'package:gecko/widgets/commons/intro_info.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
class OnboardingStepOne extends StatelessWidget {
const OnboardingStepOne({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
CommonElements common = CommonElements();
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
@ -28,16 +27,15 @@ class OnboardingStepOne extends StatelessWidget {
extendBodyBehindAppBar: true,
body: SafeArea(
child: Stack(children: [
common.infoIntro(
context,
'geckoGenerateYourWalletFromMnemonic'.tr(),
'fabrication-de-portefeuille.png',
'>',
const OnboardingStepTwo(),
0,
InfoIntro(
text: 'geckoGenerateYourWalletFromMnemonic'.tr(),
assetName: 'fabrication-de-portefeuille.png',
buttonText: '>',
nextScreen: const OnboardingStepTwo(),
pagePosition: 0,
isMd: true,
),
CommonElements().offlineInfo(context),
const OfflineInfo(),
]),
),
);

View File

@ -4,7 +4,7 @@
import 'dart:async';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/wallet_data.dart';
@ -13,8 +13,11 @@ import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/widgets/commons/build_progress_bar.dart';
import 'package:gecko/widgets/commons/build_text.dart';
import 'package:gecko/screens/onBoarding/11_congratulations.dart';
import 'package:gecko/widgets/commons/fader_transition.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
import 'package:pin_code_fields/pin_code_fields.dart';
import 'package:provider/provider.dart';
@ -26,126 +29,149 @@ class OnboardingStepTen extends StatelessWidget {
final formKey = GlobalKey<FormState>();
Color? pinColor = const Color(0xFFA4B600);
bool hasError = false;
TextEditingController enterPin = TextEditingController();
FocusNode pinFocus = FocusNode(debugLabel: 'pinFocusNode');
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GenerateWalletsProvider generateWalletProvider =
final generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
WalletOptionsProvider walletOptions =
Provider.of<WalletOptionsProvider>(context);
CommonElements common = CommonElements();
final int pinLenght = generateWalletProvider.pin.text.length;
final walletOptions = Provider.of<WalletOptionsProvider>(context);
final sub = Provider.of<SubstrateSdk>(context);
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
final pinLenght = generateWalletProvider.pin.text.length;
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: SizedBox(
height: 22,
child: Text(
'myPassword'.tr(),
style: const TextStyle(fontWeight: FontWeight.w600),
return WillPopScope(
onWillPop: () {
myWalletProvider.isPinValid = false;
myWalletProvider.isPinLoading = true;
return Future<bool>.value(true);
},
child: Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: SizedBox(
height: 22,
child: Text(
'myPassword'.tr(),
style: const TextStyle(fontWeight: FontWeight.w600),
),
),
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () {
myWalletProvider.isPinValid = false;
myWalletProvider.isPinLoading = true;
Navigator.of(context).pop();
}),
),
),
extendBodyBehindAppBar: true,
body: SafeArea(
child: Stack(children: [
Column(children: <Widget>[
SizedBox(height: isTall ? 40 : 20),
common.buildProgressBar(9),
SizedBox(height: isTall ? 40 : 20),
common.buildText("geckoWillCheckPassword".tr()),
SizedBox(height: isTall ? 80 : 20),
Visibility(
visible: generateWalletProvider.scanedValidWalletNumber != -1,
child: Padding(
padding: const EdgeInsets.only(bottom: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("derivationsScanProgress".tr(args: [
'${generateWalletProvider.scanedWalletNumber}',
'${generateWalletProvider.numberScan + 1}'
])),
const SizedBox(width: 10),
const SizedBox(
height: 22,
width: 22,
child: CircularProgressIndicator(
color: orangeC,
strokeWidth: 3,
extendBodyBehindAppBar: true,
body: SafeArea(
child: Stack(children: [
Column(children: <Widget>[
SizedBox(height: isTall ? 40 : 20),
const BuildProgressBar(pagePosition: 9),
SizedBox(height: isTall ? 40 : 20),
BuildText(text: "geckoWillCheckPassword".tr()),
SizedBox(height: isTall ? 60 : 10),
Visibility(
visible: generateWalletProvider.scanedValidWalletNumber != -1,
child: Padding(
padding: const EdgeInsets.only(bottom: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("derivationsScanProgress".tr(args: [
'${generateWalletProvider.scanedWalletNumber}',
'${generateWalletProvider.numberScan + 1}'
])),
const SizedBox(width: 10),
const SizedBox(
height: 22,
width: 22,
child: CircularProgressIndicator(
color: orangeC,
strokeWidth: 3,
),
),
),
],
],
),
),
),
),
Consumer<SubstrateSdk>(builder: (context, sub, _) {
return sub.nodeConnected
? pinForm(context, walletOptions, pinLenght, 1, 2)
: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
'Vous devez vous connecter à internet\npour valider votre coffre',
style: TextStyle(
fontSize: 20,
color: Colors.redAccent,
fontWeight: FontWeight.w500,
Consumer<MyWalletsProvider>(builder: (context, mw, _) {
return Visibility(
visible: !myWalletProvider.isPinValid &&
!myWalletProvider.isPinLoading,
child: Text(
"thisIsNotAGoodCode".tr(),
style: const TextStyle(
color: Colors.red, fontWeight: FontWeight.w500),
),
);
}),
SizedBox(height: isTall ? 20 : 10),
Consumer<SubstrateSdk>(builder: (context, sub, _) {
return sub.nodeConnected
? pinForm(context, walletOptions, pinLenght, 1, 2)
: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"youHaveToBeConnectedToValidateChest".tr(),
style: const TextStyle(
fontSize: 20,
color: Colors.redAccent,
fontWeight: FontWeight.w500,
),
textAlign: TextAlign.center,
),
textAlign: TextAlign.center,
]);
}),
Consumer<WalletOptionsProvider>(
builder: (context, walletOptions, _) {
return sub.nodeConnected
? InkWell(
key: keyCachePassword,
onTap: () {
walletOptions.changePinCacheChoice();
},
child: Row(children: [
const SizedBox(height: 30),
const Spacer(),
Icon(
configBox.get('isCacheChecked') ?? false
? Icons.check_box
: Icons.check_box_outline_blank,
color: orangeC,
),
]);
}),
Consumer<SubstrateSdk>(builder: (context, sub, _) {
return sub.nodeConnected
? InkWell(
key: keyCachePassword,
onTap: () {
walletOptions.changePinCacheChoice();
},
child: Row(children: [
const SizedBox(height: 30),
const Spacer(),
Icon(
configBox.get('isCacheChecked') ?? false
? Icons.check_box
: Icons.check_box_outline_blank,
color: orangeC,
),
const SizedBox(width: 8),
Text(
'rememberPassword'.tr(),
style: TextStyle(
fontSize: 16, color: Colors.grey[700]),
),
const Spacer()
]))
: const Text('');
}),
const SizedBox(height: 10),
const SizedBox(width: 8),
Text(
'rememberPassword'.tr(),
style: TextStyle(
fontSize: 16, color: Colors.grey[700]),
),
const Spacer()
]))
: const Text('');
}),
const SizedBox(height: 10),
]),
const OfflineInfo(),
]),
CommonElements().offlineInfo(context),
]),
));
)),
);
}
Widget pinForm(context, WalletOptionsProvider walletOptions, pinLenght,
int walletNbr, int derivation) {
// var _walletPin = '';
// ignore: close_sinks
StreamController<ErrorAnimationType> errorController =
StreamController<ErrorAnimationType>();
TextEditingController enterPin = TextEditingController();
MyWalletsProvider myWalletProvider =
Provider.of<MyWalletsProvider>(context);
GenerateWalletsProvider generateWalletProvider =
Widget pinForm(
context, final walletOptions, pinLenght, int walletNbr, int derivation) {
final myWalletProvider = Provider.of<MyWalletsProvider>(context);
final generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final int currentChest = myWalletProvider.getCurrentChest();
final currentChest = myWalletProvider.getCurrentChest();
return Form(
key: formKey,
@ -153,6 +179,9 @@ class OnboardingStepTen extends StatelessWidget {
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 30),
child: PinCodeTextField(
key: keyPinForm,
textCapitalization: TextCapitalization.characters,
// autoDisposeControllers: false,
focusNode: pinFocus,
autoFocus: true,
appContext: context,
pastedTextStyle: TextStyle(
@ -162,7 +191,8 @@ class OnboardingStepTen extends StatelessWidget {
length: pinLenght,
obscureText: true,
obscuringCharacter: '*',
animationType: AnimationType.fade,
animationType: AnimationType.slide,
animationDuration: const Duration(milliseconds: 40),
validator: (v) {
if (v!.length < pinLenght) {
return "yourPasswordLengthIsX".tr(args: [pinLenght.toString()]);
@ -175,17 +205,15 @@ class OnboardingStepTen extends StatelessWidget {
borderWidth: 4,
shape: PinCodeFieldShape.box,
borderRadius: BorderRadius.circular(5),
fieldHeight: 60,
fieldHeight: 50 * ratio,
fieldWidth: 50,
activeFillColor: hasError ? Colors.blueAccent : Colors.black,
activeFillColor: Colors.black,
),
showCursor: kDebugMode ? false : true,
cursorColor: Colors.black,
animationDuration: const Duration(milliseconds: 300),
textStyle: const TextStyle(fontSize: 20, height: 1.6),
textStyle: const TextStyle(fontSize: 27, height: 1.6),
backgroundColor: const Color(0xffF9F9F1),
enableActiveFill: false,
errorAnimationController: errorController,
controller: enterPin,
keyboardType: TextInputType.visiblePassword,
boxShadows: const [
@ -201,6 +229,8 @@ class OnboardingStepTen extends StatelessWidget {
log.d('$pin || ${generateWalletProvider.pin.text}');
if (pin.toUpperCase() == generateWalletProvider.pin.text) {
pinColor = Colors.green[500];
myWalletProvider.isPinLoading = false;
myWalletProvider.isPinValid = true;
await generateWalletProvider.storeHDWChest(context);
bool isAlive = false;
@ -214,14 +244,14 @@ class OnboardingStepTen extends StatelessWidget {
derivePath: '//2',
password: generateWalletProvider.pin.text);
WalletData myWallet = WalletData(
version: dataVersion,
chest: configBox.get('currentChest'),
address: address,
number: 0,
name: 'currentWallet'.tr(),
derivation: 2,
imageDefaultPath: '0.png');
await walletBox.add(myWallet);
imageDefaultPath: '0.png',
isOwned: true);
await walletBox.put(myWallet.address, myWallet);
}
myWalletProvider.readAllWallets(currentChest);
myWalletProvider.reload();
@ -235,17 +265,21 @@ class OnboardingStepTen extends StatelessWidget {
page: const OnboardingStepEleven(), isFast: false),
);
} else {
errorController.add(ErrorAnimationType
.shake); // Triggering error shake animation
hasError = true;
myWalletProvider.isPinLoading = false;
myWalletProvider.isPinValid = false;
pinColor = Colors.red[600];
walletOptions.reload();
enterPin.text = '';
// myWalletProvider.reload();
pinFocus.requestFocus();
}
},
onChanged: (value) {
if (enterPin.text != '') myWalletProvider.isPinLoading = true;
if (pinColor != const Color(0xFFA4B600)) {
pinColor = const Color(0xFFA4B600);
}
myWalletProvider.reload();
},
)),
);

View File

@ -1,20 +1,17 @@
// ignore_for_file: file_names
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/widgets/commons/build_text.dart';
class OnboardingStepEleven extends StatelessWidget {
const OnboardingStepEleven({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
CommonElements common = CommonElements();
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
@ -31,7 +28,7 @@ class OnboardingStepEleven extends StatelessWidget {
body: SafeArea(
child: Column(children: <Widget>[
const SizedBox(height: 40),
common.buildText("yourChestAndWalletWereCreatedSuccessfully".tr()),
BuildText(text: "yourChestAndWalletWereCreatedSuccessfully".tr()),
SizedBox(height: isTall ? 20 : 10),
Image.asset(
'assets/onBoarding/gecko-clin.gif',
@ -59,22 +56,8 @@ Widget finishButton(BuildContext context) {
backgroundColor: orangeC, // foreground
),
onPressed: () {
//TODO: fix bad widget ancestor when pupUntil (multi_chest test failed)
// Navigator.popUntil(homeContext, ModalRoute.withName('/'));
// Navigator.of(homeContext, rootNavigator: true)
// .popUntil(ModalRoute.withName('/'));
// while (Navigator.of(homeContext).canPop()) {
// Navigator.of(homeContext).pop();
// }
// Navigator.pushNamed(homeContext, '/mywallets');
Navigator.pushNamedAndRemoveUntil(
context, '/mywallets', (route) => route.isFirst);
// Navigator.pushNamedAndRemoveUntil(
// homeContext, '/mywallets', ModalRoute.withName('/'));
context, '/mywallets', ModalRoute.withName('/'));
},
child: Text("accessMyChest".tr(),
style:

View File

@ -1,20 +1,18 @@
// ignore_for_file: file_names
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/3.dart';
import 'package:gecko/widgets/commons/intro_info.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
class OnboardingStepTwo extends StatelessWidget {
const OnboardingStepTwo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
CommonElements common = CommonElements();
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
@ -30,14 +28,14 @@ class OnboardingStepTwo extends StatelessWidget {
extendBodyBehindAppBar: true,
body: SafeArea(
child: Stack(children: [
common.infoIntro(
context,
'keepThisMnemonicSecure'.tr(),
'fabrication-de-portefeuille-impossible-sans-phrase.png',
'>',
const OnboardingStepThree(),
1),
CommonElements().offlineInfo(context),
InfoIntro(
text: 'keepThisMnemonicSecure'.tr(),
assetName:
'fabrication-de-portefeuille-impossible-sans-phrase.png',
buttonText: '>',
nextScreen: const OnboardingStepThree(),
pagePosition: 1),
const OfflineInfo(),
]),
),
);

View File

@ -1,20 +1,18 @@
// ignore_for_file: file_names
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/4.dart';
import 'package:gecko/widgets/commons/intro_info.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
class OnboardingStepThree extends StatelessWidget {
const OnboardingStepThree({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
CommonElements common = CommonElements();
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
@ -30,9 +28,13 @@ class OnboardingStepThree extends StatelessWidget {
extendBodyBehindAppBar: true,
body: SafeArea(
child: Stack(children: [
common.infoIntro(context, 'warningForgotPassword'.tr(),
'forgot_password.png'.tr(), '>', const OnboardingStepFor(), 2),
CommonElements().offlineInfo(context),
InfoIntro(
text: 'warningForgotPassword'.tr(),
assetName: 'forgot_password.png'.tr(),
buttonText: '>',
nextScreen: const OnboardingStepFor(),
pagePosition: 2),
const OfflineInfo(),
]),
),
);

View File

@ -1,20 +1,18 @@
// ignore_for_file: file_names
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/5.dart';
import 'package:gecko/widgets/commons/intro_info.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
class OnboardingStepFor extends StatelessWidget {
const OnboardingStepFor({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
CommonElements common = CommonElements();
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
@ -30,15 +28,14 @@ class OnboardingStepFor extends StatelessWidget {
extendBodyBehindAppBar: true,
body: SafeArea(
child: Stack(children: [
common.infoIntro(
context,
'itsTimeToUseAPenAndPaper'.tr(),
'gecko_also_can_forget.png'.tr(),
'>',
const OnboardingStepFive(),
3,
InfoIntro(
text: 'itsTimeToUseAPenAndPaper'.tr(),
assetName: 'gecko_also_can_forget.png'.tr(),
buttonText: '>',
nextScreen: const OnboardingStepFive(),
pagePosition: 3,
isMd: true),
CommonElements().offlineInfo(context),
const OfflineInfo(),
]),
),
);

View File

@ -1,14 +1,19 @@
// ignore_for_file: file_names
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/widgets/commons/build_progress_bar.dart';
import 'package:gecko/widgets/commons/build_text.dart';
import 'package:gecko/screens/onBoarding/6.dart';
import 'package:gecko/widgets/commons/fader_transition.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
import 'package:printing/printing.dart';
import 'package:provider/provider.dart';
@ -29,12 +34,9 @@ class OnboardingStepFive extends StatefulWidget {
class _ChooseChestState extends State<OnboardingStepFive> {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GenerateWalletsProvider generateWalletProvider =
final generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context, listen: false);
final CommonElements common = CommonElements();
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
@ -52,26 +54,63 @@ class _ChooseChestState extends State<OnboardingStepFive> {
child: Stack(children: [
Column(children: [
SizedBox(height: isTall ? 40 : 20),
common.buildProgressBar(4),
const BuildProgressBar(pagePosition: 4),
SizedBox(height: isTall ? 40 : 20),
common.buildText('geckoGeneratedYourMnemonicKeepItSecret'.tr()),
BuildText(text: 'geckoGeneratedYourMnemonicKeepItSecret'.tr()),
SizedBox(height: 35 * ratio),
sentanceArray(context),
SizedBox(height: 17 * ratio),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return PrintWallet(
generateWalletProvider.generatedMnemonic);
}),
);
},
child: Image.asset(
'assets/printer.png',
height: 42 * ratio,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// const SizedBox(height: 10),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return PrintWallet(
generateWalletProvider.generatedMnemonic);
}),
);
},
child: Image.asset(
'assets/printer.png',
height: 42 * ratio,
),
),
SizedBox(
height: 40,
width: 120,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
foregroundColor: Colors.black,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
backgroundColor: orangeC,
elevation: 1, // foreground
),
onPressed: () {
Clipboard.setData(ClipboardData(
text: generateWalletProvider.generatedMnemonic));
snackCopySeed(context);
},
child: Row(children: <Widget>[
Image.asset(
'assets/walletOptions/copy-white.png',
height: 25,
),
const SizedBox(width: 7),
Text(
'copy'.tr(),
style: TextStyle(fontSize: 15, color: Colors.grey[50]),
)
]),
),
),
],
),
const SizedBox(height: 40),
Expanded(
@ -104,7 +143,7 @@ class _ChooseChestState extends State<OnboardingStepFive> {
const Spacer(),
// SizedBox(height: 35 * ratio),
]),
CommonElements().offlineInfo(context),
const OfflineInfo(),
]),
),
);
@ -112,7 +151,7 @@ class _ChooseChestState extends State<OnboardingStepFive> {
}
Widget sentanceArray(BuildContext context) {
GenerateWalletsProvider generateWalletProvider =
final generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context, listen: false);
return Padding(
@ -189,7 +228,7 @@ class PrintWallet extends StatelessWidget {
@override
Widget build(BuildContext context) {
GenerateWalletsProvider generateWalletProvider =
final generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context, listen: false);
return MaterialApp(
home: Scaffold(
@ -222,9 +261,9 @@ class PrintWallet extends StatelessWidget {
Widget nextButton(
BuildContext context, String text, bool isFast, bool skipIntro) {
GenerateWalletsProvider generateWalletProvider =
final generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context, listen: false);
MyWalletsProvider myWalletProvider =
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
return SizedBox(
width: 380 * ratio,

View File

@ -2,14 +2,17 @@
// ignore_for_file: must_be_immutable
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/widgets/commons/build_progress_bar.dart';
import 'package:gecko/widgets/commons/build_text.dart';
import 'package:gecko/screens/onBoarding/7.dart';
import 'package:gecko/screens/onBoarding/9.dart';
import 'package:gecko/widgets/commons/fader_transition.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
import 'package:provider/provider.dart';
class OnboardingStepSix extends StatelessWidget {
@ -24,11 +27,9 @@ class OnboardingStepSix extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GenerateWalletsProvider generateWalletProvider =
final generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context, listen: true);
CommonElements common = CommonElements();
_mnemonicController.text = generatedMnemonic!;
return WillPopScope(
@ -57,14 +58,14 @@ class OnboardingStepSix extends StatelessWidget {
alignment: Alignment.topCenter,
child: Column(children: [
SizedBox(height: isTall ? 40 : 20),
common.buildProgressBar(5),
const BuildProgressBar(pagePosition: 5),
SizedBox(height: isTall ? 40 : 20),
common.buildText(
"didYouNoteMnemonicToBeSureTypeWord".tr(args: [
BuildText(
text: "didYouNoteMnemonicToBeSureTypeWord".tr(args: [
(generateWalletProvider.nbrWord + 1).toString()
]),
20,
true),
size: 20,
isMd: true),
SizedBox(height: isTall ? 70 : 20),
Text('${generateWalletProvider.nbrWord + 1}',
key: keyAskedWord,
@ -136,7 +137,7 @@ class OnboardingStepSix extends StatelessWidget {
SizedBox(height: 35 * ratio),
]),
),
CommonElements().offlineInfo(context),
const OfflineInfo(),
]),
),
),
@ -145,7 +146,7 @@ class OnboardingStepSix extends StatelessWidget {
}
Widget nextButton(BuildContext context, String text, nextScreen, bool isFast) {
GenerateWalletsProvider generateWalletProvider =
final generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context, listen: false);
generateWalletProvider.isAskedWordValid = false;

View File

@ -1,10 +1,11 @@
// ignore_for_file: file_names
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/8.dart';
import 'package:gecko/widgets/commons/intro_info.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
class OnboardingStepSeven extends StatelessWidget {
const OnboardingStepSeven({Key? key, this.scanDerivation = false})
@ -13,8 +14,6 @@ class OnboardingStepSeven extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
CommonElements common = CommonElements();
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
@ -30,15 +29,14 @@ class OnboardingStepSeven extends StatelessWidget {
extendBodyBehindAppBar: true,
body: SafeArea(
child: Stack(children: [
common.infoIntro(
context,
'geckoWillGenerateAPassword'.tr(),
'coffre-fort-code-secret-dans-telephone.png',
'>',
OnboardingStepEight(scanDerivation: scanDerivation),
6,
InfoIntro(
text: 'geckoWillGenerateAPassword'.tr(),
assetName: 'coffre-fort-code-secret-dans-telephone.png',
buttonText: '>',
nextScreen: OnboardingStepEight(scanDerivation: scanDerivation),
pagePosition: 6,
boxHeight: 400),
CommonElements().offlineInfo(context),
const OfflineInfo(),
]),
),
);

View File

@ -1,10 +1,11 @@
// ignore_for_file: file_names
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/9.dart';
import 'package:gecko/widgets/commons/intro_info.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
class OnboardingStepEight extends StatelessWidget {
const OnboardingStepEight({Key? key, this.scanDerivation = false})
@ -13,8 +14,6 @@ class OnboardingStepEight extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
CommonElements common = CommonElements();
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
@ -30,15 +29,14 @@ class OnboardingStepEight extends StatelessWidget {
extendBodyBehindAppBar: true,
body: SafeArea(
child: Stack(children: [
common.infoIntro(
context,
'thisPasswordProtectsYourWalletsInASecureChest'.tr(),
'coffre-fort-protege-les-portefeuilles.png',
'>',
OnboardingStepNine(scanDerivation: scanDerivation),
7,
InfoIntro(
text: 'thisPasswordProtectsYourWalletsInASecureChest'.tr(),
assetName: 'coffre-fort-protege-les-portefeuilles.png',
buttonText: '>',
nextScreen: OnboardingStepNine(scanDerivation: scanDerivation),
pagePosition: 7,
isMd: true),
CommonElements().offlineInfo(context),
const OfflineInfo(),
]),
),
);

View File

@ -1,12 +1,15 @@
// ignore_for_file: file_names
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/generate_wallets.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/widgets/commons/build_progress_bar.dart';
import 'package:gecko/widgets/commons/build_text.dart';
import 'package:gecko/screens/onBoarding/10.dart';
import 'package:gecko/widgets/commons/next_button.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
import 'package:provider/provider.dart';
class OnboardingStepNine extends StatelessWidget {
@ -16,12 +19,10 @@ class OnboardingStepNine extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GenerateWalletsProvider generateWalletProvider =
final generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
// MyWalletsProvider myWalletProvider =
// final myWalletProvider =
// Provider.of<MyWalletsProvider>(context);
CommonElements common = CommonElements();
generateWalletProvider.pin.text = debugPin // kDebugMode &&
? 'AAAAA'
@ -44,15 +45,16 @@ class OnboardingStepNine extends StatelessWidget {
child: Stack(children: [
Column(children: <Widget>[
SizedBox(height: isTall ? 40 : 20),
common.buildProgressBar(8),
const BuildProgressBar(pagePosition: 8),
SizedBox(height: isTall ? 40 : 20),
common.buildText("hereIsThePasswordKeepIt".tr(), 20, true),
BuildText(text: "hereIsThePasswordKeepIt".tr()),
const SizedBox(height: 100),
Stack(
alignment: Alignment.centerRight,
children: <Widget>[
TextField(
key: keyGeneratedPin,
textCapitalization: TextCapitalization.characters,
enabled: false,
controller: generateWalletProvider.pin,
maxLines: 1,
@ -72,6 +74,12 @@ class OnboardingStepNine extends StatelessWidget {
),
],
),
const SizedBox(height: 30),
Text(
'Pendant la phase de test de Ğecko,\nles codes secrets\nsont systématiquement AAAAA.'
.tr(),
style: TextStyle(color: Colors.grey[700], fontSize: 15),
textAlign: TextAlign.center),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
@ -96,11 +104,13 @@ class OnboardingStepNine extends StatelessWidget {
fontWeight: FontWeight.w600))),
))),
SizedBox(height: 22 * ratio),
common.nextButton(context, "iNotedMyPassword".tr(),
OnboardingStepTen(scanDerivation: scanDerivation), false),
NextButton(
text: "iNotedMyPassword".tr(),
nextScreen: OnboardingStepTen(scanDerivation: scanDerivation),
isFast: false),
SizedBox(height: 35 * ratio),
]),
CommonElements().offlineInfo(context),
const OfflineInfo(),
]),
));
}

View File

@ -1,6 +1,5 @@
// ignore_for_file: must_be_immutable
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
import 'package:gecko/providers/substrate_sdk.dart';
@ -17,7 +16,6 @@ class QrCodeFullscreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
return Scaffold(
appBar: AppBar(
elevation: 0,

View File

@ -1,26 +1,53 @@
// ignore_for_file: use_build_context_synchronously
import 'dart:async';
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/widgets/commons/common_elements.dart';
import 'package:gecko/screens/search_result.dart';
import 'package:gecko/screens/wallet_view.dart';
import 'package:gecko/widgets/commons/offline_info.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<SearchScreen> createState() => _SearchScreenState();
}
class _SearchScreenState extends State<SearchScreen> {
bool canPasteAddress = false;
String pastedAddress = '';
Timer? debounce;
final int debouneTime = 50;
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) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
SearchProvider searchProvider = Provider.of<SearchProvider>(context);
final double screenHeight = MediaQuery.of(context).size.height;
// HomeProvider _homeProvider =
// Provider.of<HomeProvider>(context, listen: false);
final searchProvider = Provider.of<SearchProvider>(context);
final screenHeight = MediaQuery.of(context).size.height;
final canValidate = searchProvider.searchController.text.length >= 2;
// final canPasteAddress = false;
return WillPopScope(
onWillPop: () {
@ -29,7 +56,6 @@ class SearchScreen extends StatelessWidget {
},
child: Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
elevation: 1,
toolbarHeight: 60 * ratio,
@ -44,7 +70,6 @@ class SearchScreen extends StatelessWidget {
Navigator.of(context).pop();
}),
),
// bottomNavigationBar: _homeProvider.bottomAppBar(context),
body: SafeArea(
child: Stack(children: [
Column(children: <Widget>[
@ -52,18 +77,52 @@ class SearchScreen extends StatelessWidget {
Padding(
padding: const EdgeInsets.symmetric(horizontal: 17),
child: TextField(
onSubmitted: searchProvider.searchController.text.length >= 2
? (_) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const SearchResultScreen();
}),
);
}
: (value) {},
textInputAction: TextInputAction.search,
key: keySearchField,
controller: searchProvider.searchController,
autofocus: true,
maxLines: 1,
textAlign: TextAlign.left,
onChanged: (v) => searchProvider.reload(),
onChanged: (v) => {
if (debounce?.isActive ?? false) {debounce!.cancel()},
debounce = Timer(Duration(milliseconds: debouneTime), () {
getClipBoard();
searchProvider.reload();
})
},
decoration: InputDecoration(
filled: true,
fillColor: Colors.white,
prefixIconConstraints: const BoxConstraints(
minHeight: 32,
),
suffixIcon: searchProvider.searchController.text == ''
? null
: Padding(
padding: const EdgeInsets.symmetric(horizontal: 17),
child: IconButton(
onPressed: (() async => {
searchProvider.searchController.text = '',
await getClipBoard(),
searchProvider.reload(),
}),
icon: Icon(
Icons.close,
color: Colors.grey[600],
size: 30,
),
),
),
prefixIcon: const Padding(
padding: EdgeInsets.symmetric(horizontal: 17),
child: Image(
@ -90,15 +149,15 @@ class SearchScreen extends StatelessWidget {
),
const Spacer(flex: 1),
SizedBox(
width: 410,
height: 70,
width: 320,
height: 90,
child: ElevatedButton(
key: keyConfirmSearch,
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, elevation: 4,
backgroundColor: orangeC, // foreground
),
onPressed: searchProvider.searchController.text.length >= 2
onPressed: canValidate
? () {
Navigator.push(
context,
@ -107,17 +166,32 @@ 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: 24, fontWeight: FontWeight.w600),
fontSize: 21, fontWeight: FontWeight.w600),
),
),
),
Spacer(flex: screenHeight <= 800 ? 1 : 2),
]),
CommonElements().offlineInfo(context),
const OfflineInfo(),
]),
),
),

View File

@ -1,18 +1,13 @@
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/cesium_plus.dart';
import 'package:gecko/models/g1_wallets_list.dart';
import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/home.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/providers/search.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/wallet_view.dart';
import 'package:gecko/widgets/bottom_app_bar.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
import 'package:gecko/widgets/search_result_list.dart';
import 'package:provider/provider.dart';
class SearchResultScreen extends StatelessWidget {
@ -20,19 +15,19 @@ class SearchResultScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
SearchProvider searchProvider =
Provider.of<SearchProvider>(context, listen: false);
CesiumPlusProvider cesiumPlusProvider =
Provider.of<CesiumPlusProvider>(context, listen: false);
final searchProvider = Provider.of<SearchProvider>(context, listen: false);
WalletsProfilesProvider walletsProfilesClass =
Provider.of<WalletsProfilesProvider>(context, listen: false);
HomeProvider homeProvider =
Provider.of<HomeProvider>(context, listen: false);
DuniterIndexer duniterIndexer =
Provider.of<DuniterIndexer>(context, listen: false);
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
double avatarSize = 55;
// List<G1WalletsList> myContacts = contactsBox.toMap().values.toList();
// myContacts = myContacts
// .where((map) =>
// (map.username ?? '').contains(searchProvider.searchController.text))
// .toList();
// final searchProvider.resultLenght.toString();
return Scaffold(
backgroundColor: backgroundColor,
@ -44,7 +39,7 @@ class SearchResultScreen extends StatelessWidget {
child: Text('researchResults'.tr()),
),
),
bottomNavigationBar: homeProvider.bottomAppBar(context),
bottomNavigationBar: const GeckoBottomAppBar(),
body: SafeArea(
child: Stack(children: [
Padding(
@ -53,129 +48,45 @@ class SearchResultScreen extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const SizedBox(height: 30),
RichText(
text: TextSpan(
style: TextStyle(
fontSize: 18,
color: Colors.grey[700],
),
children: <TextSpan>[
TextSpan(
text: "resultsFor".tr(),
),
TextSpan(
text: '"${searchProvider.searchController.text}"',
style: const TextStyle(fontStyle: FontStyle.italic),
Center(
child: Column(
children: <Widget>[
Text(
"resultsFor".tr(),
style: TextStyle(color: Colors.grey[600]),
),
Text(
'"${searchProvider.searchController.text}"',
style: const TextStyle(
fontStyle: FontStyle.italic, fontSize: 21),
)
],
),
),
// const SizedBox(height: 40),
// Text(
// 'Dans mes contacts'.tr(args: [currencyName]),
// style: const TextStyle(fontSize: 20),
// ),
// ContactsList(
// myContacts: myContacts,
// avatarSize: avatarSize,
// walletsProfilesClass: walletsProfilesClass,
// duniterIndexer: duniterIndexer),
const SizedBox(height: 40),
Text(
'inBlockchainResult'.tr(args: [currencyName]),
style: const TextStyle(fontSize: 20),
),
const SizedBox(height: 20),
FutureBuilder(
future: searchProvider.searchAddress(),
builder: (context, AsyncSnapshot<List?> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data?.isEmpty ?? true) {
return duniterIndexer.searchIdentity(
context, searchProvider.searchController.text);
// const Text('Aucun résultat');
} else {
return Expanded(
child: ListView(children: <Widget>[
for (G1WalletsList g1Wallet
in snapshot.data ?? [])
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 5),
child: ListTile(
key: keySearchResult(g1Wallet.address),
horizontalTitleGap: 40,
contentPadding: const EdgeInsets.all(5),
leading: cesiumPlusProvider
.defaultAvatar(avatarSize),
title: Row(children: <Widget>[
Text(getShortPubkey(g1Wallet.address),
style: const TextStyle(
fontSize: 18,
fontFamily: 'Monospace',
fontWeight: FontWeight.w500),
textAlign: TextAlign.center),
]),
trailing: Column(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
SizedBox(
width: 110,
child: Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
Column(
mainAxisAlignment:
MainAxisAlignment
.center,
children: [
balance(
context,
g1Wallet.address,
16),
]),
]),
),
]),
subtitle: Row(children: <Widget>[
duniterIndexer.getNameByAddress(
context, g1Wallet.address)
]),
dense: false,
isThreeLine: false,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
walletsProfilesClass.address =
g1Wallet.address;
return WalletViewScreen(
address: g1Wallet.address,
username: g1WalletsBox
.get(g1Wallet.address)
?.id
?.username,
avatar: g1WalletsBox
.get(g1Wallet.address)
?.avatar,
);
}),
);
}),
),
]),
);
}
}
return const Center(
heightFactor: 5,
child: CircularProgressIndicator(
strokeWidth: 3,
backgroundColor: yellowC,
color: orangeC,
),
);
},
),
// Text(
// _searchProvider.searchResult.toString(),
// )
SearchResult(
searchProvider: searchProvider,
duniterIndexer: duniterIndexer,
avatarSize: avatarSize,
walletsProfilesClass: walletsProfilesClass),
]),
),
CommonElements().offlineInfo(context),
const OfflineInfo(),
]),
),
);

View File

@ -1,6 +1,6 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/home.dart';
@ -18,8 +18,6 @@ class SettingsScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
const double buttonHigh = 50;
const double buttonWidth = 240;
const double fontSize = 16;
@ -35,7 +33,7 @@ class SettingsScreen extends StatelessWidget {
body: Column(children: <Widget>[
const SizedBox(height: 30),
Text(
'Connectivité réseau',
'networkSettings'.tr(),
style: TextStyle(color: Colors.grey[500], fontSize: 22),
),
const SizedBox(height: 20),
@ -44,7 +42,7 @@ class SettingsScreen extends StatelessWidget {
indexerEndpointSelection(context),
const SizedBox(height: 40),
Text(
'Affichage',
'displaySettings'.tr(),
style: TextStyle(color: Colors.grey[500], fontSize: 22),
),
const SizedBox(height: 20),
@ -110,7 +108,7 @@ class SettingsScreen extends StatelessWidget {
}
Widget duniterEndpointSelection(BuildContext context) {
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
String? selectedDuniterEndpoint;
// List of items in our dropdown menu
@ -251,7 +249,8 @@ class SettingsScreen extends StatelessWidget {
height: sub.getConnectedEndpoint() == null ? 60 : 20,
child: Text(
sub.getConnectedEndpoint() ??
"Un noeud sûr et valide sera choisi automatiquement parmis une liste aléatoire.",
"anAutoNodeChoosed"
.tr(), //"Un noeud sûr et valide sera choisi automatiquement parmis une liste aléatoire.",
style: TextStyle(
fontSize: 15,
fontStyle: FontStyle.italic,
@ -261,7 +260,9 @@ class SettingsScreen extends StatelessWidget {
);
}),
Text(
'bloc N°${sub.blocNumber}',
'blockN'.tr(args: [
sub.blocNumber.toString()
]), //'bloc N°${sub.blocNumber}',
style: TextStyle(fontSize: 14, color: Colors.grey[700]),
)
],
@ -271,8 +272,7 @@ class SettingsScreen extends StatelessWidget {
}
Widget indexerEndpointSelection(BuildContext context) {
DuniterIndexer indexer =
Provider.of<DuniterIndexer>(context, listen: false);
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
String? selectedIndexerEndpoint;
if (configBox.containsKey('customIndexer')) {
@ -282,7 +282,7 @@ class SettingsScreen extends StatelessWidget {
}
if (selectedIndexerEndpoint == '') {
selectedIndexerEndpoint = indexer.listIndexerEndpoints[0];
selectedIndexerEndpoint = duniterIndexer.listIndexerEndpoints[0];
}
TextEditingController indexerEndpointController = TextEditingController(
@ -300,7 +300,8 @@ class SettingsScreen extends StatelessWidget {
const SizedBox(width: 10),
const SizedBox(
width: 100,
child: Text('Indexer : '),
// child: Text('indexer'.tr()), // why translation does not work??
child: Text('Indexer'),
),
const Spacer(),
Icon(indexerEndpoint != '' ? Icons.check : Icons.close),
@ -388,7 +389,8 @@ class SettingsScreen extends StatelessWidget {
height: 60,
child: Text(
sub.getConnectedEndpoint() ??
"Un noeud sûr et valide sera choisi automatiquement parmis une liste aléatoire.",
"anAutoNodeChoosed"
.tr(), //"Un noeud sûr et valide sera choisi automatiquement parmis une liste aléatoire.",
style: TextStyle(
fontSize: 15,
fontStyle: FontStyle.italic,

View File

@ -1,4 +1,3 @@
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
@ -7,8 +6,7 @@ class TemplateScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
// HomeProvider _homeProvider = Provider.of<HomeProvider>(context);
// final _homeProvider = Provider.of<HomeProvider>(context);
return Scaffold(
backgroundColor: backgroundColor,

View File

@ -1,5 +1,5 @@
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';
@ -20,11 +20,10 @@ class TransactionInProgress extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: true);
WalletsProfilesProvider walletViewProvider =
final sub = Provider.of<SubstrateSdk>(context, listen: true);
final walletProfiles =
Provider.of<WalletsProfilesProvider>(context, listen: false);
MyWalletsProvider myWalletProvider =
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
bool isValid = false;
@ -35,14 +34,16 @@ class TransactionInProgress extends StatelessWidget {
// sub.spawnBlock();
log.d(walletViewProvider.address);
log.d(walletProfiles.address);
final from = fromAddress ?? myWalletProvider.getDefaultWallet().name!;
final to = toAddress ?? getShortPubkey(walletViewProvider.address);
final amount = walletViewProvider.payAmount.text;
final to = toAddress ?? getShortPubkey(walletProfiles.address);
final amount = walletProfiles.payAmount.text;
String actionName = '';
final bool isUdUnit = configBox.get('isUdUnit') ?? false;
log.d("$transType :: $actionName :: $result");
switch (transType) {
case 'pay':
{
@ -95,7 +96,6 @@ class TransactionInProgress extends StatelessWidget {
{
isLoading = false;
// jsonResult = json.decode(_result);
log.d(result);
if (result.contains('blockHash: ')) {
isValid = true;
resultText = 'extrinsicValidated'.tr(args: [actionName]);
@ -111,7 +111,7 @@ class TransactionInProgress extends StatelessWidget {
} else {
exception = exceptionSplit[0];
}
// log.d('expection: $_exception');
log.d('expection: $exceptionSplit');
switch (exception) {
case 'cert.NotRespectCertPeriod':
case 'identity.CreatorNotAllowedToCreateIdty':

View File

@ -2,53 +2,56 @@
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/g1_wallets_list.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/cesium_plus.dart';
import 'package:gecko/providers/home.dart';
import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/screens/activity.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/widgets/commons/common_elements.dart';
import 'package:gecko/screens/myWallets/choose_wallet.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:gecko/screens/qrcode_fullscreen.dart';
import 'package:gecko/screens/transaction_in_progress.dart';
import 'package:gecko/widgets/balance.dart';
import 'package:gecko/widgets/bottom_app_bar.dart';
import 'package:gecko/widgets/header_profile.dart';
import 'package:gecko/widgets/page_route_no_transition.dart';
import 'package:provider/provider.dart';
import 'package:qr_flutter/qr_flutter.dart';
class WalletViewScreen extends StatelessWidget {
const WalletViewScreen(
{required this.address, this.username, this.avatar, Key? key})
{required this.address, required this.username, this.avatar, Key? key})
: super(key: key);
final String address;
final String? username;
final String username;
final Image? avatar;
final double buttonSize = 100;
final double buttonFontSize = 18;
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
WalletsProfilesProvider walletProfile =
Provider.of<WalletsProfilesProvider>(context, listen: false);
CesiumPlusProvider cesiumPlusProvider =
Provider.of<CesiumPlusProvider>(context, listen: false);
walletProfile.address = address;
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
HomeProvider homeProvider =
Provider.of<HomeProvider>(context, listen: false);
MyWalletsProvider myWalletProvider =
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
WalletData? defaultWallet = myWalletProvider.getDefaultWallet();
walletProfile.address = address;
sub.setCurrentWallet(defaultWallet);
log.d('aaaaaaaaaaaaaaaaaaa: $username');
return Scaffold(
backgroundColor: backgroundColor,
resizeToAvoidBottomInset: true,
@ -100,15 +103,21 @@ class WalletViewScreen extends StatelessWidget {
)
],
title: SizedBox(
height: 22,
child: Text('seeAWallet'.tr()),
),
height: 22,
child: Text(duniterIndexer
.walletNameIndexer[walletProfile.address] ==
null
? 'seeAWallet'.tr()
: 'memberAccountOf'.tr(args: [
duniterIndexer.walletNameIndexer[walletProfile.address] ??
'?'
]))),
),
bottomNavigationBar: homeProvider.bottomAppBar(context),
bottomNavigationBar: const GeckoBottomAppBar(),
body: SafeArea(
child: Column(children: <Widget>[
walletProfile.headerProfileView(context, address, username),
SizedBox(height: isTall ? 10 : 0),
HeaderProfile(address: address, username: username),
SizedBox(height: isTall ? 30 : 15),
Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
Column(children: <Widget>[
SizedBox(
@ -128,11 +137,10 @@ class WalletViewScreen extends StatelessWidget {
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
PageNoTransit(builder: (context) {
return ActivityScreen(
address: address,
avatar:
cesiumPlusProvider.defaultAvatar(50));
avatar: defaultAvatar(50));
}),
);
}),
@ -150,20 +158,20 @@ class WalletViewScreen extends StatelessWidget {
Consumer<SubstrateSdk>(builder: (context, sub, _) {
WalletData? defaultWallet = myWalletProvider.getDefaultWallet();
return FutureBuilder(
future: sub.certState(defaultWallet.address!, address),
future: sub.certState(defaultWallet.address, address),
builder: (context, AsyncSnapshot<Map<String, int>> snapshot) {
if (snapshot.data == null) return const SizedBox();
String duration = '';
log.d('certDelay ${snapshot.data!['certDelay']}');
log.d('certRenewable ${snapshot.data!['certRenewable']}');
log.d(
'${getShortPubkey(address)} --- certDelay ${snapshot.data!['certDelay']} --- certRenewable ${snapshot.data!['certRenewable']}');
if (snapshot.data!['certDelay'] != null ||
snapshot.data!['certRenewable'] != null) {
final Duration durationSeconds = Duration(
seconds: snapshot.data!['certDelay'] ??
snapshot.data!['certRenewable']!);
final int seconds = durationSeconds.inSeconds;
final int minutes = durationSeconds.inMinutes;
final seconds = durationSeconds.inSeconds;
final minutes = durationSeconds.inMinutes;
if (seconds <= 0) {
duration = 'seconds'.tr(args: ['0']);
@ -172,8 +180,8 @@ class WalletViewScreen extends StatelessWidget {
} else if (seconds <= 3600) {
duration = 'minutes'.tr(args: [minutes.toString()]);
} else if (seconds <= 86400) {
final int hours = durationSeconds.inHours;
final int minutesLeft = minutes - hours * 60;
final hours = durationSeconds.inHours;
final minutesLeft = minutes - hours * 60;
String showMinutes = '';
if (minutesLeft < 60) {}
showMinutes =
@ -181,11 +189,10 @@ class WalletViewScreen extends StatelessWidget {
duration =
'hours'.tr(args: [hours.toString(), showMinutes]);
} else if (seconds <= 2592000) {
final int days = durationSeconds.inDays;
final days = durationSeconds.inDays;
duration = 'days'.tr(args: [days.toString()]);
} else {
final int months =
(durationSeconds.inDays / 30).round();
final months = (durationSeconds.inDays / 30).round();
duration = 'months'.tr(args: [months.toString()]);
}
}
@ -213,12 +220,18 @@ class WalletViewScreen extends StatelessWidget {
'assets/gecko_certify.png')),
),
onTap: () async {
final bool? result = await confirmPopup(
context,
"areYouSureYouWantToCertify".tr(
args: [
getShortPubkey(address)
]));
final bool? result =
await confirmPopupCertification(
context,
'areYouSureYouWantToCertify1'
.tr(),
duniterIndexer
.walletNameIndexer[
address] ??
"noIdentity".tr(),
'areYouSureYouWantToCertify2'
.tr(),
getShortPubkey(address));
if (result ?? false) {
String? pin;
@ -262,7 +275,9 @@ class WalletViewScreen extends StatelessWidget {
),
const SizedBox(height: 9),
Text(
"certify".tr(),
toStatus == 0
? "certify".tr()
: "createIdentity".tr(),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: buttonFontSize,
@ -422,9 +437,7 @@ void paymentPopup(BuildContext context, String toAddress) {
log.d(pin);
if (pin != null || myWalletProvider.pinCode != '') {
// Payment workflow !
WalletsProfilesProvider walletViewProvider =
Provider.of<WalletsProfilesProvider>(context, listen: false);
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final acc = sub.getCurrentWallet();
log.d(
"fromAddress: ${acc.address!},destAddress: $toAddress, amount: ${double.parse(walletViewProvider.payAmount.text)}, password: $pin");
@ -453,16 +466,19 @@ void paymentPopup(BuildContext context, String toAddress) {
context: context,
builder: (BuildContext context) {
final sub = Provider.of<SubstrateSdk>(homeContext, listen: false);
final walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
double fees = 0;
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
if (walletViewProvider.payAmount.text != '' &&
(double.parse(walletViewProvider.payAmount.text) +
2 / balanceRatio) <=
(balanceCache[defaultWallet.address] ?? 0) &&
(walletOptions.balanceCache[defaultWallet.address] ?? 0) &&
toAddress != defaultWallet.address) {
if ((balanceCache[toAddress] == 0 ||
balanceCache[toAddress] == null) &&
if ((walletOptions.balanceCache[toAddress] == 0 ||
walletOptions.balanceCache[toAddress] == null) &&
double.parse(walletViewProvider.payAmount.text) <
5 / balanceRatio) {
canValidate = false;
@ -557,7 +573,7 @@ void paymentPopup(BuildContext context, String toAddress) {
child: Row(children: [
Text(defaultWallet.name!),
const Spacer(),
balance(context, defaultWallet.address!, 20)
Balance(address: defaultWallet.address, size: 20),
]),
),
);
@ -621,10 +637,11 @@ void paymentPopup(BuildContext context, String toAddress) {
autofocus: true,
maxLines: 1,
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
keyboardType: const TextInputType.numberWithOptions(
decimal: true),
onChanged: (_) async {
fees = await sub.txFees(
defaultWallet.address!,
defaultWallet.address,
toAddress,
double.parse(
walletViewProvider.payAmount.text == ''

40
lib/styles.dart Normal file
View File

@ -0,0 +1,40 @@
// import 'dart:io';
import 'package:flutter/material.dart';
// import 'package:logger/logger.dart';
// --- THIS IS WIP ---
class GeckoStyles {
TextStyle successBold(List<String> pars) {
return TextStyle(
color: Colors.green.shade600,
fontWeight: FontWeight.bold,
);
}
TextStyle success() {
return TextStyle(color: Colors.green.shade600);
}
TextStyle error500(List<String> pars) {
return const TextStyle(
fontSize: 20,
color: Colors.redAccent,
fontWeight: FontWeight.w500,
);
}
TextStyle error() {
return const TextStyle(fontSize: 20, color: Colors.redAccent);
}
TextStyle builder(Map<String, dynamic> pars) {
// pars["hola"] = 20;
// //int a = double.tryParse(source) pars["hola"];
// return const TextStyle( fontSize: double.tryParse(pars["hola"]),
// color: Colors.redAccent,
// fontWeight: FontWeight.w500
// );
return const TextStyle();
}
}

75
lib/widgets/balance.dart Normal file
View File

@ -0,0 +1,75 @@
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/widgets/ud_unit_display.dart';
import 'package:provider/provider.dart';
class Balance extends StatelessWidget {
const Balance(
{Key? key,
required this.address,
required this.size,
this.color = Colors.black,
this.loadingColor = const Color(0xffd07316)})
: super(key: key);
final String address;
final double size;
final Color color;
final Color loadingColor;
@override
Widget build(BuildContext context) {
final walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
return Column(children: <Widget>[
Consumer<SubstrateSdk>(builder: (context, sdk, _) {
return FutureBuilder(
future: sdk.getBalance(address),
builder: (BuildContext context,
AsyncSnapshot<Map<String, double>> globalBalance) {
if (globalBalance.connectionState != ConnectionState.done ||
globalBalance.hasError) {
if (walletOptions.balanceCache[address] != null &&
walletOptions.balanceCache[address] != -1) {
return Row(children: [
Text(walletOptions.balanceCache[address]!.toString(),
style: TextStyle(
fontSize: isTall ? size : size * 0.9,
color: color)),
const SizedBox(width: 5),
UdUnitDisplay(size: size, color: color),
]);
} else {
return SizedBox(
height: 15,
width: 15,
child: CircularProgressIndicator(
color: loadingColor,
strokeWidth: 2,
),
);
}
}
walletOptions.balanceCache[address] =
globalBalance.data!['transferableBalance']!;
if (walletOptions.balanceCache[address] != -1) {
return Row(children: [
Text(
walletOptions.balanceCache[address]!.toString(),
style: TextStyle(
fontSize: isTall ? size : size * 0.9,
color: color,
),
),
const SizedBox(width: 5),
UdUnitDisplay(size: size, color: color),
]);
} else {
return const Text('');
}
});
}),
]);
}
}

Some files were not shown because too many files have changed in this diff Show More