Compare commits
205 Commits
Author | SHA1 | Date |
---|---|---|
poka | 68c8a61939 | |
poka | 1878ea5f63 | |
poka | 41b9db0dfb | |
poka | 61d28e79d6 | |
pokapow | 4f07c390bd | |
Eloi Torrents | 58c82069d4 | |
pokapow | e0d1d3a085 | |
Eloi Torrents | 66dca555ab | |
pokapow | 54b721627b | |
Eloi Torrents | 985c888a47 | |
guenoel | cbeaacfca8 | |
guenoel | 32beb33be4 | |
guenoel | 459a76452b | |
guenoel | 57d68e012d | |
guenoel | ae30355b9b | |
pokapow | ebc69445ed | |
poka | be52158959 | |
poka | 228e556198 | |
poka | 2c7dcd0ee6 | |
poka | aa917b1c25 | |
poka | a0b0423856 | |
poka | 6443e04191 | |
poka | bf58e8e3d1 | |
poka | a0d6bfaf22 | |
poka | 0728bc6aba | |
poka | d927ccea39 | |
poka | 2b0a0428a0 | |
poka | eb9275fa84 | |
pokapow | 09e1592f55 | |
poka | a432db334d | |
poka | ad0019522f | |
poka | d76ad9b7e3 | |
poka | 8b32bb8e26 | |
poka | edbe1d8b5c | |
pokapow | 7f5dbf04ee | |
poka | 57cdc23436 | |
poka | 0233816f68 | |
poka | 776a0f8c75 | |
pokapow | 164fc16ed8 | |
poka | 83189990c6 | |
poka | 0d54030c1a | |
poka | 147557f545 | |
poka | fd281ad822 | |
poka | f7e3066352 | |
poka | e2ed9c5c98 | |
poka | 3825bf0488 | |
poka | e752de474d | |
poka | 23b6858a60 | |
poka | 8663186a4a | |
poka | f46acb23e4 | |
pokapow | 549996578b | |
poka | 34c69b64ee | |
poka | 0fe0c4d3c5 | |
poka | 03a9f1ea19 | |
poka | d9222fe6ba | |
poka | 58572a5e0e | |
Hugo Trentesaux | 7491b9b489 | |
poka | ad9ee382d3 | |
pokapow | e01dea9329 | |
poka | 425677827c | |
poka | a8dbf79eaa | |
poka | 37dee7f866 | |
poka | 9301eaf1a7 | |
poka | 939c6b3108 | |
poka | 03ab85a282 | |
poka | 525c375c71 | |
poka | 18743c871b | |
poka | 3761494606 | |
poka | aa7bc74645 | |
poka | 05f41e16a9 | |
poka | c060c85df8 | |
poka | 27e4de7254 | |
poka | a03f711539 | |
poka | fbc8cbd0d9 | |
poka | 5744155400 | |
poka | afae4130a6 | |
poka | fc80f5693c | |
poka | cbbd4eee34 | |
poka | dcb64c74b6 | |
poka | 9239901608 | |
poka | 3abf2666ba | |
poka | ebc33e4f6c | |
poka | 2facd8cd7f | |
poka | dd49e76fa1 | |
pokapow | 5369599b20 | |
poka | ae5fe3b128 | |
poka | 3100dc5126 | |
poka | 92992c2f69 | |
poka | ad601be19c | |
poka | c840753f4a | |
poka | 99f939d5a2 | |
poka | 506110cfc8 | |
poka | d42e715482 | |
poka | 237e581d0f | |
poka | 1b896960ea | |
poka | dbfd033fba | |
poka | 5ce381b174 | |
poka | 0983c1d01e | |
poka | 0687ae072f | |
poka | e8acb59f3e | |
poka | 1995aaf4fb | |
poka | 4a7f68626d | |
poka | 4d027e0555 | |
poka | 6af9199a76 | |
poka | 8a30ba70d7 | |
poka | 9a645e3733 | |
poka | 1ed9f3d460 | |
poka | b546078c8f | |
poka | eaf81aa701 | |
poka | 3fad0f03f0 | |
poka | edb8735109 | |
poka | 5b0ea1b2af | |
poka | d9aa66e1ec | |
poka | c6d5b30090 | |
poka | 7fd82df733 | |
pokapow | 6d55b551b1 | |
poka | 7b778a74b1 | |
poka | c603d2b201 | |
poka | 2d1b3731bb | |
poka | 99c559d38c | |
poka | cd91ea838b | |
poka | c487749f52 | |
poka | 2526f382f1 | |
poka | 2677cb8eb8 | |
poka | d71261d0ec | |
poka | 29754e23b5 | |
poka | 175334457a | |
poka | a88034b206 | |
poka | 81772f923a | |
poka | d8f3936e20 | |
poka | ef3ae9db4a | |
poka | 68175924cb | |
poka | dce9fc2117 | |
poka | fad6ebd878 | |
poka | 4fb40ff3f1 | |
poka | f44dd4aa76 | |
poka | 10eeeba601 | |
poka | a7d2e9a5d2 | |
poka | c203364dc3 | |
poka | 90f91be987 | |
pokapow | f3cb9faca7 | |
poka | e5ea67b6d0 | |
poka | c5960f8376 | |
poka | b975061a67 | |
poka | 0f43100969 | |
poka | c07cc9049b | |
poka | 5e5e6ee437 | |
pokapow | b2af9daa3b | |
poka | d1976db24a | |
cgeek | ec953b380a | |
poka | 183e89e32b | |
poka | 366d2712fa | |
poka | 39d87c765a | |
poka | d25ad55b02 | |
poka | 80ccc1f766 | |
poka | af3451b662 | |
poka | c58d859d07 | |
poka | fd9467ef79 | |
poka | e9c9019b50 | |
poka | 51894fe6be | |
poka | f02cd7d192 | |
poka | b7b01bc45f | |
poka | a64a3c6948 | |
poka | e71e00c995 | |
Hugo Trentesaux | 87a6f444b3 | |
Hugo Trentesaux | c04416ae0e | |
Hugo Trentesaux | c62c63f064 | |
Hugo Trentesaux | f688bc39c7 | |
poka | a4d72d036f | |
poka | 6f7dd4e413 | |
poka | 65f6f0a237 | |
poka | ad1a517553 | |
Hugo Trentesaux | 8555c579bd | |
poka | b89de85e90 | |
poka | 1c3aa6997b | |
poka | 431089f42e | |
poka | b03a280356 | |
poka | a4f5b44a13 | |
poka | 1c4da17db9 | |
poka | 4e9e2d40d1 | |
poka | 31619359d5 | |
poka | e62f8fa69e | |
poka | f509703084 | |
poka | 0781f26bc1 | |
poka | 0ada1635c6 | |
poka | e90e3063ae | |
poka | 58b6fba7ef | |
poka | 64e9ff1b44 | |
poka | d59d0c015a | |
poka | 05a7c82871 | |
poka | b196ed2bf1 | |
poka | 2ea2eeb255 | |
poka | d38cabe1eb | |
poka | 7f83965a8b | |
poka | cdfa62aad5 | |
poka | 86e2f3b2d7 | |
poka | 5ee80a5af4 | |
poka | 63c71fed01 | |
poka | 9ec7a6594d | |
poka | 1a49035cbf | |
poka | 7cbf328123 | |
poka | 7c11146278 | |
poka | 29505ad1be | |
poka | d62691d6f9 | |
poka | fd5504eadd |
|
@ -55,3 +55,9 @@ scripts/private/
|
|||
AppDir/
|
||||
appimage-builder-cache/
|
||||
AppImageBuilder.yml
|
||||
android/app/build.gradle
|
||||
integration_test/duniter/data/chains/
|
||||
|
||||
# Ignore PC deps
|
||||
macos/
|
||||
windows/
|
|
@ -5,7 +5,7 @@ stages:
|
|||
- package
|
||||
|
||||
.env:
|
||||
image: axiomteam/gecko-ci:v0.0.8
|
||||
image: axiomteam/gecko-ci:v0.0.11
|
||||
tags:
|
||||
- redshift
|
||||
|
||||
|
@ -17,6 +17,8 @@ format:
|
|||
- if: $CI_COMMIT_TAG || $CI_MERGE_REQUEST_ID
|
||||
- when: manual
|
||||
stage: format
|
||||
script:
|
||||
- flutter format --set-exit-if-changed lib
|
||||
|
||||
build_and_test:
|
||||
extends: .env
|
||||
|
@ -30,25 +32,6 @@ build_and_test:
|
|||
- redshift
|
||||
script:
|
||||
- flutter analyze
|
||||
# - flutter test
|
||||
|
||||
lint:
|
||||
extends: .env
|
||||
rules:
|
||||
- if: $CI_COMMIT_REF_NAME =~ /^wip*$/
|
||||
when: manual
|
||||
- if: $CI_COMMIT_TAG || $CI_MERGE_REQUEST_ID
|
||||
- when: manual
|
||||
stage: quality
|
||||
|
||||
audit_dependencies:
|
||||
extends: .env
|
||||
rules:
|
||||
- if: $CI_COMMIT_REF_NAME =~ /^wip*$/
|
||||
when: manual
|
||||
- if: $CI_COMMIT_TAG || $CI_MERGE_REQUEST_ID
|
||||
- when: manual
|
||||
stage: quality
|
||||
|
||||
releases:test:
|
||||
extends: .env
|
||||
|
|
24
.metadata
|
@ -1,10 +1,30 @@
|
|||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
# This file should be version controlled.
|
||||
|
||||
version:
|
||||
revision: 1aafb3a8b9b0c36241c5f5b34ee914770f015818
|
||||
revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
||||
channel: stable
|
||||
|
||||
project_type: app
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
||||
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
||||
- platform: android
|
||||
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
||||
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
||||
|
|
33
README.md
|
@ -10,12 +10,9 @@ The development is quite early, you can participate in the discussion [on the Du
|
|||
|
||||
<div align="center">
|
||||
|
||||
![Demo Gif](https://git.p2p.legal/axiom-team/gecko/raw/branch/master/assets/Demo-0.0.1+0.gif)
|
||||
![Demo Gif](https://git.duniter.org/clients/gecko/-/raw/master/images/demo-0.0.9+2.gif)
|
||||
|
||||
<br><br>
|
||||
|
||||
![Foo](https://git.p2p.legal/axiom-team/gecko/raw/commit/1cd2d63fe02949edabb69aa5fc498512c01db416/images/art/bb_gecko.png)
|
||||
|
||||
</div>
|
||||
|
||||
## Develop
|
||||
|
@ -89,30 +86,4 @@ then
|
|||
|
||||
## Roadmap
|
||||
|
||||
- v0.1.0 (expected date: 21-08-16)
|
||||
- Reorganization of persistent data
|
||||
- Complete implementation of Figma model (made by Boris)
|
||||
- Account management (creation, security)
|
||||
- Payment (QR-code generation / reading, form)
|
||||
- Viewing transaction history
|
||||
- Finalization of integration tests and unit tests
|
||||
- Completing the network scan when starting the application
|
||||
- F-Droid publication
|
||||
- v1.0
|
||||
- Multi-vault management
|
||||
- Cesium import
|
||||
- Advanced search
|
||||
- Item basket management
|
||||
- Transaction monitoring
|
||||
- Contacts / Messaging
|
||||
- IOS compatibility
|
||||
- Sharding (sharing of key fragments)
|
||||
- Apple AppStore and Google PlayStore publication
|
||||
- Mock-up and UX design of future functionalities
|
||||
- v2.0
|
||||
- Opaque bypass
|
||||
- NFC payment
|
||||
- Desktop compatibility
|
||||
- Web of trust management (certifications, promises of certifications)
|
||||
- Calendar / community
|
||||
|
||||
-> https://pad.p2p.legal/gecko-roadmap-2022?view
|
||||
|
|
|
@ -32,7 +32,7 @@ if (keystorePropertiesFile.exists()) {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 31
|
||||
compileSdkVersion 33
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
|
@ -46,7 +46,7 @@ android {
|
|||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "gecko.axiomteam.fr"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 31
|
||||
targetSdkVersion 33
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
multiDexEnabled true
|
||||
|
@ -66,7 +66,6 @@ android {
|
|||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig signingConfigs.release //poka: comment this to build unsigned release, or set to signingConfigs.debug to sign with debug keys
|
||||
useProguard true
|
||||
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
<activity
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:name=".MainActivity"
|
||||
android:resource="@style/NormalTheme"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/LaunchTheme"
|
||||
|
@ -42,6 +41,10 @@
|
|||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.yalantis.ucrop.UCropActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
<meta-data
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package gecko.axiomteam.gecko
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="?android:colorBackground" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
</layer-list>
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
|
@ -1,12 +1,12 @@
|
|||
buildscript {
|
||||
ext.kotlin_version = '1.6.10'
|
||||
ext.kotlin_version = '1.7.10'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.0.1'
|
||||
classpath 'com.android.tools.build:gradle:7.2.2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.enableR8=true
|
||||
|
|
|
@ -3,4 +3,5 @@ distributionBase=GRADLE_USER_HOME
|
|||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
|
||||
|
||||
|
|
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 3.6 MiB |
After Width: | Height: | Size: 238 KiB |
Before Width: | Height: | Size: 211 KiB After Width: | Height: | Size: 211 KiB |
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 166 KiB |
After Width: | Height: | Size: 166 KiB |
After Width: | Height: | Size: 166 KiB |
After Width: | Height: | Size: 2.2 KiB |
|
@ -0,0 +1,199 @@
|
|||
{
|
||||
"searchWallet": "Search\nwallet",
|
||||
"manageWallets": "Manage\nwallets",
|
||||
"scanQRCode": "Scan a\nQR code",
|
||||
"wellConnectedToNode": "You are well connected to node\n{}",
|
||||
"networkLost": "Network has been lost...",
|
||||
"noDuniterEndointAvailable": "No server available...",
|
||||
"connectionPending": "Connection pending...",
|
||||
"noLizard": "no lounge lizard ;-)",
|
||||
"loading": "Loading...",
|
||||
"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.",
|
||||
"fastAppDescription": "The {} app payment\nfaster than a reptile of Vietnam",
|
||||
"createWallet": "Create a wallet",
|
||||
"restoreWallet": "Restore my wallets",
|
||||
"parameters": "Parameters",
|
||||
"chooseAnotherMnemonic": "Choose an other\nmnemonic sentence",
|
||||
"iNotedMyMnemonic": "I wrote down my sentence",
|
||||
"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": "My root wallet",
|
||||
"currentWallet": "My current chest",
|
||||
"wallet": "Wallet",
|
||||
"displayMnemonic": "Display my mnemonic sentence",
|
||||
"changePassword": "Change my password",
|
||||
"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": "Choose this wallet",
|
||||
"thisWalletIsDefault": "This wallet is the default one",
|
||||
"defineWalletAsDefault": "Define this as the default one",
|
||||
"displayActivity": "Display activity",
|
||||
"displayNActivity": "Display\nactivity",
|
||||
"memberValidated": "Validated member!",
|
||||
"copyAddress": "Copy\naddress",
|
||||
"copy": "Copy",
|
||||
"thisAddressHasBeenCopiedToClipboard": "This address has been copied to clipboard",
|
||||
"chooseWalletName": "Choose a new name\nfor your wallet:",
|
||||
"choosePassword": "Choose a random password:",
|
||||
"chooseDerivation": "Choose a derivation:",
|
||||
"validate": "Validate",
|
||||
"confirm": "Confirm",
|
||||
"confirmPayment": "Confirm payment",
|
||||
"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.",
|
||||
"chooseAnotherPassword": "Choose an other password",
|
||||
"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": "Yes",
|
||||
"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",
|
||||
"continue": "Continue",
|
||||
"itsTheGoodWord": "It's the good word!",
|
||||
"nthMnemonicWord": "word of your mnemonic",
|
||||
"1th": "First",
|
||||
"2th": "Second",
|
||||
"3th": "Third",
|
||||
"4th": "Fourth",
|
||||
"5th": "Fifth",
|
||||
"6th": "Sixth",
|
||||
"7th": "Seventh",
|
||||
"8th": "Eighth",
|
||||
"9th": "Ninth",
|
||||
"10th": "Tenth",
|
||||
"11th": "Eleventh",
|
||||
"12th": "Twelfth",
|
||||
"yourPasswordLengthIsX": "Your password length is {}",
|
||||
"noIdentity": "No identity",
|
||||
"identityCreated": "Identity created",
|
||||
"identityConfirmed": "Identity confirmed",
|
||||
"identityExpired": "Identity expired",
|
||||
"confirmYourIdentity": "Confirm your identity",
|
||||
"noDuniterNodeAvailableTryLater": "No Duniter node available, please try again later",
|
||||
"youAreConnectedToNode": "You are connected to node",
|
||||
"accountActivity": "Account activity",
|
||||
"noNetworkNoHistory": "Network state does not allow\nto display account history",
|
||||
"noDataToDisplay": "No data to be displayed.",
|
||||
"noTransactionToDisplay": "No transaction to display",
|
||||
"month1": "January",
|
||||
"month2": "February",
|
||||
"month3": "March",
|
||||
"month4": "April",
|
||||
"month5": "May",
|
||||
"month6": "June",
|
||||
"month7": "July",
|
||||
"month8": "August",
|
||||
"month9": "September",
|
||||
"month10": "October",
|
||||
"month11": "November",
|
||||
"month12": "December",
|
||||
"today": "Today",
|
||||
"yesterday": "Yesterday",
|
||||
"thisWeek": "This week",
|
||||
"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": "You are not connected to internet",
|
||||
"researchResults": "Results of your research",
|
||||
"resultsFor": "Results for ",
|
||||
"forgetAllMyChests": "Forget all my chests",
|
||||
"transaction": "Transaction",
|
||||
"certification": "Certification",
|
||||
"identityConfirm": "Identity confirmation",
|
||||
"revokeAdhesion": "Adhesion revocation",
|
||||
"strangeTransaction": "Strange transaction",
|
||||
"sending": "Sending...",
|
||||
"propagating": "Propagating...",
|
||||
"validating": "Validating...",
|
||||
"anErrorOccurred": "An error occurred",
|
||||
"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": "See a wallet",
|
||||
"mustWaitXBeforeCertify": "You have to wait\n{} before\ncertifying again",
|
||||
"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",
|
||||
"seconds": "{} seconds",
|
||||
"minutes": "{} minutes",
|
||||
"hours": "{} hours {}",
|
||||
"days": "{} days",
|
||||
"months": "{} months",
|
||||
"certify": "Certify",
|
||||
"from": "From:",
|
||||
"to": "To:",
|
||||
"amount": "Amount:",
|
||||
"choiceOfSourceWallet": "Choose a source wallet",
|
||||
"extrinsicInProgress": "{} in progress",
|
||||
"extrinsicValidated": "{} validated !",
|
||||
"fromMinus": "from",
|
||||
"toMinus": "to",
|
||||
"deleteThisWallet": "Delete this wallet",
|
||||
"cancel": "Cancel",
|
||||
"inBlockchainResult": "In {} blockchain",
|
||||
"search": "Search",
|
||||
"currencyNode": "{} node :",
|
||||
"contactsManagementWithNbr": "My contacts ({})",
|
||||
"contactsManagement": "My contacts",
|
||||
"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": "Enter your Cesium ID",
|
||||
"enterCesiumPassword": "Enter your Cesium password",
|
||||
"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 !",
|
||||
"confirmMyIdentity": "Confirm my identity",
|
||||
"revokeMyIdentity": "Revoke my identity",
|
||||
"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"
|
||||
}
|
|
@ -0,0 +1,199 @@
|
|||
{
|
||||
"searchWallet": "Buscar\nbilletera",
|
||||
"manageWallets": "Gestionar\nbilleteras",
|
||||
"scanQRCode": "Escanear un\ncódigo QR",
|
||||
"wellConnectedToNode": "Estas bien conectada 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.",
|
||||
"fastAppDescription": "La aplicación de pago {}\nmás rápida que un reptil de Vietnam",
|
||||
"createWallet": "Crear una billetera",
|
||||
"restoreWallet": "Restaurar mis billeteras",
|
||||
"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",
|
||||
"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",
|
||||
"memberValidated": "Miembro validado!",
|
||||
"copyAddress": "Copiar\ndirecció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:",
|
||||
"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.",
|
||||
"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",
|
||||
"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",
|
||||
"continue": "Continuar",
|
||||
"itsTheGoodWord": "It's the good word!",
|
||||
"nthMnemonicWord": "word of your mnemonic",
|
||||
"1th": "Primera",
|
||||
"2th": "Segunda",
|
||||
"3th": "Tercera",
|
||||
"4th": "Cuarta",
|
||||
"5th": "Quinta",
|
||||
"6th": "Sexta",
|
||||
"7th": "Séptima",
|
||||
"8th": "Octava",
|
||||
"9th": "Novena",
|
||||
"10th": "Décima",
|
||||
"11th": "Undécima",
|
||||
"12th": "Duodécima",
|
||||
"yourPasswordLengthIsX": "La longitud de tu contraseña es {}",
|
||||
"noIdentity": "No identity",
|
||||
"identityCreated": "Identidad creada",
|
||||
"identityConfirmed": "Identidad confirmada",
|
||||
"identityExpired": "Identitdad caducada",
|
||||
"confirmYourIdentity": "Confirma tu identidad",
|
||||
"noDuniterNodeAvailableTryLater": "No Duniter node available, please try again later",
|
||||
"youAreConnectedToNode": "You are connected to node",
|
||||
"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",
|
||||
"month1": "Enero",
|
||||
"month2": "Febrero",
|
||||
"month3": "Marzo",
|
||||
"month4": "Abril",
|
||||
"month5": "Mayo",
|
||||
"month6": "Junio",
|
||||
"month7": "Julio",
|
||||
"month8": "Agosto",
|
||||
"month9": "Septiembre",
|
||||
"month10": "Octubre",
|
||||
"month11": "Noviembre",
|
||||
"month12": "Diciembre",
|
||||
"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",
|
||||
"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",
|
||||
"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",
|
||||
"seconds": "{} segundos",
|
||||
"minutes": "{} minutos",
|
||||
"hours": "{} horas {}",
|
||||
"days": "{} dias",
|
||||
"months": "{} meses",
|
||||
"certify": "Certify",
|
||||
"from": "De:",
|
||||
"to": "A:",
|
||||
"amount": "Importe:",
|
||||
"choiceOfSourceWallet": "Choose a source wallet",
|
||||
"extrinsicInProgress": "{} en progreso",
|
||||
"extrinsicValidated": "{} validado !",
|
||||
"fromMinus": "de",
|
||||
"toMinus": "a",
|
||||
"deleteThisWallet": "Delete this wallet",
|
||||
"cancel": "Cancelar",
|
||||
"inBlockchainResult": "In {} blockchain",
|
||||
"search": "Buscar",
|
||||
"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 !",
|
||||
"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"
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
{
|
||||
"searchWallet": "Rechercher un\nportefeuille",
|
||||
"manageWallets": "Gérer mes\nportefeuilles",
|
||||
"scanQRCode": "Scanner un\nQR code",
|
||||
"wellConnectedToNode": "Vous êtes bien connecté aux noeud\n{}",
|
||||
"networkLost": "Le réseau a été perdu...",
|
||||
"noDuniterEndointAvailable": "Aucun serveur disponible...",
|
||||
"connectionPending": "Connexion en cours...",
|
||||
"noLizard": "y'a pas de lézard ;-)",
|
||||
"loading": "Chargement en cours...",
|
||||
"forgot_password.png": "forgot_password_fr.png",
|
||||
"warningForgotPassword": "Dans une blockchain, pas de procédure de récupération par mail. Seule votre phrase de restauration peut vous permettre de récupérer vos Ğ1 à tout moment.",
|
||||
"fastAppDescription": "L’application de paiement {}\nplus rapide qu’un reptile du Vietnam",
|
||||
"createWallet": "Créer un portefeuille",
|
||||
"restoreWallet": "Restaurer mes portefeuilles",
|
||||
"parameters": "Paramètres",
|
||||
"chooseAnotherMnemonic": "Choisir une autre phrase",
|
||||
"iNotedMyMnemonic": "J'ai noté ma phrase",
|
||||
"printMyMnemonic": "Imprimer ma phrase de restauration",
|
||||
"manageChest": "Paramétrer ce coffre",
|
||||
"changeChest": "Changer de coffre",
|
||||
"geckoChest": "Coffre à Ğecko",
|
||||
"toUnlockEnterPassword": "Pour déverrouiller votre coffre, composez votre code secret à l’abri des lézards indiscrets :",
|
||||
"rememberPassword": "Garder ce code en mémoire 15 minutes",
|
||||
"myRootWallet": "Mon portefeuille racine",
|
||||
"currentWallet": "Mon portefeuille courant",
|
||||
"wallet": "Portefeuille",
|
||||
"displayMnemonic": "Afficher ma phrase de restauration",
|
||||
"changePassword": "Changer mon code secret",
|
||||
"createDerivation": "Créer une autre dérivation",
|
||||
"createCustomDerivation": "Créer une dérivation personnalisé",
|
||||
"deleteChest": "Supprimer ce coffre",
|
||||
"openThisChest": "Ouvrir ce coffre",
|
||||
"createChest": "Créer un nouveau coffre",
|
||||
"importChest": "Importer un coffre",
|
||||
"selectMyChest": "Sélectionner mon coffre",
|
||||
"accessMyChest": "Accéder à mon coffre",
|
||||
"manageMembership": "Gérer mon adhésion",
|
||||
"chooseThisWallet": "Choisir ce portefeuille",
|
||||
"thisWalletIsDefault": "Ce portefeuille est celui par defaut",
|
||||
"defineWalletAsDefault": "Définir comme portefeuille par défaut",
|
||||
"displayActivity": "Voir l'activité",
|
||||
"displayNActivity": "Voir\nl'activité",
|
||||
"memberValidated": "Membre validé !",
|
||||
"copyAddress": "Copier\nl'adresse",
|
||||
"copy": "Copier",
|
||||
"thisAddressHasBeenCopiedToClipboard": "Cette adresse a été copié dans votre presse-papier.",
|
||||
"chooseWalletName": "Choisissez un nouveau nom\npour votre portefeuille :",
|
||||
"choosePassword": "Choisissez un code secret autogénéré :",
|
||||
"chooseDerivation": "Choisissez une dérivation:",
|
||||
"validate": "Valider",
|
||||
"confirm": "Confirmer",
|
||||
"confirmPayment": "Confirmer le paiement",
|
||||
"geckoGenerateYourWalletFromMnemonic": "Ğecko fabrique votre portefeuille à partir d’une **phrase de restauration**. Elle est un peu comme le plan qui permet de construire votre portefeuille.",
|
||||
"keepThisMnemonicSecure": "Conservez cette phrase précieusement, car sans elle Ğecko ne pourra pas reconstruire vos portefeuilles le jour où vous changez de téléphone.",
|
||||
"geckoGeneratedYourMnemonicKeepItSecret": "Gecko a généré votre phrase de restauration ! Tâchez de la garder bien secrète, car elle permet à quiconque la connaît d’accéder à tous vos portefeuilles.",
|
||||
"newWallet": "Nouveau portefeuille",
|
||||
"itsTimeToUseAPenAndPaper": "Il est temps de vous munir d’**un papier et d’un crayon** afin de pouvoir noter votre phrase de restauration.",
|
||||
"yourMnemonic": "Votre phrase de restauration",
|
||||
"gecko_also_can_forget.png": "gecko_also_can_forget_fr.png",
|
||||
"didYouNoteMnemonicToBeSureTypeWord": "Avez-vous bien noté votre phrase de restauration ?\n\nPour en être sûr, veuillez taper dans le champ ci-dessous le **{}ème mot** de votre phrase de restauration :",
|
||||
"geckoWillGenerateAPassword": "Gecko va maintenant générer pour vous un code secret court qui vous permettra d’accéder rapidement à vos portefeuilles, sans avoir à taper votre phrase de restauration à chaque fois.",
|
||||
"myPassword": "Mon code secret",
|
||||
"thisPasswordProtectsYourWalletsInASecureChest": "Ce code secret protège vos portefeuilles dans un coffre-fort **dont vous seul possédez le code**, de sorte que vos portefeuilles seront inutilisables par d’autres.",
|
||||
"hereIsThePasswordKeepIt": "Et voilà votre code secret !\n\nMémorisez-le ou notez-le, car il vous sera demandé **à chaque fois** que vous voudrez effectuer un paiement sur cet appareil.",
|
||||
"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 l’avez bien noté.",
|
||||
"yourChestAndWalletWereCreatedSuccessfully": "Top !\n\nVotre coffre votre premier portefeuille ont été créés avec un immense succès.\n\nFélicitations !",
|
||||
"allGood": "C’est 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{}",
|
||||
"yes": "Oui",
|
||||
"no": "Non",
|
||||
"keepYourMnemonicSecret": "Tâchez de garder cette phrase bien secrète, car elle permet à quiconque la connaît d’accéder à tous vos portefeuilles.",
|
||||
"iGeneratedYourMnemonicKeepItSecret": "J’ai généré votre phrase de restauration !\nTâchez de la garder bien secrète, car elle permet à quiconque la connaît d’accéder à tous vos portefeuilles.",
|
||||
"myMnemonic": "Ma phrase de restauration",
|
||||
"close": "Fermer",
|
||||
"toRestoreEnterMnemonic": "Pour restaurer vos portefeuilles Gecko, rentrez dans les champs ci-dessous les 12 mots qui constituent votre phrase de restauration :",
|
||||
"pasteFromClipboard": "Coller depuis le\npresse-papier",
|
||||
"restoreAChest": "Restaurer un coffre",
|
||||
"restoreThisChest": "Restaurer ce coffre",
|
||||
"continue": "Continuer",
|
||||
"itsTheGoodWord": "C'est le bon mot !",
|
||||
"nthMnemonicWord": "mot de votre phrase de restauration",
|
||||
"1th": "Premier",
|
||||
"2th": "Deuxième",
|
||||
"3th": "Troisième",
|
||||
"4th": "Quatrième",
|
||||
"5th": "Cinquième",
|
||||
"6th": "Sixième",
|
||||
"7th": "Septième",
|
||||
"8th": "Huitième",
|
||||
"9th": "Neuvième",
|
||||
"10th": "Dixième",
|
||||
"11th": "Onzième",
|
||||
"12th": "Douzième",
|
||||
"yourPasswordLengthIsX": "Votre code PIN fait {} caractères",
|
||||
"noIdentity": "Aucune identité",
|
||||
"identityCreated": "Identité créée",
|
||||
"identityConfirmed": "Identité confirmée",
|
||||
"identityExpired": "Identité expirée",
|
||||
"confirmYourIdentity": "Confirmez votre identité",
|
||||
"noResult": "Aucun résultat",
|
||||
"noDuniterNodeAvailableTryLater": "Aucun noeud Duniter disponible, veuillez réessayer ultérieurement",
|
||||
"youAreConnectedToNode": "Vous êtes connecté au noeud",
|
||||
"accountActivity": "Activité du compte",
|
||||
"noNetworkNoHistory": "L'état du réseau ne permet pas\nd'afficher l'historique du compte",
|
||||
"noDataToDisplay": "Aucune donnée à afficher.",
|
||||
"noTransactionToDisplay": "Aucune transaction à afficher",
|
||||
"month1": "Janvier",
|
||||
"month2": "Février",
|
||||
"month3": "Mars",
|
||||
"month4": "Avril",
|
||||
"month5": "Mai",
|
||||
"month6": "Juin",
|
||||
"month7": "Juillet",
|
||||
"month8": "Aout",
|
||||
"month9": "Septembre",
|
||||
"month10": "Octobre",
|
||||
"month11": "Novembre",
|
||||
"month12": "Décembre",
|
||||
"today": "Aujourd'hui",
|
||||
"yesterday": "Hier",
|
||||
"thisWeek": "Cette semaine",
|
||||
"chestNotCompatibleMustReinstallGecko": "La version de vos coffres n'est plus comptabile avec cette version de Ğecko.\nTous vos coffres vont être oubliés, vous devez les importer de nouveau.",
|
||||
"notConnectedToInternet": "Vous n'êtes pas connecté à internet",
|
||||
"researchResults": "Résultats de votre recherche",
|
||||
"resultsFor": "Résultats pour ",
|
||||
"forgetAllMyChests": "Oublier tous mes coffres",
|
||||
"transaction": "Transaction",
|
||||
"certification": "Certification",
|
||||
"identityConfirm": "Confirmation d'identité",
|
||||
"revokeAdhesion": "Révocation d'adhésion",
|
||||
"strangeTransaction": "Transaction étrange",
|
||||
"sending": "Envoi en cours...",
|
||||
"propagating": "En cours de propagation...",
|
||||
"validating": "En cours de validation...",
|
||||
"anErrorOccurred": "Une erreur s'est produite",
|
||||
"24hbetweenCerts": "Vous devez attendre 24h entre chaque certification",
|
||||
"canNotCertifySelf": "Vous ne pouvez pas vous certifier\nvous même ...",
|
||||
"nameAlreadyExist": "Ce nom est déjà pris",
|
||||
"2GDtoKeepAlive": "Vous devez garder au moins 2ĞD sur votre compte pour le garder actif",
|
||||
"youHaveToFeedThisAccountBeforeUsing": "Vous devez alimenter ce compte avant\nde pouvoir l'utiliser",
|
||||
"execTimeoutOver": "Le délais d'éxecution est dépassé",
|
||||
"seeAWallet": "Voir un portefeuille",
|
||||
"mustWaitXBeforeCertify": "Vous devez attendre\n{} avant\nde pouvoir certifier",
|
||||
"mustConfirmHisIdentity": "Cette personne doit confirmer\nson identité avant de pouvoir\nêtre certifié",
|
||||
"canRenewCertInX": "Vous pourrez renouveler\ncette certification\ndans {}",
|
||||
"executeATransfer": "Effectuer un virement",
|
||||
"executeTheTransfer": "Effectuer le virement",
|
||||
"doATransfer": "Faire un\nvirement",
|
||||
"seconds": "{} secondes",
|
||||
"minutes": "{} minutes",
|
||||
"hours": "{} heures {}",
|
||||
"days": "{} jours",
|
||||
"months": "{} mois",
|
||||
"certify": "Certifier",
|
||||
"from": "Depuis:",
|
||||
"to": "Vers:",
|
||||
"amount": "Montant:",
|
||||
"choiceOfSourceWallet": "Choix du portefeuille source",
|
||||
"extrinsicInProgress": "{} en cours",
|
||||
"extrinsicValidated": "{} validé !",
|
||||
"fromMinus": "de",
|
||||
"toMinus": "vers",
|
||||
"deleteThisWallet": "Supprimer ce portefeuille",
|
||||
"cancel": "Annuler",
|
||||
"inBlockchainResult": "Dans la blockchain {}",
|
||||
"search": "Rechercher",
|
||||
"currencyNode": "Noeud {} :",
|
||||
"contactsManagementWithNbr": "Mes contacts ({})",
|
||||
"contactsManagement": "Mes contacts",
|
||||
"noContacts": "Vous n'avez aucun contact",
|
||||
"addContact": "Ajouter\naux contacts",
|
||||
"removeContact": "Supprimer\nce contact",
|
||||
"derivationsScanProgress": "Scan de l'adresse {}/{}",
|
||||
"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",
|
||||
"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",
|
||||
"enterCesiumId": "Entrez votre identifiant Cesium",
|
||||
"enterCesiumPassword": "Entrez votre mot de passe Cesium",
|
||||
"migrateAccount": "Migrer le compte",
|
||||
"migrateIdentity": "Migrer l'identité",
|
||||
"identityMigration": "Migration de l'identité",
|
||||
"areYouSureMigrateIdentity": "Êtes-vous certain de vouloir migrer définitivement l'identité **{}** et son solde de **{}** ?",
|
||||
"someoneCreatedYourIdentity": "Quelqu'un a créé votre identité {} !",
|
||||
"confirmMyIdentity": "Confirmer mon identité",
|
||||
"revokeMyIdentity": "Révoquer mon identité",
|
||||
"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"
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
[
|
||||
"wss://gdev.librelois.fr/ws",
|
||||
"wss://gdev.1000i100.fr/ws",
|
||||
"wss://gdev.komun.org/ws"
|
||||
|
||||
"wss://gdev.p2p.legal/ws",
|
||||
"wss://gdev.librelois.fr/ws"
|
||||
]
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
[
|
||||
"https://gdev-indexer.p2p.legal",
|
||||
"https://idx.gdev.cgeek.fr",
|
||||
"https://duniter-indexer.coinduf.eu",
|
||||
"http://192.168.1.72:8080"
|
||||
]
|
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 5.6 KiB |
|
@ -0,0 +1,128 @@
|
|||
# Context des tests
|
||||
|
||||
Chaque test est précédé par le lancement d'un noeud Duniter v2s en docker [dont voici le compose](https://git.duniter.org/clients/gecko/-/blob/end2EndTests/integration_test/duniter/docker-compose.yml).
|
||||
|
||||
Voici le yaml de configuration de la monnaie de test éphémère: https://git.duniter.org/clients/gecko/-/blob/end2EndTests/integration_test/duniter/data/gecko_tests.json
|
||||
|
||||
|
||||
Voici le mnemonic de test utilisé:
|
||||
`pipe paddle ketchup filter life ice feel embody glide quantum ride usage`
|
||||
|
||||
Et les 5 premiers portefeuilles Gecko associés:
|
||||
```
|
||||
test1: 5FeggKqw2AbnGZF9Y9WPM2QTgzENS3Hit94Ewgmzdg5a3LNa
|
||||
test2: 5E4i8vcNjnrDp21Sbnp32WHm2gz8YP3GGFwmdpfg5bHd8Whb
|
||||
test3: 5FhTLzXLNBPmtXtDBFECmD7fvKmTtTQDtvBTfVr97tachA1p
|
||||
test4: 5DXJ4CusmCg8S1yF6JGVn4fxgk5oFx42WctXqHZ17mykgje5
|
||||
test5: 5Dq3giahrBfykJogPetZJ2jjSmhw49Fa7i6qKkseUvRJ2T3R
|
||||
```
|
||||
|
||||
Seul les 4 premiers sont membres au démarrage.
|
||||
|
||||
Voici le scénario de test principal que j'ai réalisé pour le moment
|
||||
|
||||
Scénario 1
|
||||
- Changer le noeud Duniter pour se connecter au nœud local (l'ip local est récupéré automatiquement, car le nœud est sur le host (votre pc), alors que l'app est dans son émulateur)
|
||||
- Importer le coffre de test
|
||||
- Effectuer une transaction du Portefeuille 1 (test1) vers le portefeuille 5 (test5)
|
||||
- Vérifier que les frais de créations de compte ont bien été prélevés
|
||||
- Certifier test5 avec test1, test2 et test3 et vérifier qu'il deviens bien membre
|
||||
- Créer 10 blocs, puis encore 10, puis 30 de plus et vérifier à chaque fois si le compte génère bien ses DU à la bonne valeur, réévaluation comprise au bloc 50.
|
||||
|
||||
Des vérifications sur l'état du texte affiché à l'écran ou des widgets affichés ou non sont fait entre chaque étapes pour vérifier que tout ce passe toujours bien.
|
||||
Si la moindre erreur intervient, le test s'arrête et vous informe de l'erreur en question.
|
||||
|
||||
Voici le code du test contenant ce scénario: https://git.duniter.org/clients/gecko/-/blob/end2EndTests/integration_test/gecko_complete.dart
|
||||
|
||||
Ce test dur environ 1 minutes et 15 seconds, compilation et lancement de nœud au démarrage inclus.
|
||||
|
||||
Voici le rendu (attention ça va assez vite ^^) :
|
||||
|
||||
|
||||
https://tube.p2p.legal/w/kMc5c8KnLi9BpwJrM4EnKX
|
||||
|
||||
On remarque notamment que des blocs sont créés uniquement et directement après un extrinsic lancé depuis l'app
|
||||
|
||||
---
|
||||
|
||||
# Tuto contributeurs
|
||||
|
||||
**Il n'est nécessaire ni de connaître le code de Ğecko, ni de connaître Dart/flutter pour écrire un nouveau scénario de test !**
|
||||
|
||||
Il vous suffit de comprendre par exemple cet extrait de code:
|
||||
|
||||
```
|
||||
// Copy test mnemonic in clipboard
|
||||
await clipCopy(testMnemonic);
|
||||
|
||||
// Open screen import chest
|
||||
await goKey(keyRestoreChest, duration: 0);
|
||||
|
||||
// Tap on button to paste mnemonic
|
||||
await goKey(keyPastMnemonic);
|
||||
|
||||
// Tap on next button 4 times to skip 3 screen
|
||||
await goKey(keyGoNext);
|
||||
await goKey(keyGoNext);
|
||||
await goKey(keyGoNext);
|
||||
await goKey(keyGoNext);
|
||||
|
||||
// Check if cached password checkbox is checked
|
||||
final isCached = await isIconPresent(Icons.check_box);
|
||||
|
||||
// If not, tap on to cache password
|
||||
if (!isCached) await goKey(keyCachePassword, duration: 0);
|
||||
|
||||
// Enter password
|
||||
await enterText(keyPinForm, 'AAAAA', 0);
|
||||
|
||||
// Check if string "Accéder à mon coffre" is present in screen
|
||||
await waitFor('Accéder à mon coffre');
|
||||
|
||||
// Go to wallets home
|
||||
await goKey(keyGoWalletsHome, duration: 0);
|
||||
|
||||
// Check if string "ĞD" is present in screen
|
||||
await waitFor('ĞD');
|
||||
|
||||
// Tap on add a new derivation button
|
||||
await addDerivation();
|
||||
|
||||
// Tap on Wallet 5
|
||||
await goKey(keyOpenWallet(test5.address));
|
||||
|
||||
// Copy address of Wallet 5
|
||||
await goKey(keyCopyAddress);
|
||||
|
||||
// Check if string "Cette adresse a été copié" is present in screen
|
||||
await waitFor('Cette adresse a été copié');
|
||||
|
||||
// Pop screen 2 time to go back home
|
||||
await goBack();
|
||||
await goBack();
|
||||
|
||||
// Create a new bloc (useless here, just to show you the method)
|
||||
await spawnBlock();
|
||||
|
||||
// Check if string "y'a pas de lézard" is present in screen
|
||||
await waitFor("y'a pas de lézard");
|
||||
```
|
||||
|
||||
Vous avez dans ce bout de code commenté tous ce dont vous avez besoin pour effectuer un test d'intégration dans Ğecko :slight_smile:
|
||||
|
||||
Vous trouverez toutes les clés de widgets disponibles dans l'app dans ce fichier: https://git.duniter.org/clients/gecko/-/blob/end2EndTests/lib/models/widgets_keys.dart
|
||||
|
||||
Ce sont ces clés qui vous permette d’interagir avec les widgets de l'app depuis votre test.
|
||||
|
||||
Pour créer un nouveau test **à partir de zero**, voici la marche à suivre:
|
||||
- Suivez [le readme](https://git.duniter.org/clients/gecko/-/blob/master/README.md) pour configurer votre environnement de développement et ainsi pouvoir lancer Ğecko en mode debug dans un émulateur.
|
||||
- Créer un nouveau fichier pour votre test dans le dossier `integration_test` (ici nous l’appellerons `mon_test.dart`)
|
||||
- Prenez exemple sur le fichier `gecko_complete.dart` pour écrire votre test
|
||||
- Lancer un émulateur android (1 seul)
|
||||
- Exécutez votre test ainsi: `./integration_test/launch_test.sh mon_test`
|
||||
|
||||
Créer toute sorte de tests imaginable dans Ğecko est très utile pour éviter un maximum les régressions de bugs entre les différentes versions.
|
||||
|
||||
Si vous avez envie de nous aider, que vous ne savez presque pas coder mais que vous êtes prêt à mettre un peu les mains dans la sauce, et que vous avez une idée de scénario à tester, alors n'hésitez pas, je répondrais à toutes vos questions :slight_smile:
|
||||
|
||||
A noter que ces tests permettent de tester Gecko mais aussi partiellement Duniter et l'indexer d'une même pierre.
|
|
@ -1,447 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'dart:io';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'package:gecko/main.dart' as app;
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
int globalTimeout = 2;
|
||||
group(
|
||||
'Gecko end-to-end tests',
|
||||
() {
|
||||
// First, define the Finders and use them to locate widgets from the
|
||||
// test suite. Note: the Strings provided to the `byValueKey` method must
|
||||
// be the same as the Strings we used for the Keys in step 1.
|
||||
// final manageWalletsFinder = find.byKey(Key('manageWallets'));
|
||||
// final buttonFinder = find.byValueKey('increment');
|
||||
|
||||
// FlutterDriver driver;
|
||||
WidgetTester tester;
|
||||
String pinCode;
|
||||
|
||||
// *** Global functions *** //
|
||||
|
||||
// Easy get text
|
||||
Future<String> getText(String text) async {
|
||||
Text resultText = tester.firstWidget(find.byKey(Key(text)));
|
||||
// Text pinCodeText = generatedPinFinder.evaluate().single.widget as Text;
|
||||
|
||||
return resultText.data;
|
||||
}
|
||||
|
||||
// Function to tap the widget by key
|
||||
Future tapOn(String key) async {
|
||||
await tester.tap(find.byKey(Key(key)));
|
||||
}
|
||||
|
||||
// Function to go back to previous screen
|
||||
Future goBack() async {
|
||||
await Process.run(
|
||||
'adb',
|
||||
<String>['shell', 'input', 'keyevent', 'KEYCODE_BACK'],
|
||||
runInShell: true,
|
||||
);
|
||||
}
|
||||
|
||||
// Easy sleep
|
||||
Future sleep(int _time) async {
|
||||
await Future.delayed(Duration(milliseconds: _time));
|
||||
}
|
||||
|
||||
// Test if widget exist on screen, return a boolean
|
||||
Future<bool> isPresent(String text,
|
||||
{Duration timeout = const Duration(seconds: 1)}) async {
|
||||
try {
|
||||
expect(text, findsOneWidget);
|
||||
return true;
|
||||
} catch (exception) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a derivation
|
||||
Future createDerivation(String _name) async {
|
||||
await tapOn('addDerivation');
|
||||
await sleep(100);
|
||||
|
||||
await tester.enterText(find.byKey(Key('DerivationNameKey')), _name);
|
||||
|
||||
await tapOn('validDerivation');
|
||||
await sleep(300);
|
||||
}
|
||||
|
||||
// Delete a derivation
|
||||
Future deleteWallet(bool _confirm) async {
|
||||
await tapOn('deleteWallet');
|
||||
await sleep(100);
|
||||
_confirm
|
||||
? await tapOn('confirmDeleting')
|
||||
: await tapOn('cancelDeleting');
|
||||
await sleep(300);
|
||||
}
|
||||
|
||||
// Delete all wallets
|
||||
Future deleteAllWallets() async {
|
||||
await tester.tap(find.byKey(Key('drawerMenu')));
|
||||
await sleep(300);
|
||||
await tester.tap(find.byKey(Key('parameters')));
|
||||
await sleep(300);
|
||||
await tester.tap(find.byKey(Key('deleteAllWallets')));
|
||||
await sleep(300);
|
||||
await tester.tap(find.byKey(Key('confirmDeletingAllWallets')));
|
||||
await sleep(300);
|
||||
}
|
||||
|
||||
// Fast creation of new Keychain
|
||||
Future<String> createNewKeychain(String name) async {
|
||||
await tapOn('drawerMenu');
|
||||
await sleep(300);
|
||||
await tapOn('parameters');
|
||||
await sleep(300);
|
||||
await tapOn('generateKeychain');
|
||||
expect(find.text(''), findsOneWidget);
|
||||
|
||||
pinCode = await getText('generatedPin');
|
||||
|
||||
await tapOn('storeKeychain');
|
||||
await sleep(100);
|
||||
await tester.enterText(find.byKey(Key('askedWord')), 'triche');
|
||||
await tapOn('walletName');
|
||||
await tester.enterText(find.byKey(Key('walletName')), 'name');
|
||||
await tapOn('confirmStorage');
|
||||
await sleep(300);
|
||||
return pinCode;
|
||||
}
|
||||
|
||||
// *** Begin of tests *** //
|
||||
|
||||
testWidgets('OnBoarding - Open wallets management', (
|
||||
WidgetTester tester, {
|
||||
timeout: Timeout.none,
|
||||
}) async {
|
||||
app.main();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// expect("y'a pas de lézard !", findsOneWidget);
|
||||
await tester.tap(find.byKey(Key('manageWallets')));
|
||||
|
||||
print(
|
||||
'####################################################################');
|
||||
|
||||
// If a wallet exist, go to delete theme all
|
||||
await tester.pumpAndSettle();
|
||||
if (!await isPresent(
|
||||
"Je ne connais pour l’instant aucun de vos portefeuilles.\n\nVous pouvez en créer un nouveau, ou bien importer un portefeuille Cesium existant.")) {
|
||||
await tester.pumpAndSettle();
|
||||
// await tester.pageBack();
|
||||
await goBack();
|
||||
|
||||
await sleep(500);
|
||||
await deleteAllWallets();
|
||||
|
||||
await sleep(300);
|
||||
await tester.tap(find.byKey(Key('manageWallets')));
|
||||
}
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Verify onboarding is starting, with text
|
||||
expect(
|
||||
"Je ne connais pour l’instant aucun de vos portefeuilles.\n\nVous pouvez en créer un nouveau, ou bien importer un portefeuille Cesium existant.",
|
||||
findsOneWidget);
|
||||
});
|
||||
|
||||
// test('OnBoarding - Go to create restore sentance', (
|
||||
// {timeout: Timeout.none}) async {
|
||||
// await tapOn('goStep1');
|
||||
// await tapOn('goStep2');
|
||||
// await tapOn('goStep3');
|
||||
// await tapOn('goStep4');
|
||||
// await tapOn('goStep5');
|
||||
// await tapOn('goStep6');
|
||||
|
||||
// expect(
|
||||
// "J’ai généré votre phrase de restauration !\nTâchez de la garder bien secrète, car elle permet à quiconque la connaît d’accéder à tous vos portefeuilles.",
|
||||
// findsOneWidget);
|
||||
// });
|
||||
|
||||
// test('OnBoarding - Generate sentance and confirme it', (
|
||||
// {timeout: Timeout.none}) async {
|
||||
// await tapOn('goStep7');
|
||||
|
||||
// await tester.pumpAndSettle();
|
||||
|
||||
// Future selectWord() async {
|
||||
// List words = [for (var i = 1; i <= 13; i += 1) i];
|
||||
|
||||
// for (var j = 1; j < 13; j++) {
|
||||
// words[j] = await getText('word$j');
|
||||
// }
|
||||
// expect(await getText('step7'),
|
||||
// "C'est le moment de noter votre phrase !");
|
||||
|
||||
// await tapOn('goStep8');
|
||||
// await sleep(200);
|
||||
|
||||
// String goodWord = words[int.parse(
|
||||
// await getText('askedWord'),
|
||||
// )];
|
||||
|
||||
// // Enter the expected word
|
||||
// await tester.enterText(find.byKey(Key('inputWord')), goodWord);
|
||||
|
||||
// // Check if word is valid
|
||||
// expect(find.text("C'est le bon mot !"), findsOneWidget);
|
||||
|
||||
// // Continue onboarding workflow
|
||||
// await tapOn('goStep9');
|
||||
// }
|
||||
|
||||
// await selectWord();
|
||||
|
||||
// //Go back 2 times to mnemonic generation screen
|
||||
// await goBack();
|
||||
// await goBack();
|
||||
// await sleep(100);
|
||||
|
||||
// // Generate 3 times mnemonic
|
||||
// await tapOn('generateMnemonic');
|
||||
// await tapOn('generateMnemonic');
|
||||
// await tapOn('generateMnemonic');
|
||||
// await sleep(500);
|
||||
|
||||
// await selectWord();
|
||||
// });
|
||||
// test('OnBoarding - Generate secret code and confirm it', (
|
||||
// {timeout: Timeout.none}) async {
|
||||
// expect(await getText('step9'),
|
||||
// "Super !\n\nJe vais maintenant créer votre code secret. \n\nVotre code secret chiffre votre trousseau de clefs, ce qui le rend inutilisable par d’autres, par exemple si vous perdez votre téléphone ou si on vous le vole.");
|
||||
|
||||
// await tapOn('goStep10');
|
||||
// await tapOn('goStep11');
|
||||
|
||||
// while (await getText('generatedPin') == '') {
|
||||
// print('Waiting for pin code generation...');
|
||||
// await sleep(100);
|
||||
// }
|
||||
|
||||
// // Change secret code 4 times
|
||||
// for (int i = 0; i < 4; i++) await tapOn('changeSecretCode');
|
||||
|
||||
// await sleep(500);
|
||||
// pinCode = await getText('generatedPin');
|
||||
|
||||
// await tapOn('goStep12');
|
||||
// await sleep(300);
|
||||
|
||||
// // //Enter bad secret code
|
||||
// // await tester.enterText('abcde');
|
||||
// // await tapOn('formKey');
|
||||
// // await sleep(1500);
|
||||
// // await tapOn('formKey2');
|
||||
|
||||
// //Enter good secret code
|
||||
// await tester.enterText(find.byKey(Key('formKey2')), pinCode);
|
||||
|
||||
// expect(await getText('step13'),
|
||||
// "Top !\n\nVotre trousseau de clef et votre portefeuille ont été créés avec un immense succès.\n\nFélicitations !");
|
||||
// });
|
||||
|
||||
// test('My wallets - Rename first derivation', (
|
||||
// {timeout: const Duration(seconds: 2)}) async {
|
||||
// await tapOn('goWalletHome');
|
||||
|
||||
// expect(await getText('myWallets'), "Mes portefeuilles");
|
||||
// await sleep(300);
|
||||
|
||||
// // Go to first derivation and rename it
|
||||
// await tester.tap(find.text('Mon portefeuille courant'));
|
||||
// await sleep(300);
|
||||
// await tapOn('renameWallet');
|
||||
// await sleep(100);
|
||||
// await tapOn('walletName');
|
||||
// await sleep(100);
|
||||
// await tester.enterText(
|
||||
// find.byKey(Key('walletName')), 'Renommage wallet 1');
|
||||
// await sleep(300);
|
||||
// await tapOn('renameWallet');
|
||||
// await sleep(400);
|
||||
// expect('Renommage wallet 1', findsOneWidget);
|
||||
// await goBack();
|
||||
// });
|
||||
|
||||
// test('My wallets - Create a derivations, open thems, tap all buttons', (
|
||||
// {timeout: const Duration(seconds: 2)}) async {
|
||||
// expect('Renommage wallet 1', findsOneWidget);
|
||||
|
||||
// // Add a second derivation
|
||||
// await createDerivation('Derivation 2');
|
||||
|
||||
// // Go to second derivation options
|
||||
// await tester.tap(find.text('Derivation 2'));
|
||||
// await sleep(100);
|
||||
|
||||
// // Test options
|
||||
// await tapOn('displayBalance');
|
||||
// await tapOn('displayHistory');
|
||||
// await sleep(300);
|
||||
// await goBack();
|
||||
// await tapOn('displayBalance');
|
||||
// await sleep(100);
|
||||
// await tapOn('displayBalance');
|
||||
// await sleep(100);
|
||||
// await tapOn('displayBalance');
|
||||
// await tapOn('setDefaultWallet');
|
||||
// await sleep(50);
|
||||
// await tapOn('copyPubkey');
|
||||
// expect('Cette clé publique a été copié dans votre presse-papier.',
|
||||
// findsOneWidget);
|
||||
// await goBack();
|
||||
|
||||
// // Add a third derivation
|
||||
// await createDerivation('Derivation 3');
|
||||
|
||||
// // Add a fourth derivation
|
||||
// await createDerivation('Derivation 4');
|
||||
// await sleep(50);
|
||||
|
||||
// // Go to third derivation options
|
||||
// await tester.tap(find.text('Derivation 3'));
|
||||
// await sleep(100);
|
||||
// await tapOn('displayBalance');
|
||||
|
||||
// // Delete third derivation
|
||||
// await deleteWallet(true);
|
||||
// });
|
||||
|
||||
// test('My wallets - Extra tests', (
|
||||
// {timeout: const Duration(seconds: 2)}) async {
|
||||
// // Add derivation 5,6 and 7
|
||||
// expect('Derivation 4', findsOneWidget);
|
||||
// await createDerivation('Derivation 5');
|
||||
// await createDerivation('Derivation 6');
|
||||
// await createDerivation('Derivation 7');
|
||||
|
||||
// // Go home and come back to my wallets view
|
||||
// await goBack();
|
||||
// await sleep(100);
|
||||
// await tapOn('manageWallets');
|
||||
// await sleep(200);
|
||||
// //Enter secret code
|
||||
// await tester.enterText(find.byKey(Key('formKey')), pinCode);
|
||||
// await sleep(200);
|
||||
|
||||
// // Go to derivation 6 and delete it
|
||||
// await tester.tap(find.text('Derivation 6'));
|
||||
// await sleep(100);
|
||||
// await deleteWallet(true);
|
||||
|
||||
// // Go to 2nd derivation and check if it's de default
|
||||
// await tester.tap(find.text('Derivation 2'));
|
||||
// expect('Ce portefeuille est celui par defaut', findsOneWidget);
|
||||
// await tapOn('setDefaultWallet');
|
||||
// await sleep(100);
|
||||
// expect('Ce portefeuille est celui par defaut', findsOneWidget);
|
||||
// await sleep(300);
|
||||
|
||||
// // Display history, copy pubkey, go back and rename wallet name
|
||||
// await tapOn('displayHistory');
|
||||
// await sleep(400);
|
||||
// await tapOn('copyPubkey');
|
||||
// expect('Cette clé publique a été copié dans votre presse-papier.',
|
||||
// findsOneWidget);
|
||||
// await sleep(800);
|
||||
// await goBack();
|
||||
// await sleep(300);
|
||||
// await tapOn('renameWallet');
|
||||
// await sleep(100);
|
||||
// await tapOn('walletName');
|
||||
// await sleep(100);
|
||||
// await tester.enterText(
|
||||
// find.byKey(Key('walletName')), 'Renommage wallet 2');
|
||||
// await sleep(300);
|
||||
// await tapOn('renameWallet');
|
||||
// await sleep(400);
|
||||
// await goBack();
|
||||
// expect('Renommage wallet 2', findsOneWidget);
|
||||
// await createDerivation('Derivation 8');
|
||||
// await createDerivation('Derivation 9');
|
||||
// await createDerivation('Derivation 10');
|
||||
// await createDerivation('Derivation 11');
|
||||
// await createDerivation('Derivation 12');
|
||||
// await createDerivation('Derivation 13');
|
||||
// await createDerivation('Derivation 14');
|
||||
// await createDerivation('Derivation 15');
|
||||
// await createDerivation('Derivation 16');
|
||||
// await createDerivation('Derivation 17');
|
||||
// await createDerivation('Derivation 18');
|
||||
// await createDerivation('Derivation 19');
|
||||
// await createDerivation('Derivation 20');
|
||||
// await sleep(400);
|
||||
|
||||
// // Scroll the wallet screen until Derivation 20 and open it
|
||||
// await tester.scrollUntilVisible(find.byKey(Key('listWallets')), -300.0);
|
||||
|
||||
// expect('Derivation 20', findsOneWidget);
|
||||
// await sleep(400);
|
||||
// await tester.tap(find.text('Derivation 20'));
|
||||
// await tapOn('copyPubkey');
|
||||
// });
|
||||
|
||||
// test('Search - Search Pi profile, navigate in history transactions', (
|
||||
// {timeout: const Duration(seconds: 2)}) async {
|
||||
// expect('Derivation 20', findsOneWidget);
|
||||
// await goBack();
|
||||
// await goBack();
|
||||
// await sleep(200);
|
||||
// await tapOn('searchIcon');
|
||||
// await sleep(400);
|
||||
// await tester.enterText(find.byKey(Key('searchInput')),
|
||||
// 'D2meevcAHFTS2gQMvmRW5Hzi25jDdikk4nC4u1FkwRaU');
|
||||
// await sleep(100);
|
||||
// await tapOn('copyPubkey');
|
||||
// await sleep(500);
|
||||
// await tapOn('switchPayHistory');
|
||||
// await sleep(1200);
|
||||
// // await tester.scrollIntoView(find.byValueKey('listTransactions'));
|
||||
// await tester.scrollUntilVisible(
|
||||
// find.byKey(Key('listTransactions')),
|
||||
// -600.0,
|
||||
// );
|
||||
// await sleep(100);
|
||||
// await tapOn('transaction33');
|
||||
// expect('Commentaire:', findsOneWidget);
|
||||
|
||||
// // Want to paste pubkey copied, but doesn't work actualy with flutter driver: https://github.com/flutter/flutter/issues/47448
|
||||
// // final ClipboardData pubkeyCopied =
|
||||
// // await Clipboard.getData(Clipboard.kTextPlain);
|
||||
// // await tester.enterText(pubkeyCopied.text);
|
||||
|
||||
// await sleep(300);
|
||||
// }, timeout: Timeout(Duration(minutes: globalTimeout)));
|
||||
|
||||
// test('Wallet generation - Fast wallets generations', (
|
||||
// {timeout: const Duration(seconds: 2)}) async {
|
||||
// expect('Commentaire:', findsOneWidget);
|
||||
// await goBack();
|
||||
// await goBack();
|
||||
// await deleteAllWallets();
|
||||
// await sleep(100);
|
||||
// final String pincode = await createNewKeychain('Fast wallet');
|
||||
// await sleep(100);
|
||||
// await tapOn('manageWallets');
|
||||
// await sleep(200);
|
||||
// await tester.enterText(find.byKey(Key('formKey')), pinCode);
|
||||
// await sleep(100);
|
||||
// await createDerivation('Derivation 2');
|
||||
// await sleep(100);
|
||||
// await tester.tap(find.text('Fast wallet'));
|
||||
// expect('Fast wallet', findsOneWidget);
|
||||
// // Wait 3 seconds at the end
|
||||
// await sleep(3000);
|
||||
// });
|
||||
},
|
||||
);
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
{
|
||||
"first_ud": 10000,
|
||||
"first_ud_reeval": 50,
|
||||
"genesis_parameters": {
|
||||
"genesis_certs_expire_on": 10,
|
||||
"genesis_certs_min_received": 3,
|
||||
"genesis_memberships_expire_on": 1051200,
|
||||
"genesis_smith_certs_expire_on": 2102400,
|
||||
"genesis_smith_certs_min_received": 3,
|
||||
"genesis_smith_memberships_expire_on": 1051200
|
||||
},
|
||||
"identities": {
|
||||
"test1": {
|
||||
"balance": 10000,
|
||||
"certs": ["test2", "test3", "test4"],
|
||||
"pubkey": "5FeggKqw2AbnGZF9Y9WPM2QTgzENS3Hit94Ewgmzdg5a3LNa"
|
||||
},
|
||||
"test2": {
|
||||
"balance": 10000,
|
||||
"certs": ["test1", "test3", "test4"],
|
||||
"pubkey": "5E4i8vcNjnrDp21Sbnp32WHm2gz8YP3GGFwmdpfg5bHd8Whb"
|
||||
},
|
||||
"test3": {
|
||||
"balance": 10000,
|
||||
"certs": ["test1", "test2", "test4"],
|
||||
"pubkey": "5FhTLzXLNBPmtXtDBFECmD7fvKmTtTQDtvBTfVr97tachA1p"
|
||||
},
|
||||
"test4": {
|
||||
"balance": 10000,
|
||||
"certs": ["test1", "test2", "test3"],
|
||||
"pubkey": "5DXJ4CusmCg8S1yF6JGVn4fxgk5oFx42WctXqHZ17mykgje5"
|
||||
},
|
||||
"testCesium1": {
|
||||
"balance": 10000,
|
||||
"certs": ["test1", "test2", "test3"],
|
||||
"pubkey": "5GAT6CJW8yVKwUuQc7sM5Kk9GZVTpbZYk9PfjNXtvnNgAJZ1"
|
||||
}
|
||||
},
|
||||
"parameters": {
|
||||
"babe_epoch_duration": 30,
|
||||
"cert_period": 15,
|
||||
"cert_max_by_issuer": 10,
|
||||
"cert_min_received_cert_to_issue_cert": 2,
|
||||
"cert_validity_period": 1000,
|
||||
"idty_confirm_period": 40,
|
||||
"idty_creation_period": 50,
|
||||
"membership_period": 1000,
|
||||
"pending_membership_period": 500,
|
||||
"ud_creation_period": 10,
|
||||
"ud_reeval_period": 50,
|
||||
"smith_cert_period": 15,
|
||||
"smith_cert_max_by_issuer": 8,
|
||||
"smith_cert_min_received_cert_to_issue_cert": 2,
|
||||
"smith_cert_validity_period": 1000,
|
||||
"smith_membership_period": 1000,
|
||||
"smith_pending_membership_period": 500,
|
||||
"smiths_wot_first_cert_issuable_on": 4,
|
||||
"smiths_wot_min_cert_for_membership": 3,
|
||||
"wot_first_cert_issuable_on": 0,
|
||||
"wot_min_cert_for_create_idty_right": 3,
|
||||
"wot_min_cert_for_membership": 3
|
||||
},
|
||||
"smiths": {
|
||||
"test1": {
|
||||
"certs": ["test2", "test3", "test4"]
|
||||
},
|
||||
"test2": {
|
||||
"certs": ["test1", "test3", "test4"]
|
||||
},
|
||||
"test3": {
|
||||
"certs": ["test1", "test2", "test4"]
|
||||
},
|
||||
"test4": {
|
||||
"certs": ["test1", "test2", "test3"]
|
||||
}
|
||||
},
|
||||
"sudo_key": "5FeggKqw2AbnGZF9Y9WPM2QTgzENS3Hit94Ewgmzdg5a3LNa",
|
||||
"technical_committee": ["test1", "test2", "test3"]
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
version: "3.5"
|
||||
|
||||
services:
|
||||
duniter-v2s-gecko-tests:
|
||||
container_name: duniter-v2s-gecko-tests
|
||||
image: duniter/duniter-v2s:debug-latest
|
||||
command: --sealing=manual
|
||||
ports:
|
||||
- "127.0.0.1:9615:9615"
|
||||
- "127.0.0.1:9933:9933"
|
||||
- "0.0.0.0:9944:9944"
|
||||
- "30333:30333"
|
||||
environment:
|
||||
DUNITER_INSTANCE_NAME: "gecko_tests"
|
||||
DUNITER_CHAIN_NAME: "dev"
|
||||
DUNITER_GENESIS_CONFIG: "/var/lib/duniter/gecko_tests.json"
|
||||
volumes:
|
||||
- ./data:/var/lib/duniter
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
for test_file in $(ls integration_test/scenarios/); do
|
||||
testName=$(echo $test_file | awk -F '.' '{print $1}')
|
||||
./integration_test/launch_test.sh $testName || break
|
||||
done
|
|
@ -0,0 +1,29 @@
|
|||
#!/bin/bash
|
||||
|
||||
testName=$1
|
||||
option=$2
|
||||
[[ ! $testName ]] && testName='gecko_complete'
|
||||
|
||||
# Get local IP and set .env
|
||||
ip_address=$(hostname -I | awk '{print $1}')
|
||||
echo "ip_address=$ip_address" > .env
|
||||
[[ $option == 'human' ]] && echo "isHumanReading=true" >> .env
|
||||
|
||||
## Start local Duniter node
|
||||
cd integration_test/duniter
|
||||
docker compose down
|
||||
rm -rf data/chains
|
||||
docker compose up -d
|
||||
cd ../..
|
||||
|
||||
# Start integration test
|
||||
flutter test integration_test/scenarios/$testName.dart && echo '0' > /tmp/geckoTestResult || echo '1' > /tmp/geckoTestResult
|
||||
|
||||
# Reset .env
|
||||
echo "ip_address=127.0.0.1" > .env
|
||||
|
||||
# Stop Duniter
|
||||
cd integration_test/duniter
|
||||
docker compose down
|
||||
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:gecko/models/widgets_keys.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import '../utility/general_actions.dart';
|
||||
import '../utility/tests_utility.dart';
|
||||
|
||||
void main() async {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
await dotenv.load();
|
||||
|
||||
testWidgets('Certifications state', (testerLoc) async {
|
||||
tester = testerLoc;
|
||||
// Connect local node and import test chest in background
|
||||
await bkFastStart();
|
||||
|
||||
// Open chest
|
||||
await firstOpenChest();
|
||||
spawnBlock(until: 15);
|
||||
await goBack();
|
||||
|
||||
// Go wallet 5 view
|
||||
await tapKey(keyOpenSearch);
|
||||
await enterText(keySearchField, test5.address);
|
||||
await tapKey(keyConfirmSearch);
|
||||
await waitFor(test5.shortAddress());
|
||||
await tapKey(keySearchResult(test5.address));
|
||||
await waitFor('Certifier');
|
||||
await waitFor('Vous devez ', reverse: true);
|
||||
await waitFor('Vous pourrez renouveler ', reverse: true);
|
||||
|
||||
// Background pay 25
|
||||
await bkPay(
|
||||
fromAddress: test1.address, destAddress: test5.address, amount: 25);
|
||||
await waitFor('25.0', exactMatch: true);
|
||||
await spawnBlock();
|
||||
await waitFor('22.0', exactMatch: true);
|
||||
await bkCertify(
|
||||
fromAddress: test1.address,
|
||||
destAddress: test5.address,
|
||||
spawnBloc: false);
|
||||
await bkConfirmIdentity(fromAddress: test5.address, name: test5.name);
|
||||
await waitFor('1', exactMatch: true);
|
||||
await bkCertify(
|
||||
fromAddress: test2.address,
|
||||
destAddress: test5.address,
|
||||
spawnBloc: false);
|
||||
// await waitFor('2', exactMatch: true);
|
||||
await bkCertify(fromAddress: test3.address, destAddress: test5.address);
|
||||
await waitFor('3', exactMatch: true);
|
||||
await bkCertify(fromAddress: test4.address, destAddress: test5.address);
|
||||
await waitFor('4', exactMatch: true);
|
||||
// await bkPay(
|
||||
// fromAddress: test2.address, destAddress: test5.address, amount: 40);
|
||||
await waitFor('21.99', exactMatch: true);
|
||||
await spawnBlock(until: 30);
|
||||
await waitFor('121.99', exactMatch: true);
|
||||
await spawnBlock(until: 40);
|
||||
await waitFor('221.99', exactMatch: true);
|
||||
}, timeout: testTimeout());
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:gecko/models/widgets_keys.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import '../utility/general_actions.dart';
|
||||
import '../utility/tests_utility.dart';
|
||||
|
||||
void main() async {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
await dotenv.load();
|
||||
|
||||
testWidgets('Gecko complete', (testerLoc) async {
|
||||
// Share WidgetTester to test provider
|
||||
tester = testerLoc;
|
||||
|
||||
// Start app and wait finish starting
|
||||
await startWait();
|
||||
|
||||
// Change Duniter endpoint to local
|
||||
await changeNode();
|
||||
|
||||
// Delete all existing chests is exists
|
||||
await deleteAllWallets();
|
||||
|
||||
// Restore the test chest
|
||||
await restoreChest();
|
||||
|
||||
// Execute a transaction to test5
|
||||
await payTest2();
|
||||
|
||||
// Certify test5 account with 3 accounts to become member
|
||||
await certifyTest5();
|
||||
}, timeout: testTimeout());
|
||||
}
|
||||
|
||||
Future payTest2() async {
|
||||
spawnBlock(until: 13);
|
||||
await waitFor('Rechercher');
|
||||
await tapKey(keyOpenSearch);
|
||||
final addressToSearch = await clipPaste();
|
||||
final endAddress = addressToSearch.substring(addressToSearch.length - 6);
|
||||
expect(addressToSearch, test5.address);
|
||||
await enterText(keySearchField, addressToSearch);
|
||||
await tapKey(keyConfirmSearch);
|
||||
await waitFor(endAddress);
|
||||
await tapKey(keySearchResult(addressToSearch));
|
||||
await waitFor(endAddress);
|
||||
await waitFor('0.0', exactMatch: true);
|
||||
await tapKey(keyPay);
|
||||
await enterText(keyAmountField, '12.14');
|
||||
await tapKey(keyConfirmPayment);
|
||||
spawnBlock(duration: 500);
|
||||
|
||||
await waitFor('validé !', timeout: const Duration(seconds: 1));
|
||||
await tapKey(keyCloseTransactionScreen, duration: 0);
|
||||
await waitFor('12.14');
|
||||
spawnBlock(duration: 500);
|
||||
await waitFor('9.14');
|
||||
humanRead(2);
|
||||
}
|
||||
|
||||
Future certifyTest5() async {
|
||||
// Create identity with Test1 account
|
||||
await tapKey(keyCertify);
|
||||
await tapKey(keyConfirm);
|
||||
spawnBlock(duration: 500);
|
||||
await waitFor('validé !', timeout: const Duration(seconds: 1));
|
||||
await tapKey(keyCloseTransactionScreen);
|
||||
await waitFor('Identité créée');
|
||||
|
||||
// Confirm Identity Test5
|
||||
await tapKey(keyAppBarChest, duration: 300);
|
||||
await tapKey(keyOpenWallet(test5.address));
|
||||
await tapKey(keyCopyAddress);
|
||||
humanRead(3);
|
||||
await tapKey(keyConfirmIdentity);
|
||||
await enterText(keyEnterIdentityUsername, test5.name);
|
||||
await tapKey(keyConfirm);
|
||||
spawnBlock(duration: 500);
|
||||
await waitFor('validé !', timeout: const Duration(seconds: 1));
|
||||
await tapKey(keyCloseTransactionScreen);
|
||||
await waitFor('Identité confirmée');
|
||||
humanRead(2);
|
||||
// Set wallet 2 as default wallet
|
||||
await goBack();
|
||||
await tapKey(keyOpenWallet(test2.address));
|
||||
await tapKey(keySetDefaultWallet);
|
||||
await waitFor('Ce portefeuille est celui par defaut');
|
||||
|
||||
// Search Wallet 5 again
|
||||
await tapKey(keyAppBarSearch);
|
||||
final addressToSearch = await clipPaste();
|
||||
final endAddress = addressToSearch.substring(addressToSearch.length - 6);
|
||||
expect(addressToSearch, test5.address);
|
||||
await enterText(keySearchField, addressToSearch);
|
||||
await tapKey(keyConfirmSearch);
|
||||
await waitFor(endAddress);
|
||||
await tapKey(keySearchResult(addressToSearch));
|
||||
await waitFor(endAddress);
|
||||
await waitFor('1');
|
||||
|
||||
// Certify with test2 account
|
||||
await tapKey(keyCertify);
|
||||
await tapKey(keyConfirm);
|
||||
spawnBlock(duration: 500);
|
||||
await waitFor('validé !', timeout: const Duration(seconds: 1));
|
||||
await tapKey(keyCloseTransactionScreen);
|
||||
await waitFor('2');
|
||||
|
||||
// Change default wallet to test3
|
||||
await tapKey(keyPay);
|
||||
await tapKey(keyChangeChest);
|
||||
await tapKey(keySelectThisWallet(test3.address));
|
||||
await tapKey(keyConfirm);
|
||||
await sleep();
|
||||
|
||||
// Certify with test3 account
|
||||
await tapKey(keyCertify);
|
||||
await tapKey(keyConfirm);
|
||||
spawnBlock(duration: 500);
|
||||
await waitFor('validé !', timeout: const Duration(seconds: 1));
|
||||
await tapKey(keyCloseTransactionScreen);
|
||||
await waitFor('Vous devez attendre');
|
||||
|
||||
// Check if test5 is member
|
||||
await tapKey(keyAppBarChest, duration: 300);
|
||||
await tapKey(keyOpenWallet(test5.address));
|
||||
await waitFor('Membre validé !');
|
||||
|
||||
// spawn 20 blocs and check if ud is creating
|
||||
await spawnBlock(until: 20);
|
||||
await waitFor('109.13');
|
||||
await spawnBlock(until: 30);
|
||||
await waitFor('209.13');
|
||||
|
||||
// Check UD reval
|
||||
await spawnBlock(until: 60);
|
||||
await waitFor('509.57');
|
||||
humanRead(5);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:gecko/models/widgets_keys.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import '../utility/general_actions.dart';
|
||||
import '../utility/tests_utility.dart';
|
||||
|
||||
void main() async {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
await dotenv.load();
|
||||
|
||||
testWidgets('Identity revocation', (testerLoc) async {
|
||||
tester = testerLoc;
|
||||
// Connect local node and import test chest in background
|
||||
await bkFastStart();
|
||||
|
||||
// Open chest
|
||||
await firstOpenChest();
|
||||
await spawnBlock(until: 13);
|
||||
await sleep();
|
||||
|
||||
// Create test5 identity
|
||||
await bkPay(
|
||||
fromAddress: test1.address, destAddress: test5.address, amount: 30);
|
||||
sub.reload();
|
||||
await bkCertify(fromAddress: test1.address, destAddress: test5.address);
|
||||
sub.reload();
|
||||
await sleep();
|
||||
|
||||
// Certify test5 to become member
|
||||
await tapKey(keyOpenWallet(test5.address));
|
||||
await bkConfirmIdentity(fromAddress: test5.address, name: test5.name);
|
||||
await bkCertify(fromAddress: test2.address, destAddress: test5.address);
|
||||
await bkCertify(fromAddress: test3.address, destAddress: test5.address);
|
||||
await waitFor('Membre validé !', exactMatch: true);
|
||||
|
||||
// Revoke test5
|
||||
await tapKey(keyManageMembership, duration: 1000);
|
||||
await tapKey(keyRevokeIdty);
|
||||
await tapKey(keyConfirm);
|
||||
spawnBlock(duration: 2000);
|
||||
await waitFor('validé !', timeout: const Duration(seconds: 4));
|
||||
await tapKey(keyCloseTransactionScreen, duration: 0);
|
||||
await waitFor('Aucune identité', exactMatch: true);
|
||||
await sleep();
|
||||
|
||||
// Check test1 cannot be revoked
|
||||
await goBack();
|
||||
await tapKey(keyAddDerivation);
|
||||
await tapKey(keyOpenWallet(test1.address), duration: 500);
|
||||
await tapKey(keyManageMembership, duration: 1000);
|
||||
await waitFor('Vous ne pouvez pas révoquer cette identité');
|
||||
|
||||
// // Try migrate test1 identity to test6 address
|
||||
// await tapKey(keyMigrateIdentity);
|
||||
// await tapKey(keySelectWallet);
|
||||
// await tapKey(keySelectThisWallet(test6.address), selectLast: true);
|
||||
// await spawnBlock(number: 100);
|
||||
// await waitFor('Vous devez attendre', reverse: true);
|
||||
// await waitForButtonEnabled(keyConfirm);
|
||||
// await tapKey(keyConfirm, duration: 500);
|
||||
// await spawnBlock(duration: 2000);
|
||||
// await waitFor('validé !');
|
||||
// await tapKey(keyCloseTransactionScreen, duration: 0);
|
||||
// await sleep(5000);
|
||||
}, timeout: testTimeout());
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:gecko/models/widgets_keys.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import '../utility/general_actions.dart';
|
||||
import '../utility/tests_utility.dart';
|
||||
|
||||
void main() async {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
await dotenv.load();
|
||||
|
||||
testWidgets('Migrate Cesium identity and balance', (testerLoc) async {
|
||||
tester = testerLoc;
|
||||
// Connect local node and import test chest in background
|
||||
await bkFastStart();
|
||||
|
||||
// Open chest
|
||||
await firstOpenChest();
|
||||
|
||||
// Go to test1 options and check if balance growup with UDs creations
|
||||
await tapKey(keyAddDerivation);
|
||||
await waitFor('Portefeuille 6');
|
||||
|
||||
await scrollUntil(keyImportG1v1);
|
||||
await tapKey(keyImportG1v1);
|
||||
await enterText(keyCesiumId, 'test');
|
||||
await enterText(keyCesiumPassword, 'test');
|
||||
await waitFor(cesiumTest1.shortAddress());
|
||||
await waitFor('100.0');
|
||||
await waitFor('3', exactMatch: true);
|
||||
|
||||
isObscureText();
|
||||
await tapKey(keyCesiumIdVisible);
|
||||
await tester.pumpAndSettle();
|
||||
isObscureText(false);
|
||||
await tapKey(keyCesiumIdVisible);
|
||||
await tester.pumpAndSettle();
|
||||
isObscureText();
|
||||
|
||||
await tapKey(keySelectWallet);
|
||||
await tapKey(keySelectThisWallet(test6.address), selectLast: true);
|
||||
await waitForButtonEnabled(keyConfirm);
|
||||
await tapKey(keyConfirm);
|
||||
spawnBlock(duration: 2000);
|
||||
await waitFor('validé !');
|
||||
await tapKey(keyCloseTransactionScreen, duration: 0);
|
||||
|
||||
await tapKey(keyOpenWallet(test6.address), duration: 300);
|
||||
await waitFor('3', exactMatch: true);
|
||||
await waitFor('Membre validé !');
|
||||
|
||||
await waitFor('99.98', exactMatch: true);
|
||||
}, timeout: testTimeout());
|
||||
}
|
||||
|
||||
isObscureText([bool isObscure = true]) {
|
||||
final passwordTextFormField = find.descendant(
|
||||
of: find.byKey(keyCesiumId),
|
||||
matching: find.byType(EditableText),
|
||||
);
|
||||
final input = tester.widget<EditableText>(passwordTextFormField);
|
||||
expect(input.obscureText, isObscure ? isTrue : isFalse);
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import '../utility/general_actions.dart';
|
||||
import '../utility/tests_utility.dart';
|
||||
|
||||
void main() async {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
await dotenv.load();
|
||||
|
||||
testWidgets('Onboarding and multi chest', (testerLoc) async {
|
||||
tester = testerLoc;
|
||||
await bkFastStart(false);
|
||||
await onboardingNewChest();
|
||||
}, timeout: testTimeout());
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:gecko/models/widgets_keys.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import '../utility/general_actions.dart';
|
||||
import '../utility/tests_utility.dart';
|
||||
|
||||
void main() async {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
await dotenv.load();
|
||||
|
||||
testWidgets('UDs creation state', (testerLoc) async {
|
||||
tester = testerLoc;
|
||||
// Connect local node and import test chest in background
|
||||
await bkFastStart();
|
||||
|
||||
// Open chest
|
||||
await firstOpenChest();
|
||||
|
||||
// Go to test1 options and check if balance growup with UDs creations
|
||||
await tapKey(keyOpenWallet(test1.address));
|
||||
await waitFor('100.0', exactMatch: true);
|
||||
await spawnBlock(until: 10);
|
||||
await waitFor('200.0', exactMatch: true);
|
||||
await spawnBlock(until: 20);
|
||||
await waitFor('300.0', exactMatch: true);
|
||||
}, timeout: testTimeout());
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:gecko/globals.dart';
|
||||
import 'package:gecko/models/widgets_keys.dart';
|
||||
import 'package:gecko/providers/generate_wallets.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'tests_utility.dart';
|
||||
|
||||
// GENERAL ACTIONS
|
||||
|
||||
Future changeNode() async {
|
||||
final ipAddress = dotenv.env['ip_address'] ?? '127.0.0.1';
|
||||
log.d('ip address: $ipAddress');
|
||||
|
||||
await tapKey(keyDrawerMenu);
|
||||
await tapKey(keyParameters);
|
||||
await tapKey(keySelectDuniterNodeDropDown, duration: 5);
|
||||
await tapKey(keySelectDuniterNode('Personnalisé'), selectLast: true);
|
||||
await enterText(keyCustomDuniterEndpoint, 'ws://$ipAddress:9944');
|
||||
await tapKey(keyConnectToEndpoint);
|
||||
await isIconPresent(Icons.add_card_sharp,
|
||||
timeout: const Duration(seconds: 8));
|
||||
await goBack();
|
||||
}
|
||||
|
||||
Future deleteAllWallets() async {
|
||||
if (await isPresent('Rechercher')) {
|
||||
await tapKey(keyDrawerMenu);
|
||||
await tapKey(keyParameters);
|
||||
|
||||
// Check if ud unit checkbox is checked
|
||||
final isUdUnit = await isIconPresent(Icons.check_box);
|
||||
// If yes, tap on to use currency value
|
||||
if (isUdUnit) await tapKey(keyUdUnit, duration: 0);
|
||||
|
||||
await tapKey(keyDeleteAllWallets);
|
||||
await tapKey(keyConfirm);
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
}
|
||||
|
||||
Future restoreChest() async {
|
||||
// Copy test mnemonic in clipboard
|
||||
await clipCopy(testMnemonic);
|
||||
|
||||
// Open screen import chest
|
||||
await tapKey(keyRestoreChest, duration: 0);
|
||||
|
||||
// Tap on button to paste mnemonic
|
||||
await tapKey(keyPastMnemonic);
|
||||
|
||||
// Tap on next button 4 times to skip 3 screen
|
||||
await tapKey(keyGoNext);
|
||||
await tapKey(keyGoNext);
|
||||
await tapKey(keyGoNext);
|
||||
await tapKey(keyGoNext);
|
||||
|
||||
// Check if cached password checkbox is checked
|
||||
final isCached = await isIconPresent(Icons.check_box);
|
||||
|
||||
// If not, tap on to cache password
|
||||
if (!isCached) await tapKey(keyCachePassword, duration: 0);
|
||||
|
||||
// Enter password
|
||||
await enterText(keyPinForm, 'AAAAA', 0);
|
||||
|
||||
// Check if string "Accéder à mon coffre" is present in screen
|
||||
await waitFor('Accéder à mon coffre');
|
||||
|
||||
// Go to wallets home
|
||||
await tapKey(keyGoWalletsHome, duration: 0);
|
||||
|
||||
// Check if string "ĞD" is present in screen
|
||||
await waitFor('ĞD');
|
||||
|
||||
// Tap on add a new derivation button
|
||||
await addDerivation();
|
||||
|
||||
// Tap on Wallet 5
|
||||
await tapKey(keyOpenWallet(test5.address));
|
||||
|
||||
// Copy address of Wallet 5
|
||||
await tapKey(keyCopyAddress);
|
||||
|
||||
// Check if string "Cette adresse a été copié" is present in screen
|
||||
await waitFor('Cette adresse a été copié');
|
||||
|
||||
// Pop screen 2 time to go back home
|
||||
await goBack();
|
||||
await goBack();
|
||||
}
|
||||
|
||||
Future onboardingNewChest() async {
|
||||
final generateWalletProvider =
|
||||
Provider.of<GenerateWalletsProvider>(homeContext, listen: false);
|
||||
// Open screen create new wallet
|
||||
await tapKey(keyOnboardingNewChest);
|
||||
|
||||
// Tap on next button 4 times to skip 3 screen
|
||||
await tapKey(keyGoNext);
|
||||
await tapKey(keyGoNext);
|
||||
await tapKey(keyGoNext);
|
||||
await tapKey(keyGoNext);
|
||||
await waitFor('7', exactMatch: true);
|
||||
|
||||
final word41 = getWidgetText(keyMnemonicWord('4'));
|
||||
|
||||
// Change 2 times mnemonic
|
||||
await tapKey(keyGenerateMnemonic);
|
||||
await tester.pumpAndSettle();
|
||||
final word42 = getWidgetText(keyMnemonicWord('4'));
|
||||
expect(word41, isNot(word42));
|
||||
await tapKey(keyGenerateMnemonic, duration: 500);
|
||||
await tester.pumpAndSettle();
|
||||
final word43 = getWidgetText(keyMnemonicWord('4'));
|
||||
expect(word42, isNot(word43));
|
||||
|
||||
// Go next screen
|
||||
await tapKey(keyGoNext);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Enter asked word
|
||||
final askedWordNumber = int.parse(getWidgetText(keyAskedWord));
|
||||
List mnemonic = generateWalletProvider.generatedMnemonic!.split(' ');
|
||||
|
||||
final askedWord = mnemonic[askedWordNumber - 1];
|
||||
await enterText(keyInputWord, askedWord);
|
||||
await waitFor('Continuer', exactMatch: true);
|
||||
await tapKey(keyGoNext);
|
||||
await tapKey(keyGoNext);
|
||||
await tapKey(keyGoNext);
|
||||
await waitFor('AAAAA', exactMatch: true);
|
||||
await tapKey(keyGoNext);
|
||||
|
||||
// Check if cached password checkbox is checked
|
||||
final isCached = await isIconPresent(Icons.check_box);
|
||||
|
||||
// If not, tap on to cache password
|
||||
if (!isCached) await tapKey(keyCachePassword, duration: 0);
|
||||
|
||||
// Enter password
|
||||
await enterText(keyPinForm, 'AAAAA', 0);
|
||||
|
||||
// Check if string "Accéder à mon coffre" is present in screen
|
||||
await waitFor('Accéder à mon coffre');
|
||||
|
||||
// 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('0.0', exactMatch: true);
|
||||
// await waitFor('Scanner un');
|
||||
}
|
||||
|
||||
Future addDerivation() async {
|
||||
await tapKey(keyAddDerivation);
|
||||
await waitFor('Portefeuille 5');
|
||||
}
|
||||
|
||||
Future firstOpenChest() async {
|
||||
await tapKey(keyOpenWalletsHomme);
|
||||
sleep(300);
|
||||
final isCached = await isIconPresent(Icons.check_box);
|
||||
if (!isCached) await tapKey(keyCachePassword, duration: 0);
|
||||
await enterText(keyPinForm, 'AAAAA', 0);
|
||||
await waitFor('100.0', exactMatch: true);
|
||||
}
|
|
@ -0,0 +1,328 @@
|
|||
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';
|
||||
import 'package:gecko/models/wallet_data.dart';
|
||||
import 'package:gecko/providers/generate_wallets.dart';
|
||||
import 'package:gecko/providers/my_wallets.dart';
|
||||
import 'package:gecko/providers/substrate_sdk.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'dart:io' as io;
|
||||
import 'package:gecko/main.dart' as app;
|
||||
|
||||
final bool isHumanReading =
|
||||
dotenv.env['isHumanReading'] == 'true' ? true : false;
|
||||
Timeout testTimeout([int seconds = 120]) =>
|
||||
Timeout(Duration(seconds: isHumanReading ? 600 : seconds));
|
||||
final sub = Provider.of<SubstrateSdk>(homeContext, listen: false);
|
||||
late WidgetTester tester;
|
||||
|
||||
// TEST WALLETS CONSTS
|
||||
const testMnemonic =
|
||||
'pipe paddle ketchup filter life ice feel embody glide quantum ride usage';
|
||||
final test1 =
|
||||
TestWallet('5FeggKqw2AbnGZF9Y9WPM2QTgzENS3Hit94Ewgmzdg5a3LNa', 'test1');
|
||||
final test2 =
|
||||
TestWallet('5E4i8vcNjnrDp21Sbnp32WHm2gz8YP3GGFwmdpfg5bHd8Whb', 'test2');
|
||||
final test3 =
|
||||
TestWallet('5FhTLzXLNBPmtXtDBFECmD7fvKmTtTQDtvBTfVr97tachA1p', 'test3');
|
||||
final test4 =
|
||||
TestWallet('5DXJ4CusmCg8S1yF6JGVn4fxgk5oFx42WctXqHZ17mykgje5', 'test4');
|
||||
final test5 =
|
||||
TestWallet('5Dq3giahrBfykJogPetZJ2jjSmhw49Fa7i6qKkseUvRJ2T3R', 'test5');
|
||||
final test6 =
|
||||
TestWallet('5GxEp3do81j97kNaH4JyZgDXuPoKWoTuxXXWGyyNXeKeVLHb', 'test6');
|
||||
final test7 =
|
||||
TestWallet('5FZ1sSvREbQLCtSSCvMUx7KCAnpJkB7q5mfz2oixiZq2ChET', 'test7');
|
||||
final test8 =
|
||||
TestWallet('5CoKV9EEgwb2NmWamTXUAa6ycfNb2k1iNfVGvJAkg7dLq9RH', 'test8');
|
||||
final cesiumTest1 = TestWallet(
|
||||
'5GAT6CJW8yVKwUuQc7sM5Kk9GZVTpbZYk9PfjNXtvnNgAJZ1', 'cesiumTest1');
|
||||
final cesiumTest2 = TestWallet(
|
||||
'5DTnny1tTkUs1SXHZTx98RUAj76Z88FfFhsQjd48dXnk8gHR', 'cesiumTest2');
|
||||
final cesiumTest3 = TestWallet(
|
||||
'5EJct9jTDNKco4YiYfETAseq1gaduBtsJUcNnFicfvh3bTV6', 'cesiumTest3');
|
||||
final cesiumTest4 = TestWallet(
|
||||
'5HD1oSv6A7VNxPYos6F86JFZ3bhz5LnEaWC4hkwLMj84v4ww', 'cesiumTest4');
|
||||
|
||||
// CUSTOM FUNCTIONS
|
||||
|
||||
Future sleep([int time = 1000]) async {
|
||||
await Future.delayed(Duration(milliseconds: time));
|
||||
}
|
||||
|
||||
Future<String> clipPaste() async =>
|
||||
(await Clipboard.getData('text/plain'))?.text ?? '';
|
||||
|
||||
clipCopy(String text) async =>
|
||||
await Clipboard.setData(ClipboardData(text: text));
|
||||
|
||||
Future humanRead([int time = 1, bool force = false]) async {
|
||||
if (isHumanReading || force) io.sleep(Duration(seconds: time));
|
||||
}
|
||||
|
||||
Future tapKey(Key buttonKey,
|
||||
{Finder? customFinder, int duration = 100, bool selectLast = false}) async {
|
||||
if (duration != 0) {
|
||||
await tester.pumpAndSettle(Duration(milliseconds: duration));
|
||||
}
|
||||
final Finder finder = customFinder ?? find.byKey(buttonKey);
|
||||
log.d('INTEGRATION TEST: Tap on ${finder.description}}');
|
||||
await tester.tap(selectLast ? finder.last : finder);
|
||||
humanRead();
|
||||
}
|
||||
|
||||
Finder findByKey(Key key) {
|
||||
return find.byKey(key);
|
||||
}
|
||||
|
||||
bool isButtonEnabled(Key key) {
|
||||
return tester.widget<ElevatedButton>(findByKey(key)).enabled;
|
||||
}
|
||||
|
||||
Future scrollUntil(Key element) async {
|
||||
final findList = find.byType(Scrollable);
|
||||
final findElement = findByKey(element);
|
||||
await tester.scrollUntilVisible(
|
||||
findElement,
|
||||
500.0,
|
||||
scrollable: findList,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> waitForButtonEnabled(Key key,
|
||||
{Duration timeout = const Duration(seconds: 5),
|
||||
bool reverse = false}) async {
|
||||
final end = DateTime.now().add(timeout);
|
||||
|
||||
log.d('INTEGRATION TEST: Wait for $key to be enabled');
|
||||
|
||||
do {
|
||||
if (DateTime.now().isAfter(end)) {
|
||||
throw Exception('Timed out waiting for button enabled: $key');
|
||||
}
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
} while (reverse ? isButtonEnabled(key) : !isButtonEnabled(key));
|
||||
humanRead();
|
||||
}
|
||||
|
||||
Future goBack() async {
|
||||
final NavigatorState navigator = tester.state(find.byType(Navigator));
|
||||
log.d('INTEGRATION TEST: Go back');
|
||||
navigator.pop();
|
||||
await tester.pump();
|
||||
humanRead();
|
||||
}
|
||||
|
||||
Future enterText(Key fieldKey, String textIn, [int duration = 200]) async {
|
||||
if (duration != 0) {
|
||||
await tester.pumpAndSettle(Duration(milliseconds: duration));
|
||||
}
|
||||
log.d('INTEGRATION TEST: Enter text: $textIn');
|
||||
await tester.enterText(find.byKey(fieldKey), textIn);
|
||||
humanRead();
|
||||
}
|
||||
|
||||
Future<void> waitFor(String text,
|
||||
{Duration timeout = const Duration(seconds: 5),
|
||||
bool reverse = false,
|
||||
bool exactMatch = false}) async {
|
||||
final end = DateTime.now().add(timeout);
|
||||
|
||||
Finder finder = exactMatch ? find.text(text) : find.textContaining(text);
|
||||
log.d('INTEGRATION TEST: Wait for: $text');
|
||||
|
||||
final String searchType = reverse ? 'reversed text' : 'text';
|
||||
|
||||
do {
|
||||
if (DateTime.now().isAfter(end)) {
|
||||
throw Exception('Timed out waiting for $searchType : "$text"');
|
||||
}
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
} while (reverse ? finder.evaluate().isNotEmpty : finder.evaluate().isEmpty);
|
||||
humanRead();
|
||||
}
|
||||
|
||||
// Test if text is visible on screen, return a boolean
|
||||
Future<bool> isPresent(String text,
|
||||
{Duration timeout = const Duration(seconds: 1)}) async {
|
||||
try {
|
||||
await waitFor(text, timeout: timeout);
|
||||
humanRead();
|
||||
return true;
|
||||
} catch (exception) {
|
||||
humanRead();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test if widget exist on screen, return a boolean
|
||||
Future<bool> isIconPresent(IconData icon,
|
||||
{Duration timeout = const Duration(seconds: 1)}) async {
|
||||
await tester.pumpAndSettle();
|
||||
final finder = find.byIcon(icon);
|
||||
log.d('tatatatatatata: ${finder.evaluate()}');
|
||||
humanRead();
|
||||
return finder.evaluate().isEmpty ? false : true;
|
||||
}
|
||||
|
||||
Future spawnBlock({int number = 1, int duration = 200, int? until}) async {
|
||||
if (duration != 0) {
|
||||
await sleep(duration);
|
||||
}
|
||||
if (until != null) {
|
||||
number = until - sub.blocNumber;
|
||||
}
|
||||
await sub.spawnBlock(number);
|
||||
await sleep(200);
|
||||
}
|
||||
|
||||
// Pay in background
|
||||
Future bkPay(
|
||||
{required String fromAddress,
|
||||
required String destAddress,
|
||||
required double amount}) async {
|
||||
sub.pay(
|
||||
fromAddress: fromAddress,
|
||||
destAddress: destAddress,
|
||||
amount: amount,
|
||||
password: 'AAAAA');
|
||||
await sleep(500);
|
||||
await spawnBlock();
|
||||
await sleep(500);
|
||||
}
|
||||
|
||||
// Certify in background
|
||||
Future bkCertify(
|
||||
{required String fromAddress,
|
||||
required String destAddress,
|
||||
bool spawnBloc = true}) async {
|
||||
sub.certify(fromAddress, destAddress, 'AAAAA');
|
||||
if (spawnBloc) {
|
||||
await sleep(500);
|
||||
await spawnBlock();
|
||||
}
|
||||
await sleep(500);
|
||||
}
|
||||
|
||||
// Confirm my identity in background
|
||||
Future bkConfirmIdentity(
|
||||
{required String fromAddress, required String name}) async {
|
||||
sub.confirmIdentity(fromAddress, name, 'AAAAA');
|
||||
await sleep(500);
|
||||
await spawnBlock();
|
||||
await sleep(500);
|
||||
}
|
||||
|
||||
// Change node in background
|
||||
Future bkSetNode([String? endpoint]) async {
|
||||
if (endpoint == null) {
|
||||
final ipAddress = dotenv.env['ip_address'] ?? '127.0.0.1';
|
||||
endpoint = 'ws://$ipAddress:9944';
|
||||
}
|
||||
configBox.put('customEndpoint', endpoint);
|
||||
sub.connectNode(homeContext);
|
||||
}
|
||||
|
||||
// Restore chest in background
|
||||
Future bkRestoreChest([String mnemonic = testMnemonic]) async {
|
||||
final myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(homeContext, listen: false);
|
||||
final generateWalletProvider =
|
||||
Provider.of<GenerateWalletsProvider>(homeContext, listen: false);
|
||||
|
||||
await generateWalletProvider.storeHDWChest(homeContext);
|
||||
|
||||
for (int number = 0; number <= 4; number++) {
|
||||
await _addImportAccount(
|
||||
mnemonic: mnemonic,
|
||||
chest: 0,
|
||||
number: number,
|
||||
name: 'test${number + 1}',
|
||||
derivation: (number + 1) * 2);
|
||||
}
|
||||
myWalletProvider.reload();
|
||||
}
|
||||
|
||||
Future<WalletData> _addImportAccount(
|
||||
{required String mnemonic,
|
||||
required int chest,
|
||||
required int number,
|
||||
required String name,
|
||||
required int derivation}) async {
|
||||
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);
|
||||
|
||||
return myWallet;
|
||||
}
|
||||
|
||||
// Delete all wallets in background
|
||||
Future bkDeleteAllWallets() async {
|
||||
final myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(homeContext, listen: false);
|
||||
final isWalletsPresents =
|
||||
await isPresent('Scanner un', timeout: const Duration(milliseconds: 300));
|
||||
if (isWalletsPresents) {
|
||||
await walletBox.clear();
|
||||
await chestBox.clear();
|
||||
await configBox.delete('defaultWallet');
|
||||
await configBox.delete('isUdUnit');
|
||||
await sub.deleteAllAccounts();
|
||||
myWalletProvider.pinCode = '';
|
||||
myWalletProvider.reload();
|
||||
}
|
||||
}
|
||||
|
||||
Future bkFastStart([bool restoreChest = true]) async {
|
||||
// Start app and wait finish starting
|
||||
await startWait();
|
||||
|
||||
// Connect to local endpoint
|
||||
await bkSetNode();
|
||||
await sleep();
|
||||
|
||||
// Delete all existing chests is exists
|
||||
await bkDeleteAllWallets();
|
||||
|
||||
if (restoreChest) {
|
||||
// Restore the test chest
|
||||
await bkRestoreChest();
|
||||
await waitFor("y'a pas de lézard");
|
||||
}
|
||||
}
|
||||
|
||||
Future startWait() async {
|
||||
app.main();
|
||||
await waitFor('Test starting...', reverse: true);
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 300));
|
||||
await sleep(3000);
|
||||
}
|
||||
|
||||
String getWidgetText(Key key) {
|
||||
final word4Finder = find.byKey(key);
|
||||
return (word4Finder.evaluate().single.widget as Text).data!;
|
||||
}
|
||||
|
||||
class TestWallet {
|
||||
String address;
|
||||
String name;
|
||||
|
||||
TestWallet(this.address, this.name);
|
||||
|
||||
endAddress() => address.substring(address.length - 6);
|
||||
shortAddress() => getShortPubkey(address);
|
||||
}
|
|
@ -1 +1,2 @@
|
|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
# Uncomment this line to define a global platform for your project
|
||||
# platform :ios, '11.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
project 'Runner', {
|
||||
'Debug' => :debug,
|
||||
'Profile' => :release,
|
||||
'Release' => :release,
|
||||
}
|
||||
|
||||
def flutter_root
|
||||
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
|
||||
unless File.exist?(generated_xcode_build_settings_path)
|
||||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
|
||||
end
|
||||
|
||||
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||
return matches[1].strip if matches
|
||||
end
|
||||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
|
||||
end
|
||||
|
||||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||
|
||||
flutter_ios_podfile_setup
|
||||
|
||||
target 'Runner' do
|
||||
use_frameworks!
|
||||
use_modular_headers!
|
||||
|
||||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
flutter_additional_ios_build_settings(target)
|
||||
end
|
||||
end
|
|
@ -3,7 +3,7 @@
|
|||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objectVersion = 51;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
|
@ -288,6 +288,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 72JY5XXU29;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -420,6 +421,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 72JY5XXU29;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -447,6 +449,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 72JY5XXU29;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Camera permission is required for barcode scanning.</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Camera permission is required for barcode scanning.</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Access to user's is required for profile image upload in wallet management</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
|
@ -14,6 +16,8 @@
|
|||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>gecko</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<string>NO</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
|
|
|
@ -3,18 +3,13 @@ import 'package:flutter/material.dart';
|
|||
import 'package:gecko/models/chest_data.dart';
|
||||
import 'package:gecko/models/g1_wallets_list.dart';
|
||||
import 'package:gecko/models/wallet_data.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:logger/logger.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
// Version of box data
|
||||
const int dataVersion = 4;
|
||||
|
||||
// Files paths
|
||||
Directory? appPath;
|
||||
|
||||
late String appVersion;
|
||||
late SharedPreferences prefs;
|
||||
const int pinLength = 5;
|
||||
const String appLang = 'english';
|
||||
|
||||
|
@ -22,6 +17,7 @@ late Box<WalletData> walletBox;
|
|||
late Box<ChestData> chestBox;
|
||||
late Box configBox;
|
||||
late Box<G1WalletsList> g1WalletsBox;
|
||||
late Box<G1WalletsList> contactsBox;
|
||||
// late Box keystoreBox;
|
||||
late Directory imageDirectory;
|
||||
|
||||
|
@ -37,17 +33,20 @@ late double ratio;
|
|||
late BuildContext homeContext;
|
||||
|
||||
// Logger
|
||||
var log = Logger();
|
||||
final log = Logger();
|
||||
|
||||
// Colors
|
||||
Color orangeC = const Color(0xffd07316);
|
||||
Color yellowC = const Color(0xffFFD68E);
|
||||
Color floattingYellow = const Color(0xffEFEFBF);
|
||||
Color backgroundColor = const Color(0xFFF5F5F5);
|
||||
const Color orangeC = Color(0xffd07316);
|
||||
const Color yellowC = Color(0xffFFD68E);
|
||||
const Color floattingYellow = Color(0xffEFEFBF);
|
||||
const Color backgroundColor = Color(0xFFF5F5F5);
|
||||
|
||||
// Substrate settings
|
||||
const int ss58 = 42;
|
||||
String currencyName = 'ĞD';
|
||||
const String currencyName = 'ĞD';
|
||||
|
||||
// Debug
|
||||
const debugPin = true;
|
||||
|
||||
String indexerEndpoint = '';
|
||||
late double balanceRatio;
|
||||
late int udValue;
|
||||
|
|
|
@ -13,17 +13,18 @@
|
|||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
// ignore_for_file: avoid_print
|
||||
|
||||
import 'dart:async';
|
||||
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/providers/duniter_indexer.dart';
|
||||
import 'package:gecko/providers/generate_wallets.dart';
|
||||
import 'package:gecko/providers/settings_provider.dart';
|
||||
import 'package:gecko/providers/substrate_sdk.dart';
|
||||
import 'package:gecko/providers/wallets_profiles.dart';
|
||||
import 'package:gecko/providers/home.dart';
|
||||
|
@ -40,39 +41,44 @@ import 'package:hive_flutter/hive_flutter.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:responsive_framework/responsive_framework.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
import 'package:window_size/window_size.dart';
|
||||
import 'package:graphql_flutter/graphql_flutter.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
|
||||
const bool enableSentry = true;
|
||||
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
if (!kIsWeb && (Platform.isWindows || Platform.isLinux || Platform.isMacOS)) {
|
||||
setWindowTitle('Ğecko');
|
||||
setWindowMinSize(const Size(400, 700));
|
||||
setWindowMaxSize(const Size(800, 1000));
|
||||
await EasyLocalization.ensureInitialized();
|
||||
|
||||
if (kDebugMode) {
|
||||
await dotenv.load();
|
||||
}
|
||||
|
||||
HomeProvider _homeProvider = HomeProvider();
|
||||
await _homeProvider.initHive();
|
||||
appVersion = await _homeProvider.getAppVersion();
|
||||
prefs = await SharedPreferences.getInstance();
|
||||
HomeProvider homeProvider = HomeProvider();
|
||||
// DuniterIndexer _duniterIndexer = DuniterIndexer();
|
||||
await initHiveForFlutter();
|
||||
await homeProvider.initHive();
|
||||
appVersion = await homeProvider.getAppVersion();
|
||||
|
||||
// Reset GraphQL cache
|
||||
// final cache = HiveStore();
|
||||
// cache.reset();
|
||||
|
||||
// Configure Hive and open boxes
|
||||
Hive.registerAdapter(WalletDataAdapter());
|
||||
Hive.registerAdapter(ChestDataAdapter());
|
||||
Hive.registerAdapter(G1WalletsListAdapter());
|
||||
Hive.registerAdapter(IdAdapter());
|
||||
// Hive.registerAdapter(KeyStoreDataAdapter());
|
||||
|
||||
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 homeProvider.getValidEndpoints();
|
||||
// await configBox.delete('isCacheChecked');
|
||||
if (configBox.get('isCacheChecked') == null) {
|
||||
configBox.put('isCacheChecked', false);
|
||||
|
@ -92,27 +98,31 @@ 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(const Gecko()));
|
||||
|
||||
// runZoned<Future<void>>(
|
||||
// () async {
|
||||
// runApp(Gecko(endPointGVA, _store));
|
||||
// },
|
||||
// onError: (dynamic error, StackTrace stackTrace) {
|
||||
// print("=================== CAUGHT DART ERROR");
|
||||
// // Sentry.captureException(
|
||||
// // error,
|
||||
// // stackTrace: stackTrace,
|
||||
// // );
|
||||
// },
|
||||
// ));
|
||||
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(),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
print('Debug mode enabled: No sentry alerte');
|
||||
log.i('Debug mode enabled: No sentry alerte');
|
||||
|
||||
runApp(const Gecko());
|
||||
runApp(
|
||||
EasyLocalization(
|
||||
supportedLocales: const [Locale('en'), Locale('fr'), Locale('es')],
|
||||
path: 'assets/translations',
|
||||
fallbackLocale: const Locale('en'),
|
||||
child: const Gecko(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,9 +133,10 @@ class Gecko extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
|
||||
// To configure multi_endpoints GraphQLProvider: https://stackoverflow.com/q/70656513/8301867
|
||||
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
// Provider(create: (context) => HistoryProvider()),
|
||||
ChangeNotifierProvider(create: (_) => HomeProvider()),
|
||||
ChangeNotifierProvider(create: (_) => WalletsProfilesProvider('')),
|
||||
ChangeNotifierProvider(create: (_) => MyWalletsProvider()),
|
||||
|
@ -134,9 +145,14 @@ class Gecko extends StatelessWidget {
|
|||
ChangeNotifierProvider(create: (_) => WalletOptionsProvider()),
|
||||
ChangeNotifierProvider(create: (_) => SearchProvider()),
|
||||
ChangeNotifierProvider(create: (_) => CesiumPlusProvider()),
|
||||
ChangeNotifierProvider(create: (_) => SubstrateSdk())
|
||||
ChangeNotifierProvider(create: (_) => SubstrateSdk()),
|
||||
ChangeNotifierProvider(create: (_) => DuniterIndexer()),
|
||||
ChangeNotifierProvider(create: (_) => SettingsProvider())
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: context.localizationDelegates,
|
||||
supportedLocales: context.supportedLocales,
|
||||
locale: context.locale,
|
||||
builder: (context, widget) => ResponsiveWrapper.builder(
|
||||
BouncingScrollWrapper.builder(context, widget!),
|
||||
maxWidth: 1200,
|
||||
|
|
|
@ -6,7 +6,7 @@ part 'g1_wallets_list.g.dart';
|
|||
@HiveType(typeId: 2)
|
||||
class G1WalletsList {
|
||||
@HiveField(0)
|
||||
String? pubkey;
|
||||
late String address;
|
||||
|
||||
@HiveField(1)
|
||||
double? balance;
|
||||
|
@ -27,7 +27,7 @@ class G1WalletsList {
|
|||
bool? isMembre;
|
||||
|
||||
G1WalletsList({
|
||||
this.pubkey,
|
||||
required this.address,
|
||||
this.balance,
|
||||
this.id,
|
||||
this.avatar,
|
||||
|
@ -37,14 +37,14 @@ class G1WalletsList {
|
|||
});
|
||||
|
||||
G1WalletsList.fromJson(Map<String, dynamic> json) {
|
||||
pubkey = json['pubkey'];
|
||||
address = json['pubkey'];
|
||||
balance = json['balance'];
|
||||
id = json['id'] != null ? Id.fromJson(json['id']) : null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['pubkey'] = pubkey;
|
||||
data['pubkey'] = address;
|
||||
data['balance'] = balance;
|
||||
if (id != null) {
|
||||
data['id'] = id!.toJson();
|
||||
|
|
|
@ -17,7 +17,7 @@ class G1WalletsListAdapter extends TypeAdapter<G1WalletsList> {
|
|||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return G1WalletsList(
|
||||
pubkey: fields[0] as String?,
|
||||
address: fields[0] as String,
|
||||
balance: fields[1] as double?,
|
||||
id: fields[2] as Id?,
|
||||
avatar: fields[3] as Image?,
|
||||
|
@ -32,7 +32,7 @@ class G1WalletsListAdapter extends TypeAdapter<G1WalletsList> {
|
|||
writer
|
||||
..writeByte(7)
|
||||
..writeByte(0)
|
||||
..write(obj.pubkey)
|
||||
..write(obj.address)
|
||||
..writeByte(1)
|
||||
..write(obj.balance)
|
||||
..writeByte(2)
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
const String getNameByAddressQ = r'''
|
||||
query ($address: String!) {
|
||||
account_by_pk(pubkey: $address) {
|
||||
identity {
|
||||
name
|
||||
}
|
||||
pubkey
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
||||
const String searchAddressByNameQ = r'''
|
||||
query ($name: String!) {
|
||||
search_identity(args: {name: $name}) {
|
||||
pubkey
|
||||
name
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
||||
const String getHistoryByAddressQ = r'''
|
||||
query ($address: String!, $number: Int!, $cursor: String) {
|
||||
transaction_connection(where:
|
||||
{_or: [
|
||||
{issuer_pubkey: {_eq: $address}},
|
||||
{receiver_pubkey: {_eq: $address}}
|
||||
]},
|
||||
order_by: {created_at: desc},
|
||||
first: $number,
|
||||
after: $cursor) {
|
||||
edges {
|
||||
node {
|
||||
amount
|
||||
created_at
|
||||
issuer_pubkey
|
||||
receiver_pubkey
|
||||
issuer {
|
||||
identity {
|
||||
name
|
||||
}
|
||||
}
|
||||
receiver {
|
||||
identity {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
endCursor
|
||||
hasNextPage
|
||||
hasPreviousPage
|
||||
startCursor
|
||||
}
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
||||
// To parse indexer date format
|
||||
// log.d(DateTime.parse("2022-06-13T16:51:24.001+00:00").toString());
|
|
@ -6,10 +6,10 @@ class StatefulWrapper extends StatefulWidget {
|
|||
const StatefulWrapper({Key? key, required this.onInit, required this.child})
|
||||
: super(key: key);
|
||||
@override
|
||||
_StatefulWrapperState createState() => _StatefulWrapperState();
|
||||
StatefulWrapperState createState() => StatefulWrapperState();
|
||||
}
|
||||
|
||||
class _StatefulWrapperState extends State<StatefulWrapper> {
|
||||
class StatefulWrapperState extends State<StatefulWrapper> {
|
||||
@override
|
||||
void initState() {
|
||||
widget.onInit();
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
// General
|
||||
const keyInfoPopup = Key('keyInfoPopup');
|
||||
const keyGoNext = Key('keyGoNext');
|
||||
const keyCancel = Key('keyCancel');
|
||||
const keyConfirm = Key('keyConfirm');
|
||||
const keyAppBarSearch = Key('keyAppBarSearch');
|
||||
const keyAppBarQrcode = Key('keyAppBarQrcode');
|
||||
const keyAppBarChest = Key('keyAppBarChest');
|
||||
|
||||
// Home
|
||||
const keyParameters = Key('keyParameters');
|
||||
const keyContacts = Key('keyContacts');
|
||||
const keyDrawerMenu = Key('keyDrawerMenu');
|
||||
const keyOpenWalletsHomme = Key('keyOpenWalletsHomme');
|
||||
const keyOpenSearch = Key('keyOpenSearch');
|
||||
const keyRestoreChest = Key('keyRestoreChest');
|
||||
const keyOnboardingNewChest = Key('keyOnboardingNewChest');
|
||||
|
||||
// Wallets home
|
||||
const keyImportG1v1 = Key('keyImportG1v1');
|
||||
const keyChangeChest = Key('keyChangeChest');
|
||||
const keyListWallets = Key('keyListWallets');
|
||||
const keyAddDerivation = Key('keyAddDerivation');
|
||||
|
||||
// Wallet options
|
||||
const keyCopyAddress = Key('keyCopyAddress');
|
||||
const keyOpenActivity = Key('keyOpenActivity');
|
||||
const keyManageMembership = Key('keyManageMembership');
|
||||
const keySetDefaultWallet = Key('keySetDefaultWallet');
|
||||
const keyDeleteWallet = Key('keyDeleteWallet');
|
||||
const keyWalletName = Key('keyWalletName');
|
||||
const keyRenameWallet = Key('keyRenameWallet');
|
||||
const keyConfirmIdentity = Key('keyConfirmIdentity');
|
||||
const keyEnterIdentityUsername = Key('keyEnterIdentityUsername');
|
||||
|
||||
// Chest options
|
||||
const keyShowSeed = Key('keyShowSeed');
|
||||
const keyChangePin = Key('keyChangePin');
|
||||
const keycreateRootDerivation = Key('keycreateRootDerivation');
|
||||
const keyDeleteChest = Key('keyDeleteChest');
|
||||
|
||||
// Manage membership
|
||||
const keyMigrateIdentity = Key('keyMigrateIdentity');
|
||||
const keyRevokeIdty = Key('keyRevokeIdty');
|
||||
|
||||
// Choose chest
|
||||
const keyCreateNewChest = Key('keyCreateNewChest');
|
||||
const keyImportChest = Key('keyImportChest');
|
||||
|
||||
// Profile view
|
||||
const keyViewActivity = Key('keyViewActivity');
|
||||
const keyCertify = Key('keyCertify');
|
||||
const keyPay = Key('keyPay');
|
||||
const keyAmountField = Key('keyAmountField');
|
||||
const keyConfirmPayment = Key('keyConfirmPayment');
|
||||
const keyCloseTransactionScreen = Key('keyCloseTransactionScreen');
|
||||
|
||||
// Activity view
|
||||
const keyListTransactions = Key('keyListTransactions');
|
||||
const keyActivityScreen = Key('keyActivityScreen');
|
||||
|
||||
// Unlock wallet
|
||||
const keyUnlockWallet = Key('keyUnlockWallet');
|
||||
const keyPinForm = Key('keyPinForm');
|
||||
const keyPopButton = Key('keyPopButton');
|
||||
const keyCachePassword = Key('keyCachePassword');
|
||||
|
||||
// Settings
|
||||
const keyDeleteAllWallets = Key('keyDeleteAllWallets');
|
||||
const keySelectDuniterNodeDropDown = Key('keySelectDuniterNodeDropDown');
|
||||
const keyCustomDuniterEndpoint = Key('keyCustomDuniterEndpoint');
|
||||
const keyConnectToEndpoint = Key('keyConnectToEndpoint');
|
||||
const keyUdUnit = Key('keyUdUnit');
|
||||
|
||||
// Onboarding
|
||||
const keyPastMnemonic = Key('keyPastMnemonic');
|
||||
const keyBubbleSpeak = Key('keyBubbleSpeak');
|
||||
const keyGenerateMnemonic = Key('keyGenerateMnemonic');
|
||||
const keyAskedWord = Key('keyAskedWord');
|
||||
const keyInputWord = Key('keyInputWord');
|
||||
const keyGeneratedPin = Key('keyGeneratedPin');
|
||||
const keyGoWalletsHome = Key('keyGoWalletsHome');
|
||||
|
||||
// Search
|
||||
const keySearchField = Key('keySearchField');
|
||||
const keyConfirmSearch = Key('keyConfirmSearch');
|
||||
|
||||
// Import Cesium wallet
|
||||
const keyCesiumId = Key('keyCesiumId');
|
||||
const keyCesiumPassword = Key('keyCesiumPassword');
|
||||
const keySelectWallet = Key('keySelectWallet');
|
||||
const keyCesiumIdVisible = Key('keyCesiumIdVisible');
|
||||
|
||||
// Items keys
|
||||
Key keyTransaction(int keyId) => Key('keyTransaction$keyId');
|
||||
Key keyMnemonicWord(String word) => Key('keyMnemonicWord$word');
|
||||
Key keySearchResult(String address) => Key('keySearchResult$address');
|
||||
Key keySelectDuniterNode(String endpoint) =>
|
||||
Key('keySelectDuniterNode$endpoint');
|
||||
Key keyOpenWallet(String address) => Key('keyOpenWallet$address');
|
||||
Key keySelectThisWallet(String address) => Key('keySelectThisWallet$address');
|
|
@ -8,23 +8,23 @@ import 'package:path_provider/path_provider.dart';
|
|||
|
||||
class CesiumPlusProvider with ChangeNotifier {
|
||||
TextEditingController cesiumName = TextEditingController();
|
||||
Image defaultAvatar(double? size) =>
|
||||
Image defaultAvatar(double size) =>
|
||||
Image.asset(('assets/icon_user.png'), height: size);
|
||||
|
||||
CancelToken avatarCancelToken = CancelToken();
|
||||
|
||||
Future<List> _buildQuery(_pubkey) async {
|
||||
Future<List> _buildQuery(pubkey) async {
|
||||
var queryGetAvatar = json.encode({
|
||||
"query": {
|
||||
"bool": {
|
||||
"should": [
|
||||
{
|
||||
"match": {
|
||||
'_id': {"query": _pubkey, "boost": 2}
|
||||
'_id': {"query": pubkey, "boost": 2}
|
||||
}
|
||||
},
|
||||
{
|
||||
"prefix": {'_id': _pubkey}
|
||||
"prefix": {'_id': pubkey}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -60,14 +60,14 @@ class CesiumPlusProvider with ChangeNotifier {
|
|||
return [podRequest, queryGetAvatar, headers];
|
||||
}
|
||||
|
||||
Future<String> getName(String? _pubkey) async {
|
||||
String? _name;
|
||||
Future<String> getName(String? pubkey) async {
|
||||
String? name;
|
||||
|
||||
if (g1WalletsBox.get(_pubkey)?.csName != null) {
|
||||
return g1WalletsBox.get(_pubkey)!.csName!;
|
||||
if (g1WalletsBox.get(pubkey)?.csName != null) {
|
||||
return g1WalletsBox.get(pubkey)!.csName!;
|
||||
}
|
||||
|
||||
List queryOptions = await _buildQuery(_pubkey);
|
||||
List queryOptions = await _buildQuery(pubkey);
|
||||
|
||||
var dio = Dio();
|
||||
late Response response;
|
||||
|
@ -90,28 +90,28 @@ class CesiumPlusProvider with ChangeNotifier {
|
|||
if (response.data['hits']['hits'].toString() == '[]') {
|
||||
return '';
|
||||
}
|
||||
final bool _nameExist =
|
||||
final bool nameExist =
|
||||
response.data['hits']['hits'][0]['_source'].containsKey("title");
|
||||
if (!_nameExist) {
|
||||
if (!nameExist) {
|
||||
return '';
|
||||
}
|
||||
_name = response.data['hits']['hits'][0]['_source']['title'];
|
||||
name = response.data['hits']['hits'][0]['_source']['title'];
|
||||
|
||||
_name ??= '';
|
||||
g1WalletsBox.get(_pubkey)!.csName = _name;
|
||||
name ??= '';
|
||||
g1WalletsBox.get(pubkey)!.csName = name;
|
||||
|
||||
return _name;
|
||||
return name;
|
||||
}
|
||||
|
||||
Future<Image?> getAvatar(String? _pubkey, double size) async {
|
||||
if (g1WalletsBox.get(_pubkey)?.avatar != null) {
|
||||
return g1WalletsBox.get(_pubkey)!.avatar;
|
||||
Future<Image?> getAvatar(String? pubkey, double size) async {
|
||||
if (g1WalletsBox.get(pubkey)?.avatar != null) {
|
||||
return g1WalletsBox.get(pubkey)!.avatar;
|
||||
}
|
||||
var dio = Dio();
|
||||
|
||||
// log.d(_pubkey);
|
||||
|
||||
List queryOptions = await _buildQuery(_pubkey);
|
||||
List queryOptions = await _buildQuery(pubkey);
|
||||
|
||||
late Response response;
|
||||
try {
|
||||
|
@ -138,12 +138,12 @@ class CesiumPlusProvider with ChangeNotifier {
|
|||
return defaultAvatar(size);
|
||||
}
|
||||
|
||||
final _avatar =
|
||||
final avatar =
|
||||
response.data['hits']['hits'][0]['_source']['avatar']['_content'];
|
||||
|
||||
var avatarFile =
|
||||
File('${(await getTemporaryDirectory()).path}/avatar_$_pubkey.png');
|
||||
await avatarFile.writeAsBytes(base64.decode(_avatar));
|
||||
File('${(await getTemporaryDirectory()).path}/avatar_$pubkey.png');
|
||||
await avatarFile.writeAsBytes(base64.decode(avatar));
|
||||
|
||||
final finalAvatar = Image.file(
|
||||
avatarFile,
|
||||
|
@ -151,7 +151,7 @@ class CesiumPlusProvider with ChangeNotifier {
|
|||
fit: BoxFit.fitWidth,
|
||||
);
|
||||
|
||||
g1WalletsBox.get(_pubkey)!.avatar = finalAvatar;
|
||||
g1WalletsBox.get(pubkey)!.avatar = finalAvatar;
|
||||
|
||||
return finalAvatar;
|
||||
}
|
||||
|
|
|
@ -1,27 +1,29 @@
|
|||
import 'dart:async';
|
||||
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: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:provider/provider.dart';
|
||||
|
||||
class ChestProvider with ChangeNotifier {
|
||||
void rebuildWidget() {
|
||||
void reload() {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future deleteChest(context, ChestData _chest) async {
|
||||
final bool? _answer = await (_confirmDeletingChest(context, _chest.name));
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
if (_answer ?? false) {
|
||||
await _sub.deleteAccounts(getChestWallets(_chest));
|
||||
await chestBox.delete(_chest.key);
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
Future deleteChest(context, ChestData chest) async {
|
||||
final bool? answer = await (_confirmDeletingChest(context, chest.name));
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
if (answer ?? false) {
|
||||
await sub.deleteAccounts(getChestWallets(chest));
|
||||
await chestBox.delete(chest.key);
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
|
||||
_myWalletProvider.pinCode = '';
|
||||
myWalletProvider.pinCode = '';
|
||||
|
||||
if (chestBox.isEmpty) {
|
||||
await configBox.put('currentChest', 0);
|
||||
|
@ -38,34 +40,33 @@ class ChestProvider with ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
List<String> getChestWallets(ChestData _chest) {
|
||||
List<String> getChestWallets(ChestData chest) {
|
||||
List<String> toDelete = [];
|
||||
log.d(_chest.key);
|
||||
log.d(chest.key);
|
||||
walletBox.toMap().forEach((key, WalletData value) {
|
||||
if (value.chest == _chest.key) {
|
||||
if (value.chest == chest.key) {
|
||||
toDelete.add(value.address!);
|
||||
}
|
||||
});
|
||||
return toDelete;
|
||||
}
|
||||
|
||||
Future<bool?> _confirmDeletingChest(context, String? _walletName) async {
|
||||
Future<bool?> _confirmDeletingChest(context, String? walletName) async {
|
||||
return showDialog<bool>(
|
||||
context: context,
|
||||
barrierDismissible: true, // user must tap button!
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(
|
||||
'Êtes-vous sûr de vouloir supprimer le coffre "$_walletName" ?'),
|
||||
title: Text('areYouSureToDeleteWallet'.tr(args: [walletName!])),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: const Text("Non", key: Key('cancelDeleting')),
|
||||
child: Text("no".tr(), key: keyCancel),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, false);
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: const Text("Oui", key: Key('confirmDeleting')),
|
||||
child: Text("yes".tr(), key: keyConfirm),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, true);
|
||||
},
|
||||
|
|
|
@ -0,0 +1,449 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
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/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;
|
||||
|
||||
void reload() {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<bool> checkIndexerEndpoint(String endpoint) async {
|
||||
isLoadingIndexer = true;
|
||||
notifyListeners();
|
||||
final client = HttpClient();
|
||||
client.connectionTimeout = const Duration(milliseconds: 4000);
|
||||
try {
|
||||
final request = await client.postUrl(Uri.parse('$endpoint/v1/graphql'));
|
||||
final response = await request.close();
|
||||
if (response.statusCode != 200) {
|
||||
log.d('INDEXER IS OFFILINE');
|
||||
indexerEndpoint = '';
|
||||
isLoadingIndexer = false;
|
||||
notifyListeners();
|
||||
return false;
|
||||
} else {
|
||||
indexerEndpoint = endpoint;
|
||||
await configBox.put('indexerEndpoint', endpoint);
|
||||
// await configBox.put('customEndpoint', endpoint);
|
||||
isLoadingIndexer = false;
|
||||
notifyListeners();
|
||||
final cache = HiveStore();
|
||||
cache.reset();
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
log.d('INDEXER IS OFFILINE');
|
||||
indexerEndpoint = '';
|
||||
isLoadingIndexer = false;
|
||||
notifyListeners();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Future checkIndexerEndpointBackground() async {
|
||||
// final oldEndpoint = indexerEndpoint;
|
||||
// while (true) {
|
||||
// await Future.delayed(const Duration(seconds: 30));
|
||||
// final isValid = await checkIndexerEndpoint(oldEndpoint);
|
||||
// if (!isValid) {
|
||||
// log.d('INDEXER IS OFFILINE');
|
||||
// indexerEndpoint = '';
|
||||
// } else {
|
||||
// // log.d('Indexer is online');
|
||||
// indexerEndpoint = oldEndpoint;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
Future<String> getValidIndexerEndpoint() async {
|
||||
// await configBox.delete('indexerEndpoint');
|
||||
|
||||
listIndexerEndpoints = await rootBundle
|
||||
.loadString('config/indexer_endpoints.json')
|
||||
.then((jsonStr) => jsonDecode(jsonStr));
|
||||
// _listEndpoints.shuffle();
|
||||
|
||||
log.d(listIndexerEndpoints);
|
||||
listIndexerEndpoints.add('Personnalisé');
|
||||
|
||||
if (configBox.containsKey('customIndexer')) {
|
||||
return configBox.get('customIndexer');
|
||||
// listIndexerEndpoints.insert(0, configBox.get('customIndexer'));
|
||||
}
|
||||
|
||||
if (configBox.containsKey('indexerEndpoint')) {
|
||||
if (await checkIndexerEndpoint(configBox.get('indexerEndpoint'))) {
|
||||
return configBox.get('indexerEndpoint');
|
||||
}
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
// String _endpoint = '';
|
||||
int statusCode = 0;
|
||||
|
||||
final client = HttpClient();
|
||||
client.connectionTimeout = const Duration(milliseconds: 3000);
|
||||
|
||||
do {
|
||||
int listLenght = listIndexerEndpoints.length - 1;
|
||||
if (i >= listLenght) {
|
||||
log.e('NO VALID INDEXER ENDPOINT FOUND');
|
||||
indexerEndpoint = '';
|
||||
break;
|
||||
}
|
||||
log.d('${i + 1}n indexer endpoint try: ${listIndexerEndpoints[i]}');
|
||||
|
||||
if (i != 0) {
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
}
|
||||
|
||||
try {
|
||||
String endpointPath = '${listIndexerEndpoints[i]}/v1/graphql';
|
||||
|
||||
final request = await client.postUrl(Uri.parse(endpointPath));
|
||||
final response = await request.close();
|
||||
|
||||
indexerEndpoint = listIndexerEndpoints[i];
|
||||
await configBox.put('indexerEndpoint', listIndexerEndpoints[i]);
|
||||
|
||||
statusCode = response.statusCode;
|
||||
i++;
|
||||
} on TimeoutException catch (_) {
|
||||
log.e('This endpoint is timeout, next');
|
||||
statusCode = 50;
|
||||
i++;
|
||||
continue;
|
||||
} on SocketException catch (_) {
|
||||
log.e('This endpoint is a bad endpoint, next');
|
||||
statusCode = 70;
|
||||
i++;
|
||||
continue;
|
||||
} on Exception {
|
||||
log.e('Unknown error');
|
||||
statusCode = 60;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
} while (statusCode != 200);
|
||||
|
||||
log.i('INDEXER: $indexerEndpoint');
|
||||
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 = [];
|
||||
int i = 0;
|
||||
|
||||
for (final trans in blockchainTX) {
|
||||
final transaction = trans['node'];
|
||||
final direction =
|
||||
transaction['issuer_pubkey'] != pubkey ? 'RECEIVED' : 'SENT';
|
||||
|
||||
transBC.add(i);
|
||||
transBC[i] = [];
|
||||
transBC[i].add(DateTime.parse(transaction['created_at']));
|
||||
final int amountBrut = transaction['amount'];
|
||||
final double amount = removeDecimalZero(amountBrut / 100);
|
||||
if (direction == "RECEIVED") {
|
||||
transBC[i].add(transaction['issuer_pubkey']);
|
||||
transBC[i].add(transaction['issuer']['identity']?['name'] ?? '');
|
||||
} else if (direction == "SENT") {
|
||||
transBC[i].add(transaction['receiver_pubkey']);
|
||||
transBC[i].add(transaction['receiver']['identity']?['name'] ?? '');
|
||||
}
|
||||
transBC[i].add(amount);
|
||||
transBC[i].add(direction);
|
||||
// transBC[i].add(''); //transaction comment
|
||||
|
||||
i++;
|
||||
}
|
||||
return transBC;
|
||||
}
|
||||
|
||||
FetchMoreOptions? checkQueryResult(result, opts, pubkey) {
|
||||
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++;
|
||||
|
||||
if (fetchMoreCursor != null) {
|
||||
opts = FetchMoreOptions(
|
||||
variables: {'cursor': fetchMoreCursor, 'number': nRepositories},
|
||||
updateQuery: (previousResultData, fetchMoreResultData) {
|
||||
final List<dynamic> repos = [
|
||||
...previousResultData!['transaction_connection']['edges']
|
||||
as List<dynamic>,
|
||||
...fetchMoreResultData!['transaction_connection']['edges']
|
||||
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 {
|
||||
log.i("###### DEBUG H - Début de l'historique");
|
||||
}
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
double removeDecimalZero(double n) {
|
||||
String result = n.toStringAsFixed(n.truncateToDouble() == n ? 0 : 2);
|
||||
return double.parse(result);
|
||||
}
|
||||
|
||||
// checkHistoryResult(
|
||||
// QueryResult<Object?> result, FetchMoreOptions options, String address) {}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
import 'package:durt/durt.dart' as durt;
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:gecko/globals.dart';
|
||||
|
@ -22,7 +22,9 @@ class GenerateWalletsProvider with ChangeNotifier {
|
|||
FocusNode walletNameFocus = FocusNode();
|
||||
Color? askedWordColor = Colors.black;
|
||||
bool isAskedWordValid = false;
|
||||
int scanedValidWalletNumber = -1;
|
||||
int scanedWalletNumber = -1;
|
||||
int numberScan = 20;
|
||||
|
||||
late int nbrWord;
|
||||
String? nbrWordAlpha;
|
||||
|
@ -62,9 +64,9 @@ class GenerateWalletsProvider with ChangeNotifier {
|
|||
|
||||
String chestName;
|
||||
if (chestNumber == 0) {
|
||||
chestName = 'Coffre à Ğecko';
|
||||
chestName = 'geckoChest'.tr();
|
||||
} else {
|
||||
chestName = 'Coffre à Ğecko ${chestNumber + 1}';
|
||||
chestName = '${'geckoChest'.tr()}${chestNumber + 1}';
|
||||
}
|
||||
await configBox.put('currentChest', chestNumber);
|
||||
|
||||
|
@ -80,8 +82,8 @@ class GenerateWalletsProvider with ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
void checkAskedWord(String inputWord, String _mnemo) {
|
||||
final expectedWord = _mnemo.split(' ')[nbrWord];
|
||||
void checkAskedWord(String inputWord, String mnemo) {
|
||||
final expectedWord = mnemo.split(' ')[nbrWord];
|
||||
final normInputWord = unorm.nfkd(inputWord);
|
||||
|
||||
log.i("Is $expectedWord equal to input $normInputWord ?");
|
||||
|
@ -117,22 +119,22 @@ class GenerateWalletsProvider with ChangeNotifier {
|
|||
return rng.nextInt(12);
|
||||
}
|
||||
|
||||
String? intToString(int _nbr) {
|
||||
String? intToString(int nbr) {
|
||||
Map nbrToString = {};
|
||||
nbrToString[1] = 'Premier';
|
||||
nbrToString[2] = 'Deuxième';
|
||||
nbrToString[3] = 'Troisième';
|
||||
nbrToString[4] = 'Quatrième';
|
||||
nbrToString[5] = 'Cinquième';
|
||||
nbrToString[6] = 'Sixième';
|
||||
nbrToString[7] = 'Septième';
|
||||
nbrToString[8] = 'Huitième';
|
||||
nbrToString[9] = 'Neuvième';
|
||||
nbrToString[10] = 'Dixième';
|
||||
nbrToString[11] = 'Onzième';
|
||||
nbrToString[12] = 'Douzième';
|
||||
nbrToString[1] = '1th'.tr();
|
||||
nbrToString[2] = '2th'.tr();
|
||||
nbrToString[3] = '3th'.tr();
|
||||
nbrToString[4] = '4th'.tr();
|
||||
nbrToString[5] = '5th'.tr();
|
||||
nbrToString[6] = '6th'.tr();
|
||||
nbrToString[7] = '7th'.tr();
|
||||
nbrToString[8] = '8th'.tr();
|
||||
nbrToString[9] = '9th'.tr();
|
||||
nbrToString[10] = '10th'.tr();
|
||||
nbrToString[11] = '11th'.tr();
|
||||
nbrToString[12] = '12th'.tr();
|
||||
|
||||
nbrWordAlpha = nbrToString[_nbr];
|
||||
nbrWordAlpha = nbrToString[nbr];
|
||||
|
||||
return nbrWordAlpha;
|
||||
}
|
||||
|
@ -221,12 +223,12 @@ class GenerateWalletsProvider with ChangeNotifier {
|
|||
}
|
||||
|
||||
Future<void> generateCesiumWalletPubkey(
|
||||
String _cesiumID, String _cesiumPWD) async {
|
||||
cesiumWallet = durt.CesiumWallet(_cesiumID, _cesiumPWD);
|
||||
String _walletPubkey = cesiumWallet.pubkey;
|
||||
String cesiumID, String cesiumPWD) async {
|
||||
cesiumWallet = durt.CesiumWallet(cesiumID, cesiumPWD);
|
||||
String walletPubkey = cesiumWallet.pubkey;
|
||||
|
||||
cesiumPubkey.text = _walletPubkey;
|
||||
log.d(_walletPubkey);
|
||||
cesiumPubkey.text = walletPubkey;
|
||||
log.d(walletPubkey);
|
||||
}
|
||||
|
||||
void cesiumIDisVisible() {
|
||||
|
@ -247,19 +249,19 @@ class GenerateWalletsProvider with ChangeNotifier {
|
|||
}
|
||||
|
||||
Future<List<String>> generateWordList(BuildContext context) async {
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
generatedMnemonic = await _sub.generateMnemonic(lang: appLang);
|
||||
List<String> _wordsList = [];
|
||||
generatedMnemonic = await sub.generateMnemonic(lang: appLang);
|
||||
List<String> wordsList = [];
|
||||
String word;
|
||||
int _nbr = 1;
|
||||
int nbr = 1;
|
||||
|
||||
for (word in generatedMnemonic!.split(' ')) {
|
||||
_wordsList.add("$_nbr:$word");
|
||||
_nbr++;
|
||||
wordsList.add("$nbr:$word");
|
||||
nbr++;
|
||||
}
|
||||
|
||||
return _wordsList;
|
||||
return wordsList;
|
||||
}
|
||||
|
||||
bool isBipWord(String word, [bool checkRedondance = true]) {
|
||||
|
@ -351,6 +353,7 @@ class GenerateWalletsProvider with ChangeNotifier {
|
|||
cellController10,
|
||||
cellController11
|
||||
];
|
||||
if (sentence?.text == null) return;
|
||||
for (var word in sentence!.text!.split(' ')) {
|
||||
bool isValid = isBipWord(word, false);
|
||||
|
||||
|
@ -365,42 +368,48 @@ class GenerateWalletsProvider with ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<bool> scanDerivations(BuildContext context,
|
||||
{int numberScan = 20}) async {
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
final ss58 = _sub.ss58;
|
||||
Future<bool> scanDerivations(BuildContext context) async {
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
final currentChestNumber = configBox.get('currentChest');
|
||||
bool isAlive = false;
|
||||
scanedValidWalletNumber = 0;
|
||||
scanedWalletNumber = 0;
|
||||
notifyListeners();
|
||||
|
||||
final hasRoot = await scanRootBalance(_sub, currentChestNumber);
|
||||
if (!sub.nodeConnected) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final hasRoot = await scanRootBalance(sub, currentChestNumber);
|
||||
scanedWalletNumber = 1;
|
||||
notifyListeners();
|
||||
if (hasRoot) {
|
||||
scanedWalletNumber = 1;
|
||||
scanedValidWalletNumber = 1;
|
||||
isAlive = true;
|
||||
}
|
||||
|
||||
for (var derivationNbr in [for (var i = 0; i < numberScan; i += 1) i]) {
|
||||
final addressData = await _sub.sdk.api.keyring.addressFromMnemonic(ss58,
|
||||
final addressData = await sub.sdk.api.keyring.addressFromMnemonic(
|
||||
sub.currencyParameters['ss58']!,
|
||||
cryptoType: CryptoType.sr25519,
|
||||
mnemonic: generatedMnemonic!,
|
||||
derivePath: '//$derivationNbr');
|
||||
|
||||
final balance = await _sub.getBalance(addressData.address!).timeout(
|
||||
final Map balance = await sub.getBalance(addressData.address!).timeout(
|
||||
const Duration(seconds: 1),
|
||||
onTimeout: () => 0,
|
||||
onTimeout: () => {'transferableBalance': 0},
|
||||
);
|
||||
// const balance = 0;
|
||||
|
||||
log.d(balance);
|
||||
if (balance != 0) {
|
||||
log.d(
|
||||
"${addressData.address!}: ${balance['transferableBalance']} $currencyName");
|
||||
if (balance['transferableBalance'] != 0) {
|
||||
isAlive = true;
|
||||
String walletName = scanedWalletNumber == 0
|
||||
? 'Mon portefeuille courant'
|
||||
: 'Portefeuille ${scanedWalletNumber + 1}';
|
||||
await _sub.importAccount(
|
||||
mnemonic: '',
|
||||
fromMnemonic: true,
|
||||
String walletName = scanedValidWalletNumber == 0
|
||||
? 'currentWallet'.tr()
|
||||
: '${'wallet'.tr()} ${scanedValidWalletNumber + 1}';
|
||||
await sub.importAccount(
|
||||
mnemonic: generatedMnemonic!,
|
||||
derivePath: '//$derivationNbr',
|
||||
password: pin.text);
|
||||
|
||||
|
@ -408,34 +417,39 @@ class GenerateWalletsProvider with ChangeNotifier {
|
|||
version: dataVersion,
|
||||
chest: currentChestNumber,
|
||||
address: addressData.address!,
|
||||
number: scanedWalletNumber,
|
||||
number: scanedValidWalletNumber,
|
||||
name: walletName,
|
||||
derivation: derivationNbr,
|
||||
imageDefaultPath: '${scanedWalletNumber % 4}.png');
|
||||
imageDefaultPath: '${scanedValidWalletNumber % 4}.png');
|
||||
await walletBox.add(myWallet);
|
||||
scanedWalletNumber = scanedWalletNumber + 1;
|
||||
scanedValidWalletNumber = scanedValidWalletNumber + 1;
|
||||
}
|
||||
scanedWalletNumber = scanedWalletNumber + 1;
|
||||
notifyListeners();
|
||||
}
|
||||
log.d(scanedWalletNumber);
|
||||
scanedWalletNumber = -1;
|
||||
scanedValidWalletNumber = -1;
|
||||
notifyListeners();
|
||||
return isAlive;
|
||||
}
|
||||
|
||||
Future<bool> scanRootBalance(
|
||||
SubstrateSdk _sub, int currentChestNumber) async {
|
||||
final addressData = await _sub.sdk.api.keyring.addressFromMnemonic(ss58,
|
||||
cryptoType: CryptoType.sr25519, mnemonic: generatedMnemonic!);
|
||||
Future<bool> scanRootBalance(SubstrateSdk sub, int currentChestNumber) async {
|
||||
final addressData = await sub.sdk.api.keyring.addressFromMnemonic(
|
||||
sub.currencyParameters['ss58']!,
|
||||
cryptoType: CryptoType.sr25519,
|
||||
mnemonic: generatedMnemonic!);
|
||||
|
||||
final balance = await _sub.getBalance(addressData.address!).timeout(
|
||||
final balance = await sub.getBalance(addressData.address!).timeout(
|
||||
const Duration(seconds: 1),
|
||||
onTimeout: () => 0,
|
||||
onTimeout: () => {},
|
||||
);
|
||||
|
||||
log.d(balance);
|
||||
if (balance != 0) {
|
||||
String walletName = 'Mon portefeuille racine';
|
||||
await _sub.importAccount(
|
||||
mnemonic: '', fromMnemonic: true, password: pin.text);
|
||||
log.d(
|
||||
"${addressData.address!}: ${balance['transferableBalance']} $currencyName");
|
||||
if (balance['transferableBalance'] != 0) {
|
||||
String walletName = 'myRootWallet'.tr();
|
||||
await sub.importAccount(mnemonic: generatedMnemonic!, password: pin.text);
|
||||
|
||||
WalletData myWallet = WalletData(
|
||||
version: dataVersion,
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
// import 'package:audioplayers/audio_cache.dart';
|
||||
// import 'package:audioplayers/audioplayers.dart';
|
||||
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';
|
||||
|
@ -25,10 +31,8 @@ class HomeProvider with ChangeNotifier {
|
|||
Icon searchIcon = const Icon(Icons.search);
|
||||
final TextEditingController searchQuery = TextEditingController();
|
||||
Widget appBarTitle = Text('Ğecko', style: TextStyle(color: Colors.grey[850]));
|
||||
Widget appBarExplorer =
|
||||
Text('Explorateur', style: TextStyle(color: Colors.grey[850]));
|
||||
String homeMessage = "y'a pas de lézard ;-)";
|
||||
String defaultMessage = "y'a pas de lézard ;-)";
|
||||
String homeMessage = "loading".tr();
|
||||
String defaultMessage = "noLizard".tr();
|
||||
|
||||
Future<void> initHive() async {
|
||||
late Directory hivePath;
|
||||
|
@ -61,6 +65,15 @@ class HomeProvider with ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
Future changeCurrencyUnit(BuildContext context) async {
|
||||
final sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
final bool isUdUnit = configBox.get('isUdUnit') ?? false;
|
||||
await configBox.put('isUdUnit', !isUdUnit);
|
||||
balanceCache = {};
|
||||
sub.getBalanceRatio();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<String> getAppVersion() async {
|
||||
String version;
|
||||
String buildNumber;
|
||||
|
@ -71,7 +84,7 @@ class HomeProvider with ChangeNotifier {
|
|||
: (int.parse(packageInfo.buildNumber) - 1000).toString();
|
||||
|
||||
notifyListeners();
|
||||
return version + '+' + buildNumber;
|
||||
return '$version+$buildNumber';
|
||||
}
|
||||
|
||||
Future changeMessage(String newMessage, int seconds) async {
|
||||
|
@ -84,20 +97,23 @@ class HomeProvider with ChangeNotifier {
|
|||
|
||||
Future<List?> getValidEndpoints() async {
|
||||
await configBox.delete('endpoint');
|
||||
if (!configBox.containsKey('autoEndpoint')) {
|
||||
configBox.put('autoEndpoint', true);
|
||||
}
|
||||
|
||||
List _listEndpoints = [];
|
||||
List listEndpoints = [];
|
||||
if (!configBox.containsKey('endpoint') ||
|
||||
configBox.get('endpoint') == [] ||
|
||||
configBox.get('endpoint') == '') {
|
||||
_listEndpoints = await rootBundle
|
||||
listEndpoints = await rootBundle
|
||||
.loadString('config/gdev_endpoints.json')
|
||||
.then((jsonStr) => jsonDecode(jsonStr));
|
||||
_listEndpoints.shuffle();
|
||||
configBox.put('endpoint', _listEndpoints);
|
||||
listEndpoints.shuffle();
|
||||
configBox.put('endpoint', listEndpoints);
|
||||
}
|
||||
|
||||
log.i('ENDPOINT: ' + _listEndpoints.toString());
|
||||
return _listEndpoints;
|
||||
log.i('ENDPOINT: $listEndpoints');
|
||||
return listEndpoints;
|
||||
}
|
||||
|
||||
T getRandomElement<T>(List<T> list) {
|
||||
|
@ -117,17 +133,17 @@ class HomeProvider with ChangeNotifier {
|
|||
// }
|
||||
|
||||
Widget bottomAppBar(BuildContext context) {
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
WalletsProfilesProvider _historyProvider =
|
||||
WalletsProfilesProvider historyProvider =
|
||||
Provider.of<WalletsProfilesProvider>(context, listen: false);
|
||||
|
||||
final size = MediaQuery.of(context).size;
|
||||
|
||||
const bool _showBottomBar = true;
|
||||
const bool showBottomBar = true;
|
||||
|
||||
return Visibility(
|
||||
visible: _showBottomBar,
|
||||
visible: showBottomBar,
|
||||
child: Container(
|
||||
color: yellowC,
|
||||
width: size.width,
|
||||
|
@ -144,6 +160,7 @@ class HomeProvider with ChangeNotifier {
|
|||
const Spacer(),
|
||||
const SizedBox(width: 11),
|
||||
IconButton(
|
||||
key: keyAppBarSearch,
|
||||
iconSize: 40,
|
||||
icon: const Image(image: AssetImage('assets/loupe-noire.png')),
|
||||
onPressed: () {
|
||||
|
@ -162,6 +179,7 @@ class HomeProvider with ChangeNotifier {
|
|||
const SizedBox(width: 22),
|
||||
const Spacer(),
|
||||
IconButton(
|
||||
key: keyAppBarQrcode,
|
||||
iconSize: 70,
|
||||
icon: const Image(image: AssetImage('assets/qrcode-scan.png')),
|
||||
onPressed: () async {
|
||||
|
@ -169,19 +187,20 @@ class HomeProvider with ChangeNotifier {
|
|||
context,
|
||||
ModalRoute.withName('/'),
|
||||
);
|
||||
_historyProvider.scan(homeContext);
|
||||
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(
|
||||
WalletData? defaultWallet = myWalletProvider.getDefaultWallet();
|
||||
String? pin;
|
||||
if (myWalletProvider.pinCode == '') {
|
||||
pin = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (homeContext) {
|
||||
|
@ -191,7 +210,7 @@ class HomeProvider with ChangeNotifier {
|
|||
);
|
||||
}
|
||||
|
||||
if (_pin != null || _myWalletProvider.pinCode != '') {
|
||||
if (pin != null || myWalletProvider.pinCode != '') {
|
||||
Navigator.popUntil(
|
||||
context,
|
||||
ModalRoute.withName('/'),
|
||||
|
@ -211,42 +230,7 @@ class HomeProvider with ChangeNotifier {
|
|||
);
|
||||
}
|
||||
|
||||
void handleSearchEnd() {
|
||||
searchIcon = Icon(
|
||||
Icons.search,
|
||||
color: Colors.grey[850],
|
||||
);
|
||||
appBarTitle = Text('Ğecko', style: TextStyle(color: Colors.grey[850]));
|
||||
appBarExplorer =
|
||||
Text('Explorateur', style: TextStyle(color: Colors.grey[850]));
|
||||
isSearching = false;
|
||||
searchQuery.clear();
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void rebuildWidget() {
|
||||
void reload() {
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
class CustomRoundedButton extends CustomPainter {
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
Paint paint = Paint()
|
||||
..color = yellowC
|
||||
..style = PaintingStyle.fill;
|
||||
Path path = Path();
|
||||
path.lineTo(size.width * 0.4, 0);
|
||||
path.quadraticBezierTo(size.width * 0.5, -40, size.width * 0.6, 0);
|
||||
path.lineTo(size.width, 0);
|
||||
path.lineTo(size.width, size.height);
|
||||
path.lineTo(0, size.height);
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:async';
|
||||
import 'package:gecko/globals.dart';
|
||||
|
@ -12,6 +13,8 @@ class MyWalletsProvider with ChangeNotifier {
|
|||
late String mnemonic;
|
||||
int? pinLenght;
|
||||
bool isNewDerivationLoading = false;
|
||||
String lastFlyBy = '';
|
||||
String dragAddress = '';
|
||||
|
||||
int getCurrentChest() {
|
||||
if (configBox.get('currentChest') == null) {
|
||||
|
@ -30,11 +33,11 @@ class MyWalletsProvider with ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
List<WalletData> readAllWallets([int? _chest]) {
|
||||
_chest = _chest ?? configBox.get('currentChest') ?? 0;
|
||||
List<WalletData> readAllWallets([int? chest]) {
|
||||
chest = chest ?? configBox.get('currentChest') ?? 0;
|
||||
listWallets.clear();
|
||||
walletBox.toMap().forEach((key, value) {
|
||||
if (value.chest == _chest) {
|
||||
if (value.chest == chest) {
|
||||
listWallets.add(value);
|
||||
}
|
||||
});
|
||||
|
@ -42,33 +45,33 @@ class MyWalletsProvider with ChangeNotifier {
|
|||
return listWallets;
|
||||
}
|
||||
|
||||
WalletData? getWalletDataById(List<int?> _id) {
|
||||
if (_id.isEmpty) return WalletData();
|
||||
int? _chest = _id[0];
|
||||
int? _nbr = _id[1];
|
||||
WalletData? _targetedWallet;
|
||||
WalletData? getWalletDataById(List<int?> id) {
|
||||
if (id.isEmpty) return WalletData();
|
||||
int? chest = id[0];
|
||||
int? nbr = id[1];
|
||||
WalletData? targetedWallet;
|
||||
|
||||
walletBox.toMap().forEach((key, value) {
|
||||
if (value.chest == _chest && value.number == _nbr) {
|
||||
_targetedWallet = value;
|
||||
if (value.chest == chest && value.number == nbr) {
|
||||
targetedWallet = value;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return _targetedWallet;
|
||||
return targetedWallet;
|
||||
}
|
||||
|
||||
WalletData? getWalletDataByAddress(String address) {
|
||||
WalletData? _targetedWallet;
|
||||
WalletData? targetedWallet;
|
||||
|
||||
walletBox.toMap().forEach((key, value) {
|
||||
if (value.address == address) {
|
||||
_targetedWallet = value;
|
||||
targetedWallet = value;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return _targetedWallet;
|
||||
return targetedWallet;
|
||||
}
|
||||
|
||||
WalletData getDefaultWallet([int? chest]) {
|
||||
|
@ -83,21 +86,21 @@ class MyWalletsProvider with ChangeNotifier {
|
|||
}
|
||||
|
||||
Future<int> deleteAllWallet(context) async {
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
try {
|
||||
log.w('DELETE ALL WALLETS ?');
|
||||
|
||||
final bool? _answer = await (confirmPopup(
|
||||
context, 'Êtes-vous sûr de vouloir oublier tous vos coffres ?'));
|
||||
if (_answer!) {
|
||||
final bool? answer =
|
||||
await (confirmPopup(context, 'areYouSureForgetAllChests'.tr()));
|
||||
if (answer!) {
|
||||
await walletBox.clear();
|
||||
await chestBox.clear();
|
||||
await configBox.delete('defaultWallet');
|
||||
await _sub.deleteAllAccounts();
|
||||
await sub.deleteAllAccounts();
|
||||
|
||||
_myWalletProvider.pinCode = '';
|
||||
myWalletProvider.pinCode = '';
|
||||
|
||||
await Navigator.of(context).pushNamedAndRemoveUntil(
|
||||
'/',
|
||||
|
@ -110,32 +113,32 @@ class MyWalletsProvider with ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> generateNewDerivation(context, String _name,
|
||||
Future<void> generateNewDerivation(context, String name,
|
||||
[int? number]) async {
|
||||
isNewDerivationLoading = true;
|
||||
notifyListeners();
|
||||
|
||||
final List idList = getNextWalletNumberAndDerivation();
|
||||
int _newWalletNbr = idList[0];
|
||||
int _newDerivationNbr = number ?? idList[1];
|
||||
int newWalletNbr = idList[0];
|
||||
int newDerivationNbr = number ?? idList[1];
|
||||
|
||||
int? _chest = getCurrentChest();
|
||||
int? chest = getCurrentChest();
|
||||
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
WalletData defaultWallet = getDefaultWallet();
|
||||
|
||||
final address = await _sub.derive(
|
||||
context, defaultWallet.address!, _newDerivationNbr, pinCode);
|
||||
final address = await sub.derive(
|
||||
context, defaultWallet.address!, newDerivationNbr, pinCode);
|
||||
|
||||
WalletData newWallet = WalletData(
|
||||
version: dataVersion,
|
||||
chest: _chest,
|
||||
chest: chest,
|
||||
address: address,
|
||||
number: _newWalletNbr,
|
||||
name: _name,
|
||||
derivation: _newDerivationNbr,
|
||||
imageDefaultPath: '${_newWalletNbr % 4}.png');
|
||||
number: newWalletNbr,
|
||||
name: name,
|
||||
derivation: newDerivationNbr,
|
||||
imageDefaultPath: '${newWalletNbr % 4}.png');
|
||||
|
||||
await walletBox.add(newWallet);
|
||||
|
||||
|
@ -143,37 +146,37 @@ class MyWalletsProvider with ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> generateRootWallet(context, String _name) async {
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
Future<void> generateRootWallet(context, String name) async {
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
|
||||
isNewDerivationLoading = true;
|
||||
notifyListeners();
|
||||
int _newWalletNbr;
|
||||
int? _chest = getCurrentChest();
|
||||
int newWalletNbr;
|
||||
int? chest = getCurrentChest();
|
||||
|
||||
List<WalletData> _walletConfig = readAllWallets(_chest);
|
||||
List<WalletData> walletConfig = readAllWallets(chest);
|
||||
|
||||
if (_walletConfig.isEmpty) {
|
||||
_newWalletNbr = 0;
|
||||
if (walletConfig.isEmpty) {
|
||||
newWalletNbr = 0;
|
||||
} else {
|
||||
_newWalletNbr = _walletConfig.last.number! + 1;
|
||||
newWalletNbr = walletConfig.last.number! + 1;
|
||||
}
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
WalletData defaultWallet = _myWalletProvider.getDefaultWallet();
|
||||
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,
|
||||
chest: chest,
|
||||
address: address,
|
||||
number: _newWalletNbr,
|
||||
name: _name,
|
||||
number: newWalletNbr,
|
||||
name: name,
|
||||
derivation: -1,
|
||||
imageDefaultPath: '${_newWalletNbr % 4}.png');
|
||||
imageDefaultPath: '${newWalletNbr % 4}.png');
|
||||
|
||||
await walletBox.add(newWallet);
|
||||
|
||||
|
@ -183,29 +186,29 @@ class MyWalletsProvider with ChangeNotifier {
|
|||
|
||||
List<int> getNextWalletNumberAndDerivation(
|
||||
{int? chestNumber, bool isOneshoot = false}) {
|
||||
int _newDerivationNbr = 0;
|
||||
int _newWalletNbr = 0;
|
||||
int newDerivationNbr = 0;
|
||||
int newWalletNbr = 0;
|
||||
|
||||
chestNumber ??= getCurrentChest();
|
||||
|
||||
List<WalletData> _walletConfig = readAllWallets(chestNumber);
|
||||
List<WalletData> walletConfig = readAllWallets(chestNumber);
|
||||
|
||||
if (_walletConfig.isEmpty) {
|
||||
_newDerivationNbr = 2;
|
||||
if (walletConfig.isEmpty) {
|
||||
newDerivationNbr = 2;
|
||||
} else {
|
||||
WalletData _lastWallet = _walletConfig.reduce(
|
||||
WalletData lastWallet = walletConfig.reduce(
|
||||
(curr, next) => curr.derivation! > next.derivation! ? curr : next);
|
||||
|
||||
if (_lastWallet.derivation == -1) {
|
||||
_newDerivationNbr = 2;
|
||||
if (lastWallet.derivation == -1) {
|
||||
newDerivationNbr = 2;
|
||||
} else {
|
||||
_newDerivationNbr = _lastWallet.derivation! + (isOneshoot ? 1 : 2);
|
||||
newDerivationNbr = lastWallet.derivation! + (isOneshoot ? 1 : 2);
|
||||
}
|
||||
|
||||
_newWalletNbr = _walletConfig.last.number! + 1;
|
||||
newWalletNbr = walletConfig.last.number! + 1;
|
||||
}
|
||||
|
||||
return [_newWalletNbr, _newDerivationNbr];
|
||||
return [newWalletNbr, newDerivationNbr];
|
||||
}
|
||||
|
||||
int lockPin = 0;
|
||||
|
@ -218,7 +221,7 @@ class MyWalletsProvider with ChangeNotifier {
|
|||
if (actualLock == lockPin) pinCode = '';
|
||||
}
|
||||
|
||||
void rebuildWidget() {
|
||||
void reload() {
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ class SearchProvider with ChangeNotifier {
|
|||
final cacheDuring = 20 * 60 * 1000; //First number is minutes
|
||||
int cacheTime = 0;
|
||||
|
||||
void rebuildWidget() {
|
||||
void reload() {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
@ -68,12 +68,12 @@ class SearchProvider with ChangeNotifier {
|
|||
// }
|
||||
|
||||
Future<List<G1WalletsList>> searchAddress() async {
|
||||
final WalletsProfilesProvider _walletProfiles =
|
||||
final WalletsProfilesProvider walletProfiles =
|
||||
WalletsProfilesProvider('pubkey');
|
||||
|
||||
if (_walletProfiles.isAddress(searchController.text)) {
|
||||
G1WalletsList _wallet = G1WalletsList(pubkey: searchController.text);
|
||||
return [_wallet];
|
||||
if (walletProfiles.isAddress(searchController.text)) {
|
||||
G1WalletsList wallet = G1WalletsList(address: searchController.text);
|
||||
return [wallet];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class SettingsProvider with ChangeNotifier {
|
||||
void reload() {
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
|
@ -1,7 +1,13 @@
|
|||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'dart:io';
|
||||
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/widgets_keys.dart';
|
||||
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';
|
||||
|
@ -11,6 +17,8 @@ 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();
|
||||
|
@ -23,65 +31,47 @@ class WalletOptionsProvider with ChangeNotifier {
|
|||
FocusNode walletNameFocus = FocusNode();
|
||||
TextEditingController nameController = TextEditingController();
|
||||
late bool isDefaultWallet;
|
||||
|
||||
bool canValidateNameBool = false;
|
||||
Map<String, String> idtyStatusCache = {};
|
||||
Future<NewWallet>? get badWallet => null;
|
||||
|
||||
int getPinLenght(_walletNbr) {
|
||||
int getPinLenght(walletNbr) {
|
||||
return pinLength;
|
||||
}
|
||||
|
||||
void _renameWallet(List<int?> _walletID, String _newName,
|
||||
void _renameWallet(List<int?> walletID, String newName,
|
||||
{required bool isCesium}) async {
|
||||
MyWalletsProvider myWalletClass = MyWalletsProvider();
|
||||
|
||||
WalletData _walletTarget = myWalletClass.getWalletDataById(_walletID)!;
|
||||
_walletTarget.name = _newName;
|
||||
await walletBox.put(_walletTarget.key, _walletTarget);
|
||||
WalletData walletTarget = myWalletClass.getWalletDataById(walletID)!;
|
||||
walletTarget.name = newName;
|
||||
await walletBox.put(walletTarget.key, walletTarget);
|
||||
|
||||
_newWalletName.text = '';
|
||||
}
|
||||
|
||||
bool editWalletName(List<int?> _wID, {bool? isCesium}) {
|
||||
bool nameState;
|
||||
if (isEditing) {
|
||||
if (!nameController.text.contains(':') &&
|
||||
nameController.text.length <= 39) {
|
||||
_renameWallet(_wID, nameController.text, isCesium: isCesium!);
|
||||
nameState = true;
|
||||
} else {
|
||||
nameState = false;
|
||||
}
|
||||
} else {
|
||||
nameState = true;
|
||||
}
|
||||
|
||||
isEditing ? isEditing = false : isEditing = true;
|
||||
notifyListeners();
|
||||
return nameState;
|
||||
}
|
||||
|
||||
Future<int> deleteWallet(context, WalletData wallet) async {
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
final bool? _answer = await (confirmPopup(context,
|
||||
'Êtes-vous sûr de vouloir oublier le portefeuille "${wallet.name}" ?'));
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
final bool? answer = await (confirmPopup(
|
||||
context, 'areYouSureToForgetWallet'.tr(args: [wallet.name!])));
|
||||
|
||||
if (_answer ?? false) {
|
||||
if (answer ?? false) {
|
||||
//Check if balance is null
|
||||
final _balance = await _sub.getBalance(wallet.address!);
|
||||
if (_balance != 0) {
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
final balance = await sub.getBalance(wallet.address!);
|
||||
if (balance != {}) {
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
final _defaultWallet = _myWalletProvider.getDefaultWallet();
|
||||
log.d(_defaultWallet.address);
|
||||
_sub.pay(
|
||||
final defaultWallet = myWalletProvider.getDefaultWallet();
|
||||
log.d(defaultWallet.address);
|
||||
sub.pay(
|
||||
fromAddress: wallet.address!,
|
||||
destAddress: _defaultWallet.address!,
|
||||
destAddress: defaultWallet.address!,
|
||||
amount: -1,
|
||||
password: _myWalletProvider.pinCode);
|
||||
password: myWalletProvider.pinCode);
|
||||
}
|
||||
|
||||
await walletBox.delete(wallet.key);
|
||||
await _sub.deleteAccounts([wallet.address!]);
|
||||
await sub.deleteAccounts([wallet.address!]);
|
||||
|
||||
Navigator.pop(context);
|
||||
}
|
||||
|
@ -106,14 +96,33 @@ class WalletOptionsProvider with ChangeNotifier {
|
|||
return '';
|
||||
}
|
||||
|
||||
CroppedFile? croppedFile = await ImageCropper().cropImage(
|
||||
sourcePath: imageFile.path,
|
||||
aspectRatioPresets: [CropAspectRatioPreset.square],
|
||||
cropStyle: CropStyle.circle,
|
||||
uiSettings: [
|
||||
AndroidUiSettings(
|
||||
hideBottomControls: true,
|
||||
toolbarTitle: 'Personnalisation',
|
||||
toolbarColor: Colors.deepOrange,
|
||||
toolbarWidgetColor: Colors.white,
|
||||
initAspectRatio: CropAspectRatioPreset.original,
|
||||
lockAspectRatio: true),
|
||||
IOSUiSettings(
|
||||
title: 'Cropper',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final newPath = "${imageDirectory.path}/${pickedFile.name}";
|
||||
|
||||
await imageFile.copy(newPath);
|
||||
// final File newImage = File(newPath);
|
||||
|
||||
// await newImage.writeAsBytes(await pickedFile.readAsBytes());
|
||||
// await pickedFile.saveTo(newPath);
|
||||
// await Future.delayed(const Duration(milliseconds: 100));
|
||||
if (croppedFile != null) {
|
||||
await File(croppedFile.path).rename(newPath);
|
||||
} else {
|
||||
log.w('No image selected.');
|
||||
return '';
|
||||
}
|
||||
// await imageFile.copy(newPath);
|
||||
|
||||
log.i(newPath);
|
||||
return newPath;
|
||||
|
@ -125,9 +134,12 @@ class WalletOptionsProvider with ChangeNotifier {
|
|||
|
||||
Widget idtyStatus(BuildContext context, String address,
|
||||
{bool isOwner = false, Color color = Colors.black}) {
|
||||
_showText(String text,
|
||||
[double size = 18, bool _bold = false, bool smooth = true]) {
|
||||
log.d(text);
|
||||
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),
|
||||
|
@ -136,69 +148,80 @@ class WalletOptionsProvider with ChangeNotifier {
|
|||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: size,
|
||||
color: _bold ? color : Colors.black,
|
||||
fontWeight: _bold ? FontWeight.w500 : FontWeight.w400),
|
||||
color: bold ? color : Colors.black,
|
||||
fontWeight: bold ? FontWeight.w500 : FontWeight.w400),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Consumer<SubstrateSdk>(builder: (context, _sub, _) {
|
||||
return Consumer<SubstrateSdk>(builder: (context, sub, _) {
|
||||
return FutureBuilder(
|
||||
future: _sub.idtyStatus(address),
|
||||
future: sub.idtyStatus(address),
|
||||
initialData: '',
|
||||
builder: (context, snapshot) {
|
||||
idtyStatusCache[address] = snapshot.data.toString();
|
||||
switch (snapshot.data.toString()) {
|
||||
case 'noid':
|
||||
{
|
||||
return _showText('Aucune identité');
|
||||
return showText('noIdentity'.tr());
|
||||
}
|
||||
case 'Created':
|
||||
{
|
||||
return isOwner
|
||||
? InkWell(
|
||||
child: _showText(
|
||||
'Cliquez ici pour confirmer\nvotre nouvelle identité',
|
||||
18,
|
||||
true),
|
||||
onTap: () async {
|
||||
await validateIdentity(context);
|
||||
},
|
||||
)
|
||||
: _showText('Identité créé');
|
||||
return showText('identityCreated'.tr());
|
||||
}
|
||||
case 'ConfirmedByOwner':
|
||||
{
|
||||
return _showText('Identité confirmé');
|
||||
return isOwner
|
||||
? showText('identityConfirmed'.tr())
|
||||
: duniterIndexer.getNameByAddress(
|
||||
context,
|
||||
address,
|
||||
null,
|
||||
20,
|
||||
true,
|
||||
Colors.grey[700]!,
|
||||
FontWeight.w500,
|
||||
FontStyle.italic);
|
||||
}
|
||||
|
||||
case 'Validated':
|
||||
{
|
||||
return _showText('Membre validé !', 18, true);
|
||||
return isOwner
|
||||
? showText('memberValidated'.tr(), 18, true)
|
||||
: duniterIndexer.getNameByAddress(
|
||||
context,
|
||||
address,
|
||||
null,
|
||||
20,
|
||||
true,
|
||||
Colors.black,
|
||||
FontWeight.w600,
|
||||
FontStyle.normal);
|
||||
}
|
||||
|
||||
case 'expired':
|
||||
{
|
||||
return _showText('Identité expiré');
|
||||
return showText('identityExpired'.tr());
|
||||
}
|
||||
}
|
||||
return SizedBox(
|
||||
child: _showText('', 18, false, false),
|
||||
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';
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
return await sub.idtyStatus(address) == 'Validated';
|
||||
}
|
||||
|
||||
Future<String?> validateIdentity(BuildContext context) async {
|
||||
Future<String?> confirmIdentityPopup(BuildContext context) async {
|
||||
TextEditingController idtyName = TextEditingController();
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
WalletOptionsProvider _walletOptions =
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
WalletOptionsProvider walletOptions =
|
||||
Provider.of<WalletOptionsProvider>(context, listen: false);
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
|
||||
return showDialog<String>(
|
||||
|
@ -206,21 +229,23 @@ class WalletOptionsProvider with ChangeNotifier {
|
|||
barrierDismissible: true, // user must tap button!
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
'Confirmez votre identité',
|
||||
title: Text(
|
||||
'confirmYourIdentity'.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
|
||||
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
|
||||
),
|
||||
content: SizedBox(
|
||||
height: 100,
|
||||
child: Column(children: [
|
||||
const SizedBox(height: 20),
|
||||
const Text(
|
||||
'Nom:',
|
||||
style: TextStyle(fontSize: 19),
|
||||
),
|
||||
TextField(
|
||||
key: keyEnterIdentityUsername,
|
||||
onChanged: (_) => notifyListeners(),
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
// FilteringTextInputFormatter.allow(RegExp("[0-9a-zA-Z]")),
|
||||
FilteringTextInputFormatter.deny(RegExp(r'^ ')),
|
||||
// FilteringTextInputFormatter.deny(RegExp(r' $')),
|
||||
],
|
||||
textAlign: TextAlign.center,
|
||||
autofocus: true,
|
||||
controller: idtyName,
|
||||
|
@ -233,26 +258,30 @@ class WalletOptionsProvider with ChangeNotifier {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Consumer<WalletOptionsProvider>(
|
||||
builder: (context, _wOptions, _) {
|
||||
builder: (context, wOptions, _) {
|
||||
return TextButton(
|
||||
key: const Key('infoPopup'),
|
||||
key: keyConfirm,
|
||||
child: Text(
|
||||
"Valider",
|
||||
"validate".tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 21,
|
||||
color: idtyName.text.length >= 2
|
||||
color: idtyName.text.length.clamp(3, 64) ==
|
||||
idtyName.text.length
|
||||
? const Color(0xffD80000)
|
||||
: Colors.grey,
|
||||
),
|
||||
),
|
||||
onPressed: () async {
|
||||
if (idtyName.text.length >= 2) {
|
||||
WalletData? defaultWallet =
|
||||
_myWalletProvider.getDefaultWallet();
|
||||
idtyName.text = idtyName.text.trim().replaceAll(' ', '');
|
||||
|
||||
String? _pin;
|
||||
if (_myWalletProvider.pinCode == '') {
|
||||
_pin = await Navigator.push(
|
||||
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) {
|
||||
|
@ -261,19 +290,22 @@ class WalletOptionsProvider with ChangeNotifier {
|
|||
),
|
||||
);
|
||||
}
|
||||
if (_pin != null || _myWalletProvider.pinCode != '') {
|
||||
final _wallet = _myWalletProvider
|
||||
if (pin != null || myWalletProvider.pinCode != '') {
|
||||
final wallet = myWalletProvider
|
||||
.getWalletDataByAddress(address.text);
|
||||
await _sub.setCurrentWallet(_wallet!);
|
||||
_sub.confirmIdentity(_walletOptions.address.text,
|
||||
idtyName.text, _myWalletProvider.pinCode);
|
||||
await sub.setCurrentWallet(wallet!);
|
||||
sub.confirmIdentity(walletOptions.address.text,
|
||||
idtyName.text, myWalletProvider.pinCode);
|
||||
Navigator.pop(context);
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return const TransactionInProgress(
|
||||
transType: 'comfirmIdty');
|
||||
return TransactionInProgress(
|
||||
transType: 'comfirmIdty',
|
||||
fromAddress: getShortPubkey(wallet.address!),
|
||||
toAddress: getShortPubkey(wallet.address!),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
@ -290,7 +322,112 @@ class WalletOptionsProvider with ChangeNotifier {
|
|||
);
|
||||
}
|
||||
|
||||
void reloadBuild() {
|
||||
Future<String?> editWalletName(BuildContext context, List<int?> wID) async {
|
||||
TextEditingController walletName = TextEditingController();
|
||||
canValidateNameBool = false;
|
||||
|
||||
return showDialog<String>(
|
||||
context: context,
|
||||
barrierDismissible: true,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(
|
||||
'chooseWalletName'.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
|
||||
),
|
||||
content: SizedBox(
|
||||
height: 100,
|
||||
child: Column(children: [
|
||||
const SizedBox(height: 20),
|
||||
TextField(
|
||||
onChanged: (_) => canValidateName(context, walletName),
|
||||
textAlign: TextAlign.center,
|
||||
autofocus: true,
|
||||
controller: walletName,
|
||||
style: const TextStyle(fontSize: 19),
|
||||
)
|
||||
]),
|
||||
),
|
||||
actions: <Widget>[
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Consumer<WalletOptionsProvider>(
|
||||
builder: (context, wOptions, _) {
|
||||
return TextButton(
|
||||
key: keyInfoPopup,
|
||||
child: Text(
|
||||
"validate".tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 21,
|
||||
color: canValidateNameBool
|
||||
? const Color(0xffD80000)
|
||||
: Colors.grey,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
onPressed: () async {
|
||||
if (canValidateNameBool) {
|
||||
nameController.text = walletName.text;
|
||||
_renameWallet(wID, walletName.text, isCesium: false);
|
||||
// notifyListeners();
|
||||
Navigator.pop(context);
|
||||
}
|
||||
},
|
||||
);
|
||||
})
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
TextButton(
|
||||
key: keyCancel,
|
||||
child: Text(
|
||||
"cancel".tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: Colors.grey[800],
|
||||
fontWeight: FontWeight.w300),
|
||||
),
|
||||
onPressed: () async {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20)
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
bool canValidateName(BuildContext context, TextEditingController walletName) {
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
|
||||
bool isNameValid = walletName.text.length >= 2 &&
|
||||
!walletName.text.contains(':') &&
|
||||
walletName.text.length <= 39;
|
||||
|
||||
if (isNameValid) {
|
||||
for (var wallet in myWalletProvider.listWallets) {
|
||||
if (walletName.text == wallet.name!) {
|
||||
canValidateNameBool = false;
|
||||
break;
|
||||
}
|
||||
canValidateNameBool = true;
|
||||
}
|
||||
} else {
|
||||
canValidateNameBool = false;
|
||||
}
|
||||
notifyListeners();
|
||||
return canValidateNameBool;
|
||||
}
|
||||
|
||||
void reload() {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
@ -301,79 +438,167 @@ class WalletOptionsProvider with ChangeNotifier {
|
|||
}
|
||||
|
||||
String? getAddress(int chest, int derivation) {
|
||||
String? _address;
|
||||
String? addressGet;
|
||||
walletBox.toMap().forEach((key, value) {
|
||||
if (value.chest == chest && value.derivation == derivation) {
|
||||
_address = value.address!;
|
||||
addressGet = value.address!;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
address.text = _address ?? '';
|
||||
address.text = addressGet ?? '';
|
||||
|
||||
return _address;
|
||||
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 color = Colors.black,
|
||||
Color loadingColor = const Color(0xffd07316)]) {
|
||||
return Column(children: <Widget>[
|
||||
Consumer<SubstrateSdk>(builder: (context, _sdk, _) {
|
||||
Consumer<SubstrateSdk>(builder: (context, sdk, _) {
|
||||
return FutureBuilder(
|
||||
future: _sdk.getBalance(address),
|
||||
builder: (BuildContext context, AsyncSnapshot<double> _balance) {
|
||||
if (_balance.connectionState != ConnectionState.done ||
|
||||
_balance.hasError) {
|
||||
if (balanceCache[address] != null) {
|
||||
return Text(
|
||||
"${balanceCache[address]!.toString()} $currencyName",
|
||||
style: TextStyle(
|
||||
fontSize: isTall ? size : size * 0.9, color: _color));
|
||||
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: orangeC,
|
||||
color: loadingColor,
|
||||
strokeWidth: 2,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
balanceCache[address] = _balance.data!;
|
||||
return Text(
|
||||
"${balanceCache[address]!.toString()} $currencyName",
|
||||
style: TextStyle(
|
||||
fontSize: isTall ? size : size * 0.9,
|
||||
color: _color,
|
||||
),
|
||||
);
|
||||
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]) {
|
||||
[Color color = Colors.black]) {
|
||||
return Column(children: <Widget>[
|
||||
Consumer<SubstrateSdk>(builder: (context, _sdk, _) {
|
||||
Consumer<SubstrateSdk>(builder: (context, sdk, _) {
|
||||
return FutureBuilder(
|
||||
future: _sdk.getCerts(address),
|
||||
builder: (BuildContext context, AsyncSnapshot<List<int>> _certs) {
|
||||
future: sdk.getCerts(address),
|
||||
builder: (BuildContext context, AsyncSnapshot<List<int>> certs) {
|
||||
// log.d(_certs.data);
|
||||
|
||||
return _certs.data?[0] != 0
|
||||
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',
|
||||
Text(certs.data?[0].toString() ?? '0',
|
||||
style: const TextStyle(fontSize: 20)),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
"(${_certs.data?[1].toString() ?? '0'})",
|
||||
"(${certs.data?[1].toString() ?? '0'})",
|
||||
style: const TextStyle(fontSize: 14),
|
||||
)
|
||||
],
|
||||
|
@ -383,3 +608,32 @@ Widget getCerts(BuildContext context, String address, double size,
|
|||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -1,32 +1,33 @@
|
|||
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:graphql_flutter/graphql_flutter.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 'dart:math';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class WalletsProfilesProvider with ChangeNotifier {
|
||||
WalletsProfilesProvider(this.address);
|
||||
|
||||
String? address = '';
|
||||
String address = '';
|
||||
String pubkeyShort = '';
|
||||
List? transBC;
|
||||
String? fetchMoreCursor;
|
||||
Map? pageInfo;
|
||||
|
||||
bool isHistoryScreen = false;
|
||||
String historySwitchButtun = "Voir l'historique";
|
||||
String? rawSvg;
|
||||
TextEditingController payAmount = TextEditingController();
|
||||
TextEditingController payComment = TextEditingController();
|
||||
num? balance;
|
||||
int nRepositories = 20;
|
||||
int nPage = 1;
|
||||
num? _balance;
|
||||
|
||||
Future<String> scan(context) async {
|
||||
if (Platform.isAndroid || Platform.isIOS) {
|
||||
|
@ -43,7 +44,7 @@ class WalletsProfilesProvider with ChangeNotifier {
|
|||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return WalletViewScreen(pubkey: barcode!.rawContent);
|
||||
return WalletViewScreen(address: barcode!.rawContent);
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
|
@ -97,119 +98,12 @@ class WalletsProfilesProvider with ChangeNotifier {
|
|||
// Matograine portefeuille: 9p5nHsES6xujFR7pw2yGy4PLKKHgWsMvsDHaHF64Uj25.
|
||||
// Lion simone: 78jhpprYkMNF6i5kQPXfkAVBpd2aqcpieNsXTSW4c21f
|
||||
|
||||
List parseHistory(txs, _pubkey) {
|
||||
var transBC = [];
|
||||
int i = 0;
|
||||
|
||||
const currentBase = 0;
|
||||
double currentUD = 10.54;
|
||||
|
||||
for (final trans in txs) {
|
||||
var direction = trans['direction'];
|
||||
final transaction = trans['node'];
|
||||
String? output;
|
||||
if (direction == "RECEIVED") {
|
||||
for (String line in transaction['outputs']) {
|
||||
if (line.contains(_pubkey)) {
|
||||
output = line;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
output = transaction['outputs'][0];
|
||||
}
|
||||
if (output == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
transBC.add(i);
|
||||
transBC[i] = [];
|
||||
final dateBrut = DateTime.fromMillisecondsSinceEpoch(
|
||||
transaction['writtenTime'] * 1000);
|
||||
final DateFormat formatter = DateFormat('dd-MM-yy\nHH:mm');
|
||||
final date = formatter.format(dateBrut);
|
||||
transBC[i].add(transaction['writtenTime']);
|
||||
transBC[i].add(date);
|
||||
final int amountBrut = int.parse(output.split(':')[0]);
|
||||
final base = int.parse(output.split(':')[1]);
|
||||
final int applyBase = base - currentBase;
|
||||
final num amount =
|
||||
removeDecimalZero(amountBrut * pow(10, applyBase) / 100);
|
||||
num amountUD = amount / currentUD;
|
||||
if (direction == "RECEIVED") {
|
||||
transBC[i].add(transaction['issuers'][0]);
|
||||
transBC[i].add(getShortPubkey(transaction['issuers'][0]));
|
||||
transBC[i].add(amount.toString());
|
||||
transBC[i].add(amountUD.toStringAsFixed(2));
|
||||
} else if (direction == "SENT") {
|
||||
final outPubkey = output.split("SIG(")[1].replaceAll(')', '');
|
||||
transBC[i].add(outPubkey);
|
||||
transBC[i].add(getShortPubkey(outPubkey));
|
||||
transBC[i].add('- ' + amount.toString());
|
||||
transBC[i].add(amountUD.toStringAsFixed(2));
|
||||
}
|
||||
transBC[i].add(transaction['comment']);
|
||||
|
||||
i++;
|
||||
}
|
||||
return transBC;
|
||||
}
|
||||
|
||||
FetchMoreOptions? checkQueryResult(result, opts, _pubkey) {
|
||||
final List<dynamic>? blockchainTX =
|
||||
(result.data['txsHistoryBc']['both']['edges'] as List<dynamic>?);
|
||||
// final List<dynamic> mempoolTX =
|
||||
// (result.data['txsHistoryMp']['receiving'] as List<dynamic>);
|
||||
|
||||
pageInfo = result.data['txsHistoryBc']['both']['pageInfo'];
|
||||
fetchMoreCursor = pageInfo!['endCursor'];
|
||||
if (fetchMoreCursor == null) nPage = 1;
|
||||
|
||||
if (nPage == 1) {
|
||||
nRepositories = 40;
|
||||
} else if (nPage == 2) {
|
||||
nRepositories = 100;
|
||||
}
|
||||
nPage++;
|
||||
|
||||
if (fetchMoreCursor != null) {
|
||||
opts = FetchMoreOptions(
|
||||
variables: {'cursor': fetchMoreCursor, 'number': nRepositories},
|
||||
updateQuery: (previousResultData, fetchMoreResultData) {
|
||||
final List<dynamic> repos = [
|
||||
...previousResultData!['txsHistoryBc']['both']['edges']
|
||||
as List<dynamic>,
|
||||
...fetchMoreResultData!['txsHistoryBc']['both']['edges']
|
||||
as List<dynamic>
|
||||
];
|
||||
|
||||
fetchMoreResultData['txsHistoryBc']['both']['edges'] = repos;
|
||||
return fetchMoreResultData;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
log.d(
|
||||
"###### DEBUG H Parse blockchainTX list. Cursor: $fetchMoreCursor ######");
|
||||
if (fetchMoreCursor != null) {
|
||||
transBC = parseHistory(blockchainTX, _pubkey);
|
||||
} else {
|
||||
log.i("###### DEBUG H - Début de l'historique");
|
||||
}
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
void resetdHistory() {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
num removeDecimalZero(double n) {
|
||||
String result = n.toStringAsFixed(n.truncateToDouble() == n ? 0 : 2);
|
||||
return num.parse(result);
|
||||
}
|
||||
|
||||
String generateIdenticon(String _pubkey) {
|
||||
return Jdenticon.toSvg(_pubkey);
|
||||
String generateIdenticon(String pubkey) {
|
||||
return Jdenticon.toSvg(pubkey);
|
||||
}
|
||||
|
||||
// Future<num> getBalance(String _pubkey) async {
|
||||
|
@ -227,12 +121,122 @@ class WalletsProfilesProvider with ChangeNotifier {
|
|||
// return balance;
|
||||
// }
|
||||
|
||||
Future<num?> getBalance(String? _pubkey) async {
|
||||
while (balance == null) {
|
||||
Future<num?> getBalance(String? pubkey) async {
|
||||
while (_balance == null) {
|
||||
await Future.delayed(const Duration(milliseconds: 50));
|
||||
}
|
||||
|
||||
return balance;
|
||||
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);
|
||||
}
|
||||
|
||||
Future addContact(G1WalletsList profile) async {
|
||||
// log.d(profile.username);
|
||||
if (isContact(profile.address)) {
|
||||
await contactsBox.delete(profile.address);
|
||||
} else {
|
||||
await contactsBox.put(profile.address, profile);
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void reload() {
|
||||
|
@ -241,10 +245,10 @@ class WalletsProfilesProvider with ChangeNotifier {
|
|||
}
|
||||
|
||||
snackCopyKey(context) {
|
||||
const snackBar = SnackBar(
|
||||
padding: EdgeInsets.all(20),
|
||||
content: Text("Cette adresse a été copié dans votre presse-papier.",
|
||||
style: TextStyle(fontSize: 16)),
|
||||
duration: Duration(seconds: 2));
|
||||
final snackBar = SnackBar(
|
||||
padding: const EdgeInsets.all(20),
|
||||
content: Text("thisAddressHasBeenCopiedToClipboard".tr(),
|
||||
style: const TextStyle(fontSize: 16)),
|
||||
duration: const Duration(seconds: 2));
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,365 @@
|
|||
// 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';
|
||||
|
||||
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,
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text('accountActivity'.tr()),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: homeProvider.bottomAppBar(context),
|
||||
body: Column(children: <Widget>[
|
||||
walletProfile.headerProfileView(context, address, username),
|
||||
historyQuery(context),
|
||||
]));
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
|
@ -29,10 +29,10 @@ class AnimatedFadeOutIn<T> extends StatefulWidget {
|
|||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AnimatedFadeOutInState<T> createState() => _AnimatedFadeOutInState<T>();
|
||||
AnimatedFadeOutInState<T> createState() => AnimatedFadeOutInState<T>();
|
||||
}
|
||||
|
||||
class _AnimatedFadeOutInState<T> extends State<AnimatedFadeOutIn<T>>
|
||||
class AnimatedFadeOutInState<T> extends State<AnimatedFadeOutIn<T>>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController controller;
|
||||
late Animation<double> animation;
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:gecko/globals.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
// import 'package:gecko/models/home.dart';
|
||||
// import 'package:provider/provider.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class AvatarFullscreen extends StatelessWidget {
|
||||
TextEditingController tplController = TextEditingController();
|
||||
|
||||
AvatarFullscreen(this.avatar, {this.title, this.color, Key? key})
|
||||
: super(key: key);
|
||||
final Image? avatar;
|
||||
final String? title;
|
||||
final Color? color;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
// HomeProvider _homeProvider = Provider.of<HomeProvider>(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
backgroundColor: color ?? Colors.black,
|
||||
toolbarHeight: 60 * ratio,
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back, color: orangeC),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text(
|
||||
title ?? 'Photo de profil',
|
||||
style: TextStyle(color: orangeC),
|
||||
),
|
||||
)),
|
||||
body: SafeArea(
|
||||
child: SizedBox.expand(
|
||||
child: Container(
|
||||
color: color ?? Colors.black,
|
||||
// alignment: Alignment.center,
|
||||
// height: MediaQuery.of(context).size.height,
|
||||
// width: MediaQuery.of(context).size.width,
|
||||
child: Image(
|
||||
image: avatar!.image,
|
||||
height: avatar!.height,
|
||||
fit: BoxFit.fitWidth),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,11 @@
|
|||
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
|
||||
|
@ -27,22 +32,28 @@ class CommonElements {
|
|||
child: Image.asset('assets/onBoarding/$assetName', width: imageWidth));
|
||||
}
|
||||
|
||||
Widget buildText(List<TextSpan> text, [double size = 20]) {
|
||||
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: RichText(
|
||||
textAlign: TextAlign.justify,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: isTall ? size : size * 0.9,
|
||||
color: Colors.black,
|
||||
letterSpacing: 0.3),
|
||||
children: text,
|
||||
),
|
||||
),
|
||||
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)),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -52,10 +63,10 @@ class CommonElements {
|
|||
width: 380 * ratio,
|
||||
height: 60 * ratio,
|
||||
child: ElevatedButton(
|
||||
key: keyGoNext,
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 4,
|
||||
primary: orangeC, // background
|
||||
onPrimary: Colors.white, // foreground
|
||||
foregroundColor: Colors.white, backgroundColor: orangeC,
|
||||
elevation: 4, // foreground
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
|
@ -83,11 +94,12 @@ class CommonElements {
|
|||
|
||||
Widget infoIntro(
|
||||
BuildContext context,
|
||||
List<TextSpan> text,
|
||||
String text,
|
||||
String assetName,
|
||||
String buttonText,
|
||||
nextScreen,
|
||||
double pagePosition, {
|
||||
bool isMd = false,
|
||||
bool isFast = false,
|
||||
double boxHeight = 440,
|
||||
double imageWidth = 350,
|
||||
|
@ -98,7 +110,8 @@ class CommonElements {
|
|||
buildProgressBar(pagePosition),
|
||||
SizedBox(height: isTall ? 40 : 20),
|
||||
|
||||
buildText(text, textSize),
|
||||
buildText(text, textSize, isMd),
|
||||
|
||||
buildImage(assetName, boxHeight, imageWidth),
|
||||
Expanded(
|
||||
child: Align(
|
||||
|
@ -119,6 +132,17 @@ class CommonElements {
|
|||
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
|
||||
|
@ -132,24 +156,39 @@ class CommonElements {
|
|||
}),
|
||||
),
|
||||
),
|
||||
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)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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({this.page})
|
||||
final Widget page;
|
||||
SmoothTransition({required this.page})
|
||||
: super(
|
||||
pageBuilder: (
|
||||
BuildContext context,
|
||||
|
@ -160,7 +199,7 @@ class SmoothTransition extends PageRouteBuilder {
|
|||
duration: const Duration(seconds: 5),
|
||||
tween: Tween(begin: 200, end: 200),
|
||||
builder: (BuildContext context, dynamic value, Widget? child) {
|
||||
return page!;
|
||||
return page;
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -209,10 +248,10 @@ Future<bool?> confirmPopup(BuildContext context, String title) async {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
TextButton(
|
||||
key: const Key('confirmPopop'),
|
||||
child: const Text(
|
||||
"Oui",
|
||||
style: TextStyle(
|
||||
key: keyConfirm,
|
||||
child: Text(
|
||||
"yes".tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 21,
|
||||
color: Color(0xffD80000),
|
||||
),
|
||||
|
@ -223,9 +262,9 @@ Future<bool?> confirmPopup(BuildContext context, String title) async {
|
|||
),
|
||||
const SizedBox(width: 20),
|
||||
TextButton(
|
||||
child: const Text(
|
||||
"Non",
|
||||
style: TextStyle(fontSize: 21),
|
||||
child: Text(
|
||||
"no".tr(),
|
||||
style: const TextStyle(fontSize: 21),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, false);
|
||||
|
@ -257,7 +296,7 @@ Future<void> infoPopup(BuildContext context, String title) async {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
TextButton(
|
||||
key: const Key('infoPopup'),
|
||||
key: keyInfoPopup,
|
||||
child: const Text(
|
||||
"D'accord",
|
||||
style: TextStyle(
|
||||
|
|
|
@ -1,552 +0,0 @@
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:gecko/globals.dart';
|
||||
import 'package:gecko/providers/cesium_plus.dart';
|
||||
import 'package:gecko/providers/substrate_sdk.dart';
|
||||
import 'package:gecko/providers/wallets_profiles.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gecko/screens/avatar_fullscreen.dart';
|
||||
import 'package:gecko/screens/wallet_view.dart';
|
||||
import 'package:graphql_flutter/graphql_flutter.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class HistoryScreen extends StatelessWidget with ChangeNotifier {
|
||||
HistoryScreen({required this.pubkey, this.avatar, this.username, Key? key})
|
||||
: super(key: key);
|
||||
final ScrollController scrollController = ScrollController();
|
||||
final double avatarsSize = 80;
|
||||
final String? pubkey;
|
||||
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 _historyProvider =
|
||||
Provider.of<WalletsProfilesProvider>(context, listen: false);
|
||||
CesiumPlusProvider _cesiumPlusProvider =
|
||||
Provider.of<CesiumPlusProvider>(context, listen: false);
|
||||
log.i('Build pubkey : ' + pubkey!);
|
||||
// WidgetsBinding.instance.addPostFrameCallback((_) {});
|
||||
|
||||
_historyProvider.balance = _historyProvider.transBC = null;
|
||||
|
||||
return Scaffold(
|
||||
key: _scaffoldKey,
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
height: 22,
|
||||
child: Text('Historique des transactions'),
|
||||
),
|
||||
),
|
||||
body: Column(children: <Widget>[
|
||||
headerProfileView(context, _historyProvider, _cesiumPlusProvider),
|
||||
historyQuery(context, _cesiumPlusProvider),
|
||||
]));
|
||||
}
|
||||
|
||||
Widget historyQuery(context, CesiumPlusProvider _cesiumPlusProvider) {
|
||||
WalletsProfilesProvider _historyProvider =
|
||||
Provider.of<WalletsProfilesProvider>(context, listen: true);
|
||||
|
||||
return Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: <Widget>[
|
||||
Query(
|
||||
options: QueryOptions(
|
||||
document: gql('getHistory'),
|
||||
variables: <String, dynamic>{
|
||||
'pubkey': pubkey,
|
||||
'number': 10,
|
||||
'cursor': null
|
||||
},
|
||||
),
|
||||
builder: (QueryResult result, {fetchMore, refetch}) {
|
||||
if (result.isLoading && result.data == null) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
|
||||
if (result.hasException) {
|
||||
log.e('Error GVA: ' + result.exception.toString());
|
||||
return Column(children: const <Widget>[
|
||||
SizedBox(height: 50),
|
||||
Text(
|
||||
"Aucun noeud GVA valide n'a pu être trouvé.\nVeuillez réessayer ultérieurement.",
|
||||
style: TextStyle(fontSize: 18),
|
||||
)
|
||||
]);
|
||||
} else if (result.data == null) {
|
||||
return Column(children: const <Widget>[
|
||||
SizedBox(height: 50),
|
||||
Text(
|
||||
"Aucune donnée à afficher.",
|
||||
style: TextStyle(fontSize: 18),
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
if (result.data!['balance'] == null) {
|
||||
_historyProvider.balance = 0.0;
|
||||
} else {
|
||||
_historyProvider.balance = _historyProvider
|
||||
.removeDecimalZero(result.data!['balance']['amount'] / 100);
|
||||
}
|
||||
|
||||
if (result.isNotLoading) {
|
||||
// log.d(result.data);
|
||||
opts = _historyProvider.checkQueryResult(result, opts, pubkey);
|
||||
}
|
||||
|
||||
// Build history list
|
||||
return NotificationListener(
|
||||
child: Builder(
|
||||
builder: (context) => Expanded(
|
||||
child: ListView(
|
||||
key: const Key('listTransactions'),
|
||||
controller: scrollController,
|
||||
children: <Widget>[historyView(context, result)],
|
||||
),
|
||||
),
|
||||
),
|
||||
onNotification: (dynamic t) {
|
||||
if (t is ScrollEndNotification &&
|
||||
scrollController.position.pixels >=
|
||||
scrollController.position.maxScrollExtent * 0.7 &&
|
||||
_historyProvider.pageInfo!['hasPreviousPage'] &&
|
||||
result.isNotLoading) {
|
||||
fetchMore!(opts!);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
Widget historyView(context, result) {
|
||||
WalletsProfilesProvider _historyProvider =
|
||||
Provider.of<WalletsProfilesProvider>(context, listen: false);
|
||||
|
||||
return _historyProvider.transBC == null
|
||||
? Column(children: const <Widget>[
|
||||
SizedBox(height: 50),
|
||||
Text(
|
||||
"Aucune transaction à afficher.",
|
||||
style: TextStyle(fontSize: 18),
|
||||
)
|
||||
])
|
||||
: Column(children: <Widget>[
|
||||
getTransactionTile(context, _historyProvider),
|
||||
if (result.isLoading &&
|
||||
_historyProvider.pageInfo!['hasPreviousPage'])
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: const <Widget>[
|
||||
CircularProgressIndicator(),
|
||||
],
|
||||
),
|
||||
if (!_historyProvider.pageInfo!['hasPreviousPage'])
|
||||
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, WalletsProfilesProvider _historyProvider) {
|
||||
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;
|
||||
|
||||
const Map<int, String> monthsInYear = {
|
||||
1: "Janvier",
|
||||
2: "Février",
|
||||
3: "Mars",
|
||||
4: "Avril",
|
||||
5: "Mai",
|
||||
6: "Juin",
|
||||
7: "Juillet",
|
||||
8: "Aout",
|
||||
9: "Septembre",
|
||||
10: "Octobre",
|
||||
11: "Novembre",
|
||||
12: "Décembre"
|
||||
};
|
||||
|
||||
return Column(
|
||||
children: _historyProvider.transBC!.map((repository) {
|
||||
DateTime now = DateTime.now();
|
||||
DateTime date = DateTime.fromMillisecondsSinceEpoch(repository[0] * 1000);
|
||||
|
||||
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 = "Aujourd'hui";
|
||||
isTody = true;
|
||||
} else if (transactionDate == yesterdayDate && !isYesterday) {
|
||||
dateDelimiter = lastDateDelimiter = "Hier";
|
||||
isYesterday = true;
|
||||
} else if (weekNumber(date) == weekNumber(now) &&
|
||||
date.year == now.year &&
|
||||
lastDateDelimiter != "Cette semaine" &&
|
||||
transactionDate != yesterdayDate &&
|
||||
transactionDate != todayDate &&
|
||||
!isThisWeek) {
|
||||
dateDelimiter = lastDateDelimiter = "Cette semaine";
|
||||
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;
|
||||
}
|
||||
|
||||
return Column(children: <Widget>[
|
||||
if (dateDelimiter != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 30),
|
||||
child: Text(
|
||||
dateDelimiter!,
|
||||
style: TextStyle(
|
||||
fontSize: 23, color: orangeC, fontWeight: FontWeight.w300),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 0),
|
||||
child:
|
||||
// Row(children: [Column(children: [],)],)
|
||||
ListTile(
|
||||
key: Key('transaction${keyID++}'),
|
||||
contentPadding: const EdgeInsets.only(
|
||||
left: 20, right: 30, top: 15, bottom: 15),
|
||||
leading: g1WalletsBox.get(repository[2])?.avatar == null
|
||||
? FutureBuilder(
|
||||
future: _cesiumPlusProvider.getAvatar(
|
||||
repository[2], _avatarSize),
|
||||
builder: (BuildContext context,
|
||||
AsyncSnapshot<Image?> _avatar) {
|
||||
if (_avatar.connectionState !=
|
||||
ConnectionState.done ||
|
||||
_avatar.hasError) {
|
||||
return Stack(children: [
|
||||
_cesiumPlusProvider.defaultAvatar(_avatarSize),
|
||||
Positioned(
|
||||
top: 8,
|
||||
right: 0,
|
||||
width: 12,
|
||||
height: 12,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 1,
|
||||
color: orangeC,
|
||||
),
|
||||
),
|
||||
]);
|
||||
}
|
||||
if (_avatar.hasData) {
|
||||
g1WalletsBox.get(repository[2])?.avatar =
|
||||
_avatar.data;
|
||||
return ClipOval(child: _avatar.data);
|
||||
} else {
|
||||
g1WalletsBox.get(repository[2])?.avatar =
|
||||
_cesiumPlusProvider
|
||||
.defaultAvatar(repository[2]);
|
||||
return _cesiumPlusProvider
|
||||
.defaultAvatar(_avatarSize);
|
||||
}
|
||||
})
|
||||
: ClipOval(
|
||||
child: Image(
|
||||
image:
|
||||
g1WalletsBox.get(repository[2])!.avatar!.image,
|
||||
height: _avatarSize,
|
||||
),
|
||||
),
|
||||
title: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: 5, top: repository[6] != '' ? 0 : 0),
|
||||
child: Text(repository[3],
|
||||
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[6] != '')
|
||||
TextSpan(
|
||||
text: ' · ',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: Colors.grey[550],
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: repository[6],
|
||||
style: TextStyle(
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
trailing: Text("${repository[4]} $currencyName",
|
||||
style: const TextStyle(
|
||||
fontSize: 18, fontWeight: FontWeight.w500),
|
||||
textAlign: TextAlign.justify),
|
||||
dense: false,
|
||||
isThreeLine: false,
|
||||
onTap: () {
|
||||
_historyProvider.nPage = 1;
|
||||
// _cesiumPlusProvider.avatarCancelToken.cancel('cancelled');
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return WalletViewScreen(pubkey: repository[2]);
|
||||
}),
|
||||
);
|
||||
// Navigator.pop(context);
|
||||
}),
|
||||
),
|
||||
]);
|
||||
}).toList());
|
||||
}
|
||||
|
||||
Widget headerProfileView(
|
||||
BuildContext context,
|
||||
WalletsProfilesProvider _historyProvider,
|
||||
CesiumPlusProvider _cesiumPlusProvider) {
|
||||
const double _avatarSize = 140;
|
||||
|
||||
return Column(children: <Widget>[
|
||||
Container(
|
||||
height: 10,
|
||||
color: yellowC,
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
yellowC,
|
||||
const Color(0xFFE7811A),
|
||||
],
|
||||
)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 30, right: 40),
|
||||
child: Row(children: <Widget>[
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Row(children: [
|
||||
GestureDetector(
|
||||
key: const Key('copyPubkey'),
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: pubkey));
|
||||
snackCopyKey(context);
|
||||
},
|
||||
child: Text(
|
||||
getShortPubkey(pubkey!),
|
||||
style: const TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
const SizedBox(height: 10),
|
||||
if (username == null)
|
||||
Query(
|
||||
options: QueryOptions(
|
||||
document: gql('getId'),
|
||||
variables: {
|
||||
'pubkey': pubkey,
|
||||
},
|
||||
),
|
||||
builder: (QueryResult result,
|
||||
{VoidCallback? refetch, FetchMore? fetchMore}) {
|
||||
if (result.isLoading || result.hasException) {
|
||||
return const Text('...');
|
||||
} else if (result.data!['idty'] == null ||
|
||||
result.data!['idty']['username'] == null) {
|
||||
return const Text('');
|
||||
} else {
|
||||
return SizedBox(
|
||||
width: 230,
|
||||
child: Text(
|
||||
result.data!['idty']['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: 25),
|
||||
]),
|
||||
FutureBuilder(
|
||||
future: _historyProvider.getBalance(pubkey),
|
||||
builder:
|
||||
(BuildContext context, AsyncSnapshot<num?> _balance) {
|
||||
if (_balance.connectionState != ConnectionState.done ||
|
||||
_balance.hasError) {
|
||||
return const Text('...');
|
||||
}
|
||||
return Text(
|
||||
"${_balance.data.toString()} $currencyName",
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontSize: 22, fontWeight: FontWeight.w500),
|
||||
);
|
||||
}),
|
||||
const SizedBox(height: 30),
|
||||
]),
|
||||
const Spacer(),
|
||||
Column(children: <Widget>[
|
||||
if (avatar == null)
|
||||
FutureBuilder(
|
||||
future: _cesiumPlusProvider.getAvatar(pubkey, _avatarSize),
|
||||
builder:
|
||||
(BuildContext context, AsyncSnapshot<Image?> _avatar) {
|
||||
if (_avatar.connectionState != ConnectionState.done) {
|
||||
return Stack(children: [
|
||||
ClipOval(
|
||||
child:
|
||||
_cesiumPlusProvider.defaultAvatar(_avatarSize),
|
||||
),
|
||||
Positioned(
|
||||
top: 15,
|
||||
right: 45,
|
||||
width: 51,
|
||||
height: 51,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 5,
|
||||
color: orangeC,
|
||||
),
|
||||
),
|
||||
]);
|
||||
}
|
||||
if (_avatar.hasData) {
|
||||
return GestureDetector(
|
||||
key: const Key('openAvatar'),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return AvatarFullscreen(_avatar.data);
|
||||
}),
|
||||
);
|
||||
},
|
||||
child: ClipOval(
|
||||
child: Image(
|
||||
image: _avatar.data!.image,
|
||||
height: _avatarSize,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return ClipOval(
|
||||
child: _cesiumPlusProvider.defaultAvatar(_avatarSize),
|
||||
);
|
||||
}),
|
||||
if (avatar != null)
|
||||
GestureDetector(
|
||||
key: const Key('openAvatar'),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return AvatarFullscreen(avatar);
|
||||
}),
|
||||
);
|
||||
},
|
||||
child: ClipOval(
|
||||
child: Image(
|
||||
image: avatar!.image,
|
||||
height: _avatarSize,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
]),
|
||||
]),
|
||||
),
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,13 @@
|
|||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'package:bubble/bubble.dart';
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:gecko/globals.dart';
|
||||
import 'package:gecko/models/stateful_wrapper.dart';
|
||||
import 'package:gecko/models/widgets_keys.dart';
|
||||
import 'package:gecko/providers/chest_provider.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';
|
||||
|
@ -17,22 +23,22 @@ 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:gecko/screens/substrate_sandbox.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:gecko/screens/my_contacts.dart';
|
||||
|
||||
class HomeScreen extends StatelessWidget {
|
||||
const HomeScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
homeContext = context;
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context);
|
||||
Provider.of<ChestProvider>(context);
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
final bool isWalletsExists = _myWalletProvider.checkIfWalletExist();
|
||||
final bool isWalletsExists = myWalletProvider.checkIfWalletExist();
|
||||
|
||||
isTall = false;
|
||||
ratio = 1;
|
||||
|
@ -48,19 +54,19 @@ class HomeScreen extends StatelessWidget {
|
|||
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),
|
||||
]),
|
||||
decoration: BoxDecoration(
|
||||
color: orangeC,
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
key: const Key('parameters'),
|
||||
title: const Text('Paramètres'),
|
||||
key: keyParameters,
|
||||
title: Text('parameters'.tr()),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
Navigator.push(
|
||||
|
@ -72,24 +78,18 @@ class HomeScreen extends StatelessWidget {
|
|||
},
|
||||
),
|
||||
ListTile(
|
||||
key: const Key('substrateSandbox'),
|
||||
title: const Text('Substrate debug'),
|
||||
key: keyContacts,
|
||||
title: Text('contactsManagement'.tr()),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return const SubstrateSandBox();
|
||||
return const ContactsScreen();
|
||||
}),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
// ListTile(
|
||||
// title: const Text('A propos'),
|
||||
// onTap: () {
|
||||
// },
|
||||
// ),
|
||||
])),
|
||||
Align(
|
||||
alignment: FractionalOffset.bottomCenter,
|
||||
|
@ -104,22 +104,54 @@ class HomeScreen extends StatelessWidget {
|
|||
builder: (ctx) => StatefulWrapper(
|
||||
onInit: () {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
if (!_sub.sdkReady && !_sub.sdkLoading) await _sub.initApi();
|
||||
if (_sub.sdkReady && !_sub.nodeConnected) {
|
||||
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,
|
||||
"La version de vos coffres n'est plus comptabile avec cette version de Ğecko.\nTous vos coffres vont être oubliés, vous devez les importer de nouveau.");
|
||||
await infoPopup(
|
||||
context, "chestNotCompatibleMustReinstallGecko".tr());
|
||||
await walletBox.clear();
|
||||
await chestBox.clear();
|
||||
await configBox.delete('defaultWallet');
|
||||
await _sub.deleteAllAccounts();
|
||||
_myWalletProvider.rebuildWidget();
|
||||
await sub.deleteAllAccounts();
|
||||
myWalletProvider.reload();
|
||||
}
|
||||
|
||||
await _sub.connectNode(ctx); //kopa
|
||||
// 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)
|
||||
|
@ -151,10 +183,10 @@ class HomeScreen extends StatelessWidget {
|
|||
}
|
||||
|
||||
Widget geckHome(context) {
|
||||
MyWalletsProvider _myWalletProvider = Provider.of<MyWalletsProvider>(context);
|
||||
MyWalletsProvider myWalletProvider = Provider.of<MyWalletsProvider>(context);
|
||||
Provider.of<ChestProvider>(context);
|
||||
|
||||
WalletsProfilesProvider _historyProvider =
|
||||
WalletsProfilesProvider historyProvider =
|
||||
Provider.of<WalletsProfilesProvider>(context);
|
||||
final double statusBarHeight = MediaQuery.of(context).padding.top;
|
||||
return Container(
|
||||
|
@ -172,7 +204,7 @@ Widget geckHome(context) {
|
|||
left: 15,
|
||||
child: Builder(
|
||||
builder: (context) => IconButton(
|
||||
key: const Key('drawerMenu'),
|
||||
key: keyDrawerMenu,
|
||||
icon: const Icon(
|
||||
Icons.menu,
|
||||
color: Colors.white,
|
||||
|
@ -210,9 +242,9 @@ Widget geckHome(context) {
|
|||
),
|
||||
],
|
||||
),
|
||||
child: Consumer<HomeProvider>(builder: (context, _homeP, _) {
|
||||
child: Consumer<HomeProvider>(builder: (context, homeP, _) {
|
||||
return AnimatedFadeOutIn<String>(
|
||||
data: _homeP.homeMessage,
|
||||
data: homeP.homeMessage,
|
||||
duration: const Duration(milliseconds: 100),
|
||||
builder: (value) => Text(value),
|
||||
);
|
||||
|
@ -239,10 +271,21 @@ Widget geckHome(context) {
|
|||
Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
|
||||
Column(children: <Widget>[
|
||||
Container(
|
||||
decoration: const BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.black,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
blurRadius: 2,
|
||||
offset: Offset(1, 1.5),
|
||||
spreadRadius: 0.5)
|
||||
],
|
||||
),
|
||||
child: ClipOval(
|
||||
child: Material(
|
||||
color: orangeC, // button color
|
||||
child: InkWell(
|
||||
key: keyOpenSearch,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(18),
|
||||
child: Image(
|
||||
|
@ -260,20 +303,10 @@ Widget geckHome(context) {
|
|||
}),
|
||||
),
|
||||
),
|
||||
decoration: const BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.black,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
blurRadius: 2,
|
||||
offset: Offset(1, 1.5),
|
||||
spreadRadius: 0.5)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
"Rechercher un\nportefeuille",
|
||||
"searchWallet".tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
|
@ -284,8 +317,18 @@ Widget geckHome(context) {
|
|||
const SizedBox(width: 120),
|
||||
Column(children: <Widget>[
|
||||
Container(
|
||||
decoration: const BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.black,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
blurRadius: 2,
|
||||
offset: Offset(1, 1.5),
|
||||
spreadRadius: 0.5)
|
||||
],
|
||||
),
|
||||
child: ClipOval(
|
||||
key: const Key('manageWallets'),
|
||||
key: keyOpenWalletsHomme,
|
||||
child: Material(
|
||||
color: orangeC, // button color
|
||||
child: InkWell(
|
||||
|
@ -297,10 +340,10 @@ Widget geckHome(context) {
|
|||
height: 68 * ratio)),
|
||||
onTap: () async {
|
||||
WalletData? defaultWallet =
|
||||
_myWalletProvider.getDefaultWallet();
|
||||
String? _pin;
|
||||
if (_myWalletProvider.pinCode == '') {
|
||||
_pin = await Navigator.push(
|
||||
myWalletProvider.getDefaultWallet();
|
||||
String? pin;
|
||||
if (myWalletProvider.pinCode == '') {
|
||||
pin = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (homeContext) {
|
||||
|
@ -310,8 +353,7 @@ Widget geckHome(context) {
|
|||
),
|
||||
);
|
||||
}
|
||||
if (_pin != null ||
|
||||
_myWalletProvider.pinCode != '') {
|
||||
if (pin != null || myWalletProvider.pinCode != '') {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
|
@ -326,20 +368,10 @@ Widget geckHome(context) {
|
|||
}),
|
||||
),
|
||||
),
|
||||
decoration: const BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.black,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
blurRadius: 2,
|
||||
offset: Offset(1, 1.5),
|
||||
spreadRadius: 0.5)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
"Gérer mes\nportefeuilles",
|
||||
"manageWallets".tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
|
@ -355,6 +387,16 @@ Widget geckHome(context) {
|
|||
children: <Widget>[
|
||||
Column(children: <Widget>[
|
||||
Container(
|
||||
decoration: const BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.black,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
blurRadius: 2,
|
||||
offset: Offset(1, 1.5),
|
||||
spreadRadius: 0.5)
|
||||
],
|
||||
),
|
||||
child: ClipOval(
|
||||
child: Material(
|
||||
color: orangeC, // button color
|
||||
|
@ -366,24 +408,14 @@ Widget geckHome(context) {
|
|||
'assets/home/qrcode.png'),
|
||||
height: 68 * ratio)),
|
||||
onTap: () async {
|
||||
await _historyProvider.scan(context);
|
||||
await historyProvider.scan(context);
|
||||
}),
|
||||
),
|
||||
),
|
||||
decoration: const BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.black,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
blurRadius: 2,
|
||||
offset: Offset(1, 1.5),
|
||||
spreadRadius: 0.5)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
"Scanner un\nQR code",
|
||||
"scanQRCode".tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
|
@ -419,7 +451,7 @@ Widget welcomeHome(context) {
|
|||
left: 15,
|
||||
child: Builder(
|
||||
builder: (context) => IconButton(
|
||||
key: const Key('drawerMenu'),
|
||||
key: keyDrawerMenu,
|
||||
icon: const Icon(
|
||||
Icons.menu,
|
||||
color: Colors.white,
|
||||
|
@ -439,7 +471,7 @@ Widget welcomeHome(context) {
|
|||
child:
|
||||
Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
|
||||
Text(
|
||||
"L’application de paiement $currencyName\nplus rapide qu’un reptile du Vietnam",
|
||||
"fastAppDescription".tr(args: [currencyName]),
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
|
@ -491,7 +523,7 @@ Widget welcomeHome(context) {
|
|||
),
|
||||
Positioned(
|
||||
left: 180,
|
||||
child: bubbleSpeak("y'a pas de lézard !"),
|
||||
child: bubbleSpeak("noLizard".tr()),
|
||||
),
|
||||
const Positioned(
|
||||
left: 200,
|
||||
|
@ -507,10 +539,10 @@ Widget welcomeHome(context) {
|
|||
width: 410,
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
key: keyOnboardingNewChest,
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 4,
|
||||
primary: orangeC, // background
|
||||
onPrimary: Colors.white, // foreground
|
||||
foregroundColor: Colors.white, elevation: 4,
|
||||
backgroundColor: orangeC, // foreground
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
|
@ -522,10 +554,10 @@ Widget welcomeHome(context) {
|
|||
),
|
||||
);
|
||||
},
|
||||
child: const Text(
|
||||
'Créer un portefeuille',
|
||||
style:
|
||||
TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
|
||||
child: Text(
|
||||
'createWallet'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 24, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -534,8 +566,9 @@ Widget welcomeHome(context) {
|
|||
width: 410,
|
||||
height: 70,
|
||||
child: OutlinedButton(
|
||||
key: keyRestoreChest,
|
||||
style: OutlinedButton.styleFrom(
|
||||
side: BorderSide(width: 4, color: orangeC)),
|
||||
side: const BorderSide(width: 4, color: orangeC)),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
|
@ -547,8 +580,8 @@ Widget welcomeHome(context) {
|
|||
);
|
||||
},
|
||||
child: Text(
|
||||
"Restaurer mes portefeuilles",
|
||||
style: TextStyle(
|
||||
"restoreWallet".tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 24,
|
||||
color: orangeC,
|
||||
fontWeight: FontWeight.w600),
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// ignore_for_file: use_build_context_synchronously, must_be_immutable
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:durt/durt.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
@ -7,11 +10,9 @@ import 'package:gecko/models/wallet_data.dart';
|
|||
import 'package:gecko/providers/my_wallets.dart';
|
||||
import 'package:gecko/providers/substrate_sdk.dart';
|
||||
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class ChangePinScreen extends StatelessWidget with ChangeNotifier {
|
||||
ChangePinScreen(
|
||||
{Key? keyMyWallets,
|
||||
|
@ -20,15 +21,14 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
|
|||
: super(key: keyMyWallets);
|
||||
final String? walletName;
|
||||
final MyWalletsProvider walletProvider;
|
||||
Directory? appPath;
|
||||
|
||||
TextEditingController newPin = TextEditingController();
|
||||
final TextEditingController newPin = TextEditingController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
|
||||
return WillPopScope(
|
||||
|
@ -63,7 +63,7 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
|
|||
),
|
||||
const SizedBox(height: 80),
|
||||
Text(
|
||||
'Choisissez un code secret autogénéré :',
|
||||
'choosePassword'.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 17.0,
|
||||
|
@ -99,17 +99,16 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
|
|||
height: 50,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 12,
|
||||
primary: Colors.green[400], //smoothYellow, // background
|
||||
onPrimary: Colors.black, // foreground
|
||||
foregroundColor: Colors.black, elevation: 12,
|
||||
backgroundColor: Colors.green[400], // foreground
|
||||
),
|
||||
onPressed: () async {
|
||||
WalletData defaultWallet =
|
||||
_myWalletProvider.getDefaultWallet();
|
||||
myWalletProvider.getDefaultWallet();
|
||||
|
||||
String? _pin;
|
||||
if (_myWalletProvider.pinCode == '') {
|
||||
_pin = await Navigator.push(
|
||||
String? pin;
|
||||
if (myWalletProvider.pinCode == '') {
|
||||
pin = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (homeContext) {
|
||||
|
@ -118,17 +117,17 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
|
|||
),
|
||||
);
|
||||
}
|
||||
if (_pin != null || _myWalletProvider.pinCode != '') {
|
||||
await _sub.changePassword(context, defaultWallet.address!,
|
||||
if (pin != null || myWalletProvider.pinCode != '') {
|
||||
await sub.changePassword(context, defaultWallet.address!,
|
||||
walletProvider.pinCode, newPin.text);
|
||||
walletProvider.pinCode = newPin.text;
|
||||
newPin.text = '';
|
||||
Navigator.pop(context);
|
||||
}
|
||||
},
|
||||
child: const Text(
|
||||
'Confirmer',
|
||||
style: TextStyle(fontSize: 28),
|
||||
child: Text(
|
||||
'confirm'.tr(),
|
||||
style: const TextStyle(fontSize: 28),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
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';
|
||||
|
@ -20,9 +26,9 @@ class ChestOptions extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
ChestProvider _chestProvider =
|
||||
ChestProvider chestProvider =
|
||||
Provider.of<ChestProvider>(context, listen: false);
|
||||
HomeProvider _homeProvider =
|
||||
HomeProvider homeProvider =
|
||||
Provider.of<HomeProvider>(context, listen: false);
|
||||
|
||||
ChestData currentChest = chestBox.get(configBox.get('currentChest'))!;
|
||||
|
@ -46,21 +52,21 @@ class ChestOptions extends StatelessWidget {
|
|||
height: 22,
|
||||
child: Text(currentChest.name!),
|
||||
)),
|
||||
bottomNavigationBar: _homeProvider.bottomAppBar(context),
|
||||
body: Builder(
|
||||
builder: (ctx) => SafeArea(
|
||||
child: Column(children: <Widget>[
|
||||
SizedBox(height: 30 * ratio),
|
||||
InkWell(
|
||||
key: const Key('showSeed'),
|
||||
onTap: () async {
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
WalletData? defaultWallet =
|
||||
_myWalletProvider.getDefaultWallet();
|
||||
String? _pin;
|
||||
if (_myWalletProvider.pinCode == '') {
|
||||
_pin = await Navigator.push(
|
||||
bottomNavigationBar: homeProvider.bottomAppBar(context),
|
||||
body: Stack(children: [
|
||||
Builder(
|
||||
builder: (ctx) => SafeArea(
|
||||
child: Column(children: <Widget>[
|
||||
SizedBox(height: 30 * ratio),
|
||||
InkWell(
|
||||
key: keyShowSeed,
|
||||
onTap: () async {
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
WalletData? defaultWallet =
|
||||
myWalletProvider.getDefaultWallet();
|
||||
String? pin;
|
||||
pin = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (homeContext) {
|
||||
|
@ -68,131 +74,149 @@ class ChestOptions extends StatelessWidget {
|
|||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
if (_pin != null || _myWalletProvider.pinCode != '') {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return ShowSeed(
|
||||
walletName: currentChest.name,
|
||||
walletProvider: walletProvider,
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: SizedBox(
|
||||
height: 50,
|
||||
child: Row(children: <Widget>[
|
||||
const SizedBox(width: 20),
|
||||
Image.asset(
|
||||
'assets/onBoarding/phrase_de_restauration_flou.png',
|
||||
width: 60,
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
Text(
|
||||
'Afficher ma phrase de restauration',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: orangeC,
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10 * ratio),
|
||||
InkWell(
|
||||
key: const Key('changePin'),
|
||||
onTap: () 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;
|
||||
}
|
||||
},
|
||||
child: SizedBox(
|
||||
if (pin != null) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return ShowSeed(
|
||||
walletName: currentChest.name,
|
||||
walletProvider: walletProvider,
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: SizedBox(
|
||||
height: 50,
|
||||
child: Row(children: <Widget>[
|
||||
const SizedBox(width: 26),
|
||||
const SizedBox(width: 20),
|
||||
Image.asset(
|
||||
'assets/chests/secret_code.png',
|
||||
height: 25,
|
||||
'assets/onBoarding/phrase_de_restauration_flou.png',
|
||||
width: 60,
|
||||
),
|
||||
const SizedBox(width: 18),
|
||||
const Text(
|
||||
'Changer mon code secret',
|
||||
style: TextStyle(fontSize: 20, color: Colors.black),
|
||||
const SizedBox(width: 15),
|
||||
Text(
|
||||
'displayMnemonic'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
color: orangeC,
|
||||
),
|
||||
),
|
||||
])),
|
||||
),
|
||||
SizedBox(height: 10 * ratio),
|
||||
InkWell(
|
||||
key: const Key('createRootDerivation'),
|
||||
onTap: () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return const CustomDerivation();
|
||||
},
|
||||
]),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10 * ratio),
|
||||
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,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
if (pinResult != null) {
|
||||
walletProvider.pinCode = pinResult;
|
||||
}
|
||||
}
|
||||
: null,
|
||||
child: SizedBox(
|
||||
height: 50,
|
||||
child: Row(children: <Widget>[
|
||||
const SizedBox(width: 26),
|
||||
Image.asset(
|
||||
'assets/chests/secret_code.png',
|
||||
height: 25,
|
||||
),
|
||||
const SizedBox(width: 18),
|
||||
Text(
|
||||
'changePassword'.tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: sub.nodeConnected
|
||||
? Colors.black
|
||||
: Colors.grey[500]),
|
||||
),
|
||||
])),
|
||||
);
|
||||
}),
|
||||
SizedBox(height: 10 * ratio),
|
||||
Consumer<SubstrateSdk>(builder: (context, sub, _) {
|
||||
return InkWell(
|
||||
key: keycreateRootDerivation,
|
||||
onTap: sub.nodeConnected
|
||||
? () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return const CustomDerivation();
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
: null,
|
||||
child: SizedBox(
|
||||
height: 50,
|
||||
child: Row(children: <Widget>[
|
||||
const SizedBox(width: 35),
|
||||
const Icon(
|
||||
Icons.manage_accounts,
|
||||
size: 33,
|
||||
),
|
||||
const SizedBox(width: 25),
|
||||
Text(
|
||||
'createDerivation'.tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: sub.nodeConnected
|
||||
? Colors.black
|
||||
: Colors.grey[500]),
|
||||
),
|
||||
]),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: SizedBox(
|
||||
height: 50,
|
||||
child: Row(children: const <Widget>[
|
||||
SizedBox(width: 35),
|
||||
Icon(
|
||||
Icons.manage_accounts,
|
||||
size: 33,
|
||||
),
|
||||
SizedBox(width: 25),
|
||||
Text(
|
||||
'Créer une autre dérivation',
|
||||
style: TextStyle(fontSize: 20, color: Colors.black),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10 * ratio),
|
||||
InkWell(
|
||||
key: const Key('deleteChest'),
|
||||
onTap: () async {
|
||||
await _chestProvider.deleteChest(context, currentChest);
|
||||
},
|
||||
child: SizedBox(
|
||||
height: 50,
|
||||
child: Row(children: <Widget>[
|
||||
const SizedBox(width: 28),
|
||||
Image.asset(
|
||||
'assets/walletOptions/trash.png',
|
||||
height: 45,
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
const Text(
|
||||
'Supprimer ce coffre',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: Color(0xffD80000),
|
||||
}),
|
||||
SizedBox(height: 10 * ratio),
|
||||
InkWell(
|
||||
key: keyDeleteChest,
|
||||
onTap: () async {
|
||||
await chestProvider.deleteChest(context, currentChest);
|
||||
},
|
||||
child: SizedBox(
|
||||
height: 50,
|
||||
child: Row(children: <Widget>[
|
||||
const SizedBox(width: 28),
|
||||
Image.asset(
|
||||
'assets/walletOptions/trash.png',
|
||||
height: 45,
|
||||
),
|
||||
),
|
||||
]),
|
||||
const SizedBox(width: 20),
|
||||
Text(
|
||||
'deleteChest'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
color: Color(0xffD80000),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
CommonElements().offlineInfo(context),
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
// 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';
|
||||
import 'package:gecko/models/wallet_data.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -19,7 +23,6 @@ class ChooseChest extends StatefulWidget {
|
|||
}
|
||||
}
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class _ChooseChestState extends State<ChooseChest> {
|
||||
TextEditingController tplController = TextEditingController();
|
||||
CarouselController buttonCarouselController = CarouselController();
|
||||
|
@ -28,16 +31,16 @@ class _ChooseChestState extends State<ChooseChest> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text('Sélectionner mon coffre'),
|
||||
child: Text('selectMyChest'.tr()),
|
||||
)),
|
||||
body: SafeArea(
|
||||
child: Column(children: <Widget>[
|
||||
|
@ -108,15 +111,15 @@ class _ChooseChestState extends State<ChooseChest> {
|
|||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: orangeC, // background
|
||||
onPrimary: Colors.black, // foreground
|
||||
foregroundColor: Colors.black,
|
||||
backgroundColor: orangeC, // foreground
|
||||
),
|
||||
onPressed: () async {
|
||||
await configBox.put('currentChest', currentChest);
|
||||
_myWalletProvider.pinCode = '';
|
||||
myWalletProvider.pinCode = '';
|
||||
WalletData? defaultWallet =
|
||||
_myWalletProvider.getDefaultWallet();
|
||||
_myWalletProvider.rebuildWidget();
|
||||
myWalletProvider.getDefaultWallet();
|
||||
myWalletProvider.reload();
|
||||
|
||||
await Navigator.push(
|
||||
context,
|
||||
|
@ -130,7 +133,7 @@ class _ChooseChestState extends State<ChooseChest> {
|
|||
context,
|
||||
ModalRoute.withName('/'),
|
||||
);
|
||||
if (_myWalletProvider.pinCode != '') {
|
||||
if (myWalletProvider.pinCode != '') {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
|
@ -140,8 +143,8 @@ class _ChooseChestState extends State<ChooseChest> {
|
|||
}
|
||||
},
|
||||
child: Text(
|
||||
'Ouvrir ce coffre',
|
||||
style: TextStyle(
|
||||
'openThisChest'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 22,
|
||||
color: backgroundColor,
|
||||
fontWeight: FontWeight.w600),
|
||||
|
@ -153,7 +156,7 @@ class _ChooseChestState extends State<ChooseChest> {
|
|||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: InkWell(
|
||||
key: const Key('createNewChest'),
|
||||
key: keyCreateNewChest,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
|
@ -166,8 +169,8 @@ class _ChooseChestState extends State<ChooseChest> {
|
|||
width: 400,
|
||||
height: 50,
|
||||
child: Center(
|
||||
child: Text('Créer un nouveau coffre',
|
||||
style: TextStyle(
|
||||
child: Text('createChest'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 22,
|
||||
color: orangeC,
|
||||
fontWeight: FontWeight.w600))),
|
||||
|
@ -176,7 +179,7 @@ class _ChooseChestState extends State<ChooseChest> {
|
|||
),
|
||||
),
|
||||
InkWell(
|
||||
key: const Key('importChest'),
|
||||
key: keyImportChest,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
|
@ -189,8 +192,8 @@ class _ChooseChestState extends State<ChooseChest> {
|
|||
width: 400,
|
||||
height: 50,
|
||||
child: Center(
|
||||
child: Text('Importer un coffre',
|
||||
style: TextStyle(
|
||||
child: Text('importChest'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 22,
|
||||
color: orangeC,
|
||||
fontWeight: FontWeight.w600))),
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
// ignore_for_file: use_build_context_synchronously, must_be_immutable
|
||||
|
||||
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';
|
||||
|
@ -12,7 +16,6 @@ import 'package:provider/provider.dart';
|
|||
// import 'package:gecko/models/home.dart';
|
||||
// import 'package:provider/provider.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class ChooseWalletScreen extends StatelessWidget {
|
||||
ChooseWalletScreen({Key? key, required this.pin}) : super(key: key);
|
||||
final String pin;
|
||||
|
@ -21,16 +24,16 @@ class ChooseWalletScreen extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
final int chest = configBox.get('currentChest');
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text('Choix du portefeuille source'),
|
||||
child: Text('choiceOfSourceWallet'.tr()),
|
||||
)),
|
||||
body: SafeArea(
|
||||
child: Stack(children: [
|
||||
|
@ -43,25 +46,23 @@ class ChooseWalletScreen extends StatelessWidget {
|
|||
width: 470,
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
key: keyConfirm,
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 4,
|
||||
primary: orangeC, // background
|
||||
onPrimary: Colors.white, // foreground
|
||||
foregroundColor: Colors.white, elevation: 4,
|
||||
backgroundColor: orangeC, // foreground
|
||||
),
|
||||
onPressed: () async {
|
||||
await _sub.setCurrentWallet(selectedWallet!);
|
||||
|
||||
// _walletViewProvider.reload();
|
||||
_sub.reload();
|
||||
await sub.setCurrentWallet(selectedWallet!);
|
||||
sub.reload();
|
||||
|
||||
// Navigator.pop(context);
|
||||
Navigator.pop(context);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: const Text(
|
||||
'Choisir ce portefeuille',
|
||||
style:
|
||||
TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
|
||||
child: Text(
|
||||
'chooseThisWallet'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 24, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -71,22 +72,22 @@ class ChooseWalletScreen extends StatelessWidget {
|
|||
));
|
||||
}
|
||||
|
||||
Widget myWalletsTiles(BuildContext context, int? currentChest) {
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
Widget myWalletsTiles(BuildContext context, int currentChest) {
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context);
|
||||
// SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
final bool isWalletsExists = _myWalletProvider.checkIfWalletExist();
|
||||
WalletData? defaultWallet = _myWalletProvider.getDefaultWallet();
|
||||
final bool isWalletsExists = myWalletProvider.checkIfWalletExist();
|
||||
WalletData? defaultWallet = myWalletProvider.getDefaultWallet();
|
||||
|
||||
selectedWallet ??= defaultWallet;
|
||||
_myWalletProvider.readAllWallets(currentChest);
|
||||
myWalletProvider.readAllWallets(currentChest);
|
||||
|
||||
if (!isWalletsExists) {
|
||||
return const Text('');
|
||||
}
|
||||
|
||||
if (_myWalletProvider.listWallets.isEmpty) {
|
||||
if (myWalletProvider.listWallets.isEmpty) {
|
||||
return Column(children: const <Widget>[
|
||||
Center(
|
||||
child: Text(
|
||||
|
@ -96,7 +97,7 @@ class ChooseWalletScreen extends StatelessWidget {
|
|||
]);
|
||||
}
|
||||
|
||||
List _listWallets = _myWalletProvider.listWallets;
|
||||
List listWallets = myWalletProvider.listWallets;
|
||||
final double screenWidth = MediaQuery.of(context).size.width;
|
||||
int nTule = 2;
|
||||
|
||||
|
@ -109,19 +110,20 @@ class ChooseWalletScreen extends StatelessWidget {
|
|||
return CustomScrollView(slivers: <Widget>[
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 20)),
|
||||
SliverGrid.count(
|
||||
key: const Key('listWallets'),
|
||||
key: keyListWallets,
|
||||
crossAxisCount: nTule,
|
||||
childAspectRatio: 1,
|
||||
crossAxisSpacing: 0,
|
||||
mainAxisSpacing: 0,
|
||||
children: <Widget>[
|
||||
for (WalletData _repository in _listWallets as Iterable<WalletData>)
|
||||
for (WalletData repository in listWallets as Iterable<WalletData>)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: GestureDetector(
|
||||
key: keySelectThisWallet(repository.address!),
|
||||
onTap: () {
|
||||
selectedWallet = _repository;
|
||||
_myWalletProvider.rebuildWidget();
|
||||
selectedWallet = repository;
|
||||
myWalletProvider.reload();
|
||||
},
|
||||
child: ClipOvalShadow(
|
||||
shadow: const Shadow(
|
||||
|
@ -146,9 +148,9 @@ class ChooseWalletScreen extends StatelessWidget {
|
|||
const Color(0xFFE7E7A6),
|
||||
],
|
||||
)),
|
||||
child: _repository.imageCustomPath == null
|
||||
child: repository.imageCustomPath == null
|
||||
? Image.asset(
|
||||
'assets/avatars/${_repository.imageDefaultPath}',
|
||||
'assets/avatars/${repository.imageDefaultPath}',
|
||||
alignment: Alignment.bottomCenter,
|
||||
scale: 0.5,
|
||||
)
|
||||
|
@ -161,14 +163,14 @@ class ChooseWalletScreen extends StatelessWidget {
|
|||
image: DecorationImage(
|
||||
fit: BoxFit.contain,
|
||||
image: FileImage(
|
||||
File(_repository.imageCustomPath!),
|
||||
File(repository.imageCustomPath!),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
balanceBuilder(context, _repository.address!,
|
||||
selectedWallet!.address == _repository.address!),
|
||||
balanceBuilder(context, repository.address!,
|
||||
selectedWallet!.address == repository.address!),
|
||||
ListTile(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
|
@ -176,7 +178,7 @@ class ChooseWalletScreen extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
tileColor:
|
||||
_repository.address == selectedWallet!.address
|
||||
repository.address == selectedWallet!.address
|
||||
? orangeC
|
||||
: const Color(0xffFFD58D),
|
||||
title: Center(
|
||||
|
@ -184,11 +186,11 @@ class ChooseWalletScreen extends StatelessWidget {
|
|||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 5),
|
||||
child: Text(
|
||||
_repository.name!,
|
||||
repository.name!,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 17.0,
|
||||
color: _repository.address ==
|
||||
color: repository.address ==
|
||||
selectedWallet!.address
|
||||
? const Color(0xffF9F9F1)
|
||||
: Colors.black,
|
||||
|
@ -197,8 +199,8 @@ class ChooseWalletScreen extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
onTap: () async {
|
||||
selectedWallet = _repository;
|
||||
_myWalletProvider.rebuildWidget();
|
||||
selectedWallet = repository;
|
||||
myWalletProvider.reload();
|
||||
},
|
||||
)
|
||||
]),
|
||||
|
@ -209,12 +211,12 @@ class ChooseWalletScreen extends StatelessWidget {
|
|||
]);
|
||||
}
|
||||
|
||||
Widget balanceBuilder(context, String _address, bool isDefault) {
|
||||
Widget balanceBuilder(context, String address, bool isDefault) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
color: isDefault ? orangeC : yellowC,
|
||||
child: SizedBox(
|
||||
height: 25,
|
||||
height: 30,
|
||||
child: Column(children: [
|
||||
const Spacer(),
|
||||
// Text(
|
||||
|
@ -222,8 +224,10 @@ class ChooseWalletScreen extends StatelessWidget {
|
|||
// textAlign: TextAlign.center,
|
||||
// style: TextStyle(color: isDefault ? Colors.white : Colors.black),
|
||||
// ),
|
||||
balance(
|
||||
context, _address, 15, isDefault ? Colors.white : Colors.black)
|
||||
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||
balance(
|
||||
context, address, 16, isDefault ? Colors.white : Colors.black),
|
||||
])
|
||||
]),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// 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';
|
||||
|
@ -25,7 +28,7 @@ class _CustomDerivationState extends State<CustomDerivation> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
|
||||
final derivationList = <String>[
|
||||
|
@ -33,11 +36,11 @@ class _CustomDerivationState extends State<CustomDerivation> {
|
|||
for (var i = 0; i < 51; i += 1) i.toString()
|
||||
];
|
||||
|
||||
final listWallets = _myWalletProvider.readAllWallets();
|
||||
final listWallets = myWalletProvider.readAllWallets();
|
||||
|
||||
for (WalletData _wallet in listWallets) {
|
||||
derivationList.remove(_wallet.derivation.toString());
|
||||
if (_wallet.derivation == -1) {
|
||||
for (WalletData wallet in listWallets) {
|
||||
derivationList.remove(wallet.derivation.toString());
|
||||
if (wallet.derivation == -1) {
|
||||
derivationList.remove('root');
|
||||
}
|
||||
}
|
||||
|
@ -50,16 +53,16 @@ class _CustomDerivationState extends State<CustomDerivation> {
|
|||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text('Créer une dérivation personnalisé'),
|
||||
child: Text('createCustomDerivation'.tr()),
|
||||
)),
|
||||
body: Center(
|
||||
child: SafeArea(
|
||||
child: Column(children: <Widget>[
|
||||
const Spacer(),
|
||||
const Text(
|
||||
'Choisissez une dérivation:',
|
||||
Text(
|
||||
'chooseDerivation'.tr(),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
SizedBox(
|
||||
|
@ -69,7 +72,7 @@ class _CustomDerivationState extends State<CustomDerivation> {
|
|||
menuMaxHeight: 300,
|
||||
icon: const Icon(Icons.arrow_downward),
|
||||
elevation: 16,
|
||||
style: TextStyle(color: orangeC),
|
||||
style: const TextStyle(color: orangeC),
|
||||
underline: Container(
|
||||
height: 2,
|
||||
color: orangeC,
|
||||
|
@ -104,16 +107,15 @@ class _CustomDerivationState extends State<CustomDerivation> {
|
|||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 4,
|
||||
primary: orangeC, // background
|
||||
onPrimary: Colors.white, // foreground
|
||||
foregroundColor: Colors.white, elevation: 4,
|
||||
backgroundColor: orangeC, // foreground
|
||||
),
|
||||
onPressed: () async {
|
||||
WalletData? defaultWallet =
|
||||
_myWalletProvider.getDefaultWallet();
|
||||
String? _pin;
|
||||
if (_myWalletProvider.pinCode == '') {
|
||||
_pin = await Navigator.push(
|
||||
myWalletProvider.getDefaultWallet();
|
||||
String? pin;
|
||||
if (myWalletProvider.pinCode == '') {
|
||||
pin = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (homeContext) {
|
||||
|
@ -123,16 +125,16 @@ class _CustomDerivationState extends State<CustomDerivation> {
|
|||
);
|
||||
}
|
||||
|
||||
if (_pin != null || _myWalletProvider.pinCode != '') {
|
||||
String _newDerivationName =
|
||||
'Portefeuille ${_myWalletProvider.listWallets.last.number! + 2}';
|
||||
if (pin != null || myWalletProvider.pinCode != '') {
|
||||
String newDerivationName =
|
||||
'${'wallet'.tr()} ${myWalletProvider.listWallets.last.number! + 2}';
|
||||
if (dropdownValue == 'root') {
|
||||
await _myWalletProvider.generateRootWallet(
|
||||
await myWalletProvider.generateRootWallet(
|
||||
context, 'Portefeuille racine');
|
||||
} else {
|
||||
await _myWalletProvider.generateNewDerivation(
|
||||
await myWalletProvider.generateNewDerivation(
|
||||
context,
|
||||
_newDerivationName,
|
||||
newDerivationName,
|
||||
int.parse(dropdownValue!),
|
||||
);
|
||||
}
|
||||
|
@ -146,9 +148,10 @@ class _CustomDerivationState extends State<CustomDerivation> {
|
|||
// );
|
||||
}
|
||||
},
|
||||
child: const Text(
|
||||
'Valider',
|
||||
style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
|
||||
child: Text(
|
||||
'validate'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 24, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -0,0 +1,317 @@
|
|||
// 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/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:provider/provider.dart';
|
||||
|
||||
class ImportG1v1 extends StatelessWidget {
|
||||
const ImportG1v1({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
WalletOptionsProvider walletOptions =
|
||||
Provider.of<WalletOptionsProvider>(context, listen: false);
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
|
||||
Timer? debounce;
|
||||
const int debouneTime = 300;
|
||||
WalletData selectedWallet = myWalletProvider.getDefaultWallet();
|
||||
bool canValidate = false;
|
||||
String validationStatus = '';
|
||||
|
||||
return WillPopScope(
|
||||
onWillPop: () {
|
||||
resetScreen(context);
|
||||
return Future<bool>.value(true);
|
||||
},
|
||||
child: Scaffold(
|
||||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back, color: Colors.black),
|
||||
onPressed: () {
|
||||
resetScreen(context);
|
||||
|
||||
Navigator.of(context).pop();
|
||||
}),
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text('importOldAccount'.tr()),
|
||||
)),
|
||||
body: SafeArea(
|
||||
child: Consumer<SubstrateSdk>(builder: (context, sub, _) {
|
||||
return FutureBuilder(
|
||||
future: sub.getBalanceAndIdtyStatus(
|
||||
sub.g1V1NewAddress, selectedWallet.address!),
|
||||
builder: (BuildContext context, AsyncSnapshot<List> status) {
|
||||
// log.d(_certs.data);
|
||||
|
||||
if (status.data == null) {
|
||||
return Column(children: [
|
||||
const SizedBox(height: 80),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: const [
|
||||
SizedBox(
|
||||
height: 35,
|
||||
width: 35,
|
||||
child: CircularProgressIndicator(
|
||||
color: orangeC,
|
||||
strokeWidth: 4,
|
||||
),
|
||||
),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
final Map balance = status.data?[0] ?? {};
|
||||
final String idtyStatus = status.data?[1];
|
||||
final String myIdtyStatus = status.data?[2];
|
||||
final bool hasConsumer = status.data?[3] ?? false;
|
||||
|
||||
// log.d('hasconsumer: $hasConsumer');
|
||||
|
||||
if (balance['transferableBalance'] != 0 && !hasConsumer) {
|
||||
canValidate = true;
|
||||
validationStatus = '';
|
||||
} else {
|
||||
canValidate = false;
|
||||
validationStatus = hasConsumer
|
||||
? 'youMustWaitBeforeCashoutThisAccount'.tr(args: ['X'])
|
||||
: 'thisAccountIsEmpty'.tr();
|
||||
}
|
||||
|
||||
if (idtyStatus != 'noid' && myIdtyStatus != 'noid') {
|
||||
canValidate = false;
|
||||
validationStatus =
|
||||
'youCannotMigrateIdentityToExistingIdentity'.tr();
|
||||
}
|
||||
|
||||
if (sub.g1V1NewAddress == '') {
|
||||
validationStatus = '';
|
||||
}
|
||||
|
||||
final bool isUdUnit = configBox.get('isUdUnit') ?? false;
|
||||
final unit = isUdUnit ? 'ud'.tr(args: ['']) : currencyName;
|
||||
|
||||
return Column(children: <Widget>[
|
||||
const SizedBox(height: 20),
|
||||
TextFormField(
|
||||
key: keyCesiumId,
|
||||
autofocus: true,
|
||||
onChanged: (text) {
|
||||
if (debounce?.isActive ?? false) {
|
||||
debounce!.cancel();
|
||||
}
|
||||
debounce = Timer(
|
||||
const Duration(milliseconds: debouneTime), () {
|
||||
sub.reload();
|
||||
sub.csToV2Address(
|
||||
sub.csSalt.text, sub.csPassword.text);
|
||||
});
|
||||
},
|
||||
keyboardType: TextInputType.text,
|
||||
controller: sub.csSalt,
|
||||
obscureText: !sub
|
||||
.isCesiumIDVisible, //This will obscure text dynamically
|
||||
decoration: InputDecoration(
|
||||
hintText: 'enterCesiumId'.tr(),
|
||||
suffixIcon: IconButton(
|
||||
key: keyCesiumIdVisible,
|
||||
icon: Icon(
|
||||
sub.isCesiumIDVisible
|
||||
? Icons.visibility_off
|
||||
: Icons.visibility,
|
||||
color: Colors.black,
|
||||
),
|
||||
onPressed: () {
|
||||
sub.cesiumIDisVisible();
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextFormField(
|
||||
key: keyCesiumPassword,
|
||||
autofocus: true,
|
||||
onChanged: (text) {
|
||||
if (debounce?.isActive ?? false) {
|
||||
debounce!.cancel();
|
||||
}
|
||||
debounce = Timer(
|
||||
const Duration(milliseconds: debouneTime), () {
|
||||
sub.g1V1NewAddress = '';
|
||||
sub.reload();
|
||||
sub.csToV2Address(
|
||||
sub.csSalt.text, sub.csPassword.text);
|
||||
});
|
||||
},
|
||||
keyboardType: TextInputType.text,
|
||||
controller: sub.csPassword,
|
||||
obscureText: !sub
|
||||
.isCesiumIDVisible, //This will obscure text dynamically
|
||||
decoration: InputDecoration(
|
||||
hintText: 'enterCesiumPassword'.tr(),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
sub.isCesiumIDVisible
|
||||
? Icons.visibility_off
|
||||
: Icons.visibility,
|
||||
color: Colors.black,
|
||||
),
|
||||
onPressed: () {
|
||||
sub.cesiumIDisVisible();
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
GestureDetector(
|
||||
key: keyCopyAddress,
|
||||
onTap: () {
|
||||
Clipboard.setData(
|
||||
ClipboardData(text: sub.g1V1NewAddress));
|
||||
snackCopyKey(context);
|
||||
},
|
||||
child: Text(
|
||||
getShortPubkey(sub.g1V1NewAddress),
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
'${balance['transferableBalance']} $unit',
|
||||
style: const TextStyle(fontSize: 17),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
walletOptions.idtyStatus(context, sub.g1V1NewAddress,
|
||||
isOwner: false, color: Colors.black),
|
||||
const SizedBox(width: 10),
|
||||
getCerts(context, sub.g1V1NewAddress, 14)
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
Text('selectDestWallet'.tr()),
|
||||
const SizedBox(height: 5),
|
||||
DropdownButtonHideUnderline(
|
||||
key: keySelectWallet,
|
||||
child: DropdownButton(
|
||||
// alignment: AlignmentDirectional.topStart,
|
||||
value: selectedWallet,
|
||||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
items: myWalletProvider.listWallets.map((wallet) {
|
||||
return DropdownMenuItem(
|
||||
key: keySelectThisWallet(wallet.address!),
|
||||
value: wallet,
|
||||
child: Text(
|
||||
wallet.name!,
|
||||
style: const TextStyle(fontSize: 18),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (WalletData? newSelectedWallet) {
|
||||
selectedWallet = newSelectedWallet!;
|
||||
sub.reload();
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
SizedBox(
|
||||
width: 380 * ratio,
|
||||
height: 60 * ratio,
|
||||
child: ElevatedButton(
|
||||
key: keyConfirm,
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white, elevation: 4,
|
||||
backgroundColor: orangeC, // foreground
|
||||
),
|
||||
onPressed: canValidate
|
||||
? () async {
|
||||
WalletData? defaultWallet =
|
||||
myWalletProvider.getDefaultWallet();
|
||||
|
||||
String? pin;
|
||||
if (myWalletProvider.pinCode == '') {
|
||||
pin = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (homeContext) {
|
||||
return UnlockingWallet(
|
||||
wallet: defaultWallet);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
sub.migrateCsToV2(
|
||||
sub.csSalt.text,
|
||||
sub.csPassword.text,
|
||||
selectedWallet.address!,
|
||||
destPassword:
|
||||
pin ?? myWalletProvider.pinCode,
|
||||
balance: balance,
|
||||
idtyStatus: idtyStatus);
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return TransactionInProgress(
|
||||
transType: 'identityMigration',
|
||||
fromAddress:
|
||||
getShortPubkey(sub.g1V1NewAddress),
|
||||
toAddress: getShortPubkey(
|
||||
selectedWallet.address!));
|
||||
}),
|
||||
);
|
||||
resetScreen(context);
|
||||
}
|
||||
: null,
|
||||
child: Text(
|
||||
'migrateAccount'.tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 23 * ratio,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
validationStatus,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 15, color: Colors.grey[600]),
|
||||
)
|
||||
]);
|
||||
});
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void resetScreen(BuildContext context) {
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
sub.csSalt.text = '';
|
||||
sub.csPassword.text = '';
|
||||
sub.g1V1NewAddress = '';
|
||||
}
|
||||
}
|
|
@ -1,6 +1,18 @@
|
|||
// 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/screens/myWallets/migrate_identity.dart';
|
||||
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
|
||||
import 'package:gecko/screens/transaction_in_progress.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
// import 'package:gecko/models/wallet_data.dart';
|
||||
// import 'package:gecko/providers/my_wallets.dart';
|
||||
// import 'package:gecko/providers/substrate_sdk.dart';
|
||||
|
@ -16,77 +28,140 @@ class ManageMembership extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
// HomeProvider _homeProvider = Provider.of<HomeProvider>(context);
|
||||
final sub = Provider.of<SubstrateSdk>(context);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text('Gérer mon adhésion'),
|
||||
child: const Text('manageMembership').tr(),
|
||||
)),
|
||||
body: SafeArea(
|
||||
child: Column(children: <Widget>[
|
||||
const SizedBox(height: 20),
|
||||
revokeMyIdentity(context),
|
||||
migrateIdentity(context),
|
||||
const SizedBox(height: 10),
|
||||
FutureBuilder(
|
||||
future: sub.isSmithGet(address),
|
||||
builder: (BuildContext context, AsyncSnapshot<bool> isSmith) {
|
||||
if (isSmith.data ?? false) {
|
||||
return SizedBox(
|
||||
height: 70,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
const SizedBox(width: 20),
|
||||
Image.asset(
|
||||
'assets/skull_Icon.png',
|
||||
color: Colors.grey[500],
|
||||
height: 30,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('revokeMyIdentity'.tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: Colors.grey[500])),
|
||||
const SizedBox(height: 5),
|
||||
Text("youCannotRevokeThisIdentity".tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey[500])),
|
||||
]),
|
||||
],
|
||||
));
|
||||
} else {
|
||||
return revokeMyIdentity(context);
|
||||
}
|
||||
})
|
||||
// const SizedBox(height: 20),
|
||||
]),
|
||||
));
|
||||
}
|
||||
|
||||
Widget revokeMyIdentity(BuildContext context) {
|
||||
Widget migrateIdentity(BuildContext context) {
|
||||
return InkWell(
|
||||
key: const Key('revokeIdty'),
|
||||
key: keyMigrateIdentity,
|
||||
onTap: () async {
|
||||
// TODOO: Generate revoke document, and understand extrinsic identity.revokeIdentity options
|
||||
// final _answer = await confirmPopup(context,
|
||||
// 'Êtes-vous certains de vouloir révoquer définitivement cette identité ?') ??
|
||||
// false;
|
||||
|
||||
// if (_answer) {
|
||||
// MyWalletsProvider _myWalletProvider =
|
||||
// Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
// SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
// MyWalletsProvider _mw = MyWalletsProvider();
|
||||
// final _wallet = _mw.getWalletDataByAddress(address);
|
||||
// await _sub.setCurrentWallet(_wallet!);
|
||||
|
||||
// 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 != '') {
|
||||
// _sub.revokeIdentity(address, _myWalletProvider.pinCode);
|
||||
// }
|
||||
// Navigator.pop(context);
|
||||
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(builder: (context) {
|
||||
// return const TransactionInProgress(transType: 'revokeIdty');
|
||||
// }),
|
||||
// );
|
||||
// }
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return const MigrateIdentityScreen();
|
||||
}),
|
||||
);
|
||||
},
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
height: 60,
|
||||
child: Row(children: const <Widget>[
|
||||
SizedBox(width: 32),
|
||||
// Image.asset(
|
||||
// 'assets/medal.png',
|
||||
// height: 45,
|
||||
// ),
|
||||
Text('Révoquer mon adhésion', style: TextStyle(fontSize: 20)),
|
||||
SizedBox(width: 16),
|
||||
Icon(Icons.change_circle_outlined, size: 35),
|
||||
SizedBox(width: 11.5),
|
||||
Text('Migrer mon identité', style: TextStyle(fontSize: 20)),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget revokeMyIdentity(BuildContext context) {
|
||||
return InkWell(
|
||||
key: keyRevokeIdty,
|
||||
onTap: () async {
|
||||
// TODOO: Generate revoke document, and understand extrinsic identity.revokeIdentity options
|
||||
final answer = await confirmPopup(context,
|
||||
'Êtes-vous certains de vouloir révoquer définitivement cette identité ?') ??
|
||||
false;
|
||||
|
||||
if (answer) {
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
// MyWalletsProvider mw = MyWalletsProvider();
|
||||
// final wallet = mw.getWalletDataByAddress(address);
|
||||
// await sub.setCurrentWallet(wallet!);
|
||||
|
||||
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 != '') {
|
||||
sub.revokeIdentity(address, myWalletProvider.pinCode);
|
||||
}
|
||||
Navigator.pop(context);
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return TransactionInProgress(
|
||||
transType: 'revokeIdty',
|
||||
fromAddress: getShortPubkey(address),
|
||||
toAddress: getShortPubkey(address));
|
||||
}),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: SizedBox(
|
||||
height: 60,
|
||||
child: Row(children: <Widget>[
|
||||
const SizedBox(width: 20),
|
||||
Image.asset(
|
||||
'assets/skull_Icon.png',
|
||||
height: 30,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
const Text('Révoquer mon adhésion', style: TextStyle(fontSize: 20)),
|
||||
]),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -0,0 +1,260 @@
|
|||
// 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';
|
||||
import 'package:gecko/models/wallet_data.dart';
|
||||
import 'package:gecko/models/widgets_keys.dart';
|
||||
import 'package:gecko/providers/duniter_indexer.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/unlocking_wallet.dart';
|
||||
import 'package:gecko/screens/transaction_in_progress.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MigrateIdentityScreen extends StatelessWidget {
|
||||
const MigrateIdentityScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
// HomeProvider _homeProvider = Provider.of<HomeProvider>(context);
|
||||
WalletOptionsProvider walletOptions =
|
||||
Provider.of<WalletOptionsProvider>(context, listen: false);
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
DuniterIndexer duniterIndexer =
|
||||
Provider.of<DuniterIndexer>(context, listen: false);
|
||||
|
||||
final fromAddress = walletOptions.address.text;
|
||||
final defaultWallet = myWalletProvider.getDefaultWallet();
|
||||
final walletsList = myWalletProvider.listWallets.toList();
|
||||
late WalletData selectedWallet;
|
||||
|
||||
if (fromAddress == defaultWallet.address) {
|
||||
selectedWallet =
|
||||
walletsList[fromAddress == walletsList[0].address ? 1 : 0];
|
||||
} else {
|
||||
selectedWallet = defaultWallet;
|
||||
}
|
||||
bool canValidate = false;
|
||||
String validationStatus = '';
|
||||
|
||||
final mdStyle = MarkdownStyleSheet(
|
||||
p: const TextStyle(fontSize: 18, color: Colors.black, letterSpacing: 0.3),
|
||||
textAlign: WrapAlignment.center,
|
||||
);
|
||||
|
||||
if (walletsList.length < 2) {
|
||||
return Column(
|
||||
children: [
|
||||
const SizedBox(height: 80),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: const [
|
||||
Text(
|
||||
'Vous devez avoir au moins 2 portefeuilles\npour effecter cette opération',
|
||||
style: TextStyle(fontSize: 20),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text('importOldAccount'.tr()),
|
||||
)),
|
||||
body: SafeArea(
|
||||
child: Consumer<SubstrateSdk>(builder: (context, sub, _) {
|
||||
return FutureBuilder(
|
||||
future: sub.getBalanceAndIdtyStatus(
|
||||
fromAddress, selectedWallet.address!),
|
||||
builder: (BuildContext context, AsyncSnapshot<List> status) {
|
||||
if (status.data == null) {
|
||||
return Column(children: [
|
||||
const SizedBox(height: 80),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: const [
|
||||
SizedBox(
|
||||
height: 35,
|
||||
width: 35,
|
||||
child: CircularProgressIndicator(
|
||||
color: orangeC,
|
||||
strokeWidth: 4,
|
||||
),
|
||||
),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
// log.d('statusData: ${status.data}');
|
||||
|
||||
final Map balance = status.data?[0] ?? {};
|
||||
final String idtyStatus = status.data?[1];
|
||||
final String myIdtyStatus = status.data?[2];
|
||||
final bool hasConsumer = status.data?[3] ?? false;
|
||||
|
||||
// log.d('hasconsumer: $hasConsumer');
|
||||
|
||||
if (balance['transferableBalance'] != 0 && !hasConsumer) {
|
||||
canValidate = true;
|
||||
validationStatus = '';
|
||||
} else {
|
||||
canValidate = false;
|
||||
validationStatus = hasConsumer
|
||||
? 'youMustWaitBeforeCashoutThisAccount'.tr(args: ['X'])
|
||||
: 'thisAccountIsEmpty'.tr();
|
||||
}
|
||||
|
||||
if (idtyStatus != 'noid' && myIdtyStatus != 'noid') {
|
||||
canValidate = false;
|
||||
validationStatus =
|
||||
'youCannotMigrateIdentityToExistingIdentity'.tr();
|
||||
}
|
||||
|
||||
log.d(
|
||||
'tatatata: ${sub.g1V1NewAddress}, ${selectedWallet.address!}, $balance, $idtyStatus, $myIdtyStatus');
|
||||
|
||||
final walletsList = myWalletProvider.listWallets.toList();
|
||||
|
||||
walletsList
|
||||
.removeWhere((element) => element.address == fromAddress);
|
||||
// walletsList.add(WalletData(address: 'custom', name: 'custom'));
|
||||
|
||||
final bool isUdUnit = configBox.get('isUdUnit') ?? false;
|
||||
final unit = isUdUnit ? 'ud'.tr(args: ['']) : currencyName;
|
||||
|
||||
return Column(children: <Widget>[
|
||||
Row(children: const []),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
SizedBox(
|
||||
width: 350,
|
||||
child: MarkdownBody(
|
||||
data: 'areYouSureMigrateIdentity'.tr(args: [
|
||||
duniterIndexer.walletNameIndexer[fromAddress] ??
|
||||
'???',
|
||||
'${balance['transferableBalance']} $unit'
|
||||
]),
|
||||
styleSheet: mdStyle),
|
||||
),
|
||||
// Text(
|
||||
// 'areYouSureMigrateIdentity'.tr(args: [
|
||||
// duniterIndexer
|
||||
// .walletNameIndexer[fromAddress]!,
|
||||
// '$balance $currencyName'
|
||||
// ]),
|
||||
// textAlign: TextAlign.center,
|
||||
// ),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
sub.g1V1NewAddress,
|
||||
style: const TextStyle(
|
||||
fontSize: 14.0,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: 'Monospace'),
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
Text('selectDestWallet'.tr()),
|
||||
const SizedBox(height: 5),
|
||||
DropdownButtonHideUnderline(
|
||||
key: keySelectWallet,
|
||||
child: DropdownButton(
|
||||
// alignment: AlignmentDirectional.topStart,
|
||||
value: selectedWallet,
|
||||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
items: walletsList.map((wallet) {
|
||||
return DropdownMenuItem(
|
||||
key: keySelectThisWallet(wallet.address!),
|
||||
value: wallet,
|
||||
child: Text(
|
||||
wallet.name!,
|
||||
style: const TextStyle(fontSize: 18),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (WalletData? newSelectedWallet) {
|
||||
selectedWallet = newSelectedWallet!;
|
||||
sub.reload();
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
SizedBox(
|
||||
width: 380 * ratio,
|
||||
height: 60 * ratio,
|
||||
child: ElevatedButton(
|
||||
key: keyConfirm,
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white, elevation: 4,
|
||||
backgroundColor: orangeC, // foreground
|
||||
),
|
||||
onPressed: canValidate
|
||||
? () async {
|
||||
log.d('GOOO');
|
||||
WalletData? defaultWallet =
|
||||
myWalletProvider.getDefaultWallet();
|
||||
|
||||
String? pin;
|
||||
if (myWalletProvider.pinCode == '') {
|
||||
pin = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (homeContext) {
|
||||
return UnlockingWallet(
|
||||
wallet: defaultWallet);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
sub.migrateIdentity(
|
||||
fromAddress: fromAddress,
|
||||
destAddress: selectedWallet.address!,
|
||||
fromPassword: pin ?? myWalletProvider.pinCode,
|
||||
destPassword: pin ?? myWalletProvider.pinCode,
|
||||
withBalance: true,
|
||||
fromBalance: balance);
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return TransactionInProgress(
|
||||
transType: 'identityMigration',
|
||||
fromAddress: getShortPubkey(fromAddress),
|
||||
toAddress: getShortPubkey(
|
||||
selectedWallet.address!));
|
||||
}),
|
||||
);
|
||||
}
|
||||
: null,
|
||||
child: Text(
|
||||
'migrateIdentity'.tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 23 * ratio, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
validationStatus,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 15, color: Colors.grey[600]),
|
||||
)
|
||||
]);
|
||||
});
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
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';
|
||||
|
@ -20,7 +22,7 @@ class RestoreChest extends StatelessWidget {
|
|||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
GenerateWalletsProvider genW =
|
||||
Provider.of<GenerateWalletsProvider>(context, listen: false);
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
genW.actualWallet = null;
|
||||
if (genW.isSentenceComplete(context)) {
|
||||
|
@ -43,116 +45,119 @@ class RestoreChest extends StatelessWidget {
|
|||
genW.resetImportView();
|
||||
Navigator.of(context).pop();
|
||||
}),
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text('Restaurer un coffre'),
|
||||
child: Text('restoreAChest'.tr()),
|
||||
)),
|
||||
body: SafeArea(
|
||||
child: Column(children: <Widget>[
|
||||
SizedBox(height: isTall ? 30 : 15),
|
||||
bubbleSpeak(
|
||||
'Pour restaurer vos portefeuilles Gecko, rentrez dans les champs ci-dessous les 12 mots qui constituent votre phrase de restauration :'),
|
||||
SizedBox(height: isTall ? 30 : 15),
|
||||
child: Stack(children: [
|
||||
Column(children: <Widget>[
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
arrayCell(context, genW.cellController0),
|
||||
arrayCell(context, genW.cellController1),
|
||||
arrayCell(context, genW.cellController2),
|
||||
arrayCell(context, genW.cellController3),
|
||||
]),
|
||||
const SizedBox(height: 15),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
arrayCell(context, genW.cellController4),
|
||||
arrayCell(context, genW.cellController5),
|
||||
arrayCell(context, genW.cellController6),
|
||||
arrayCell(context, genW.cellController7),
|
||||
]),
|
||||
const SizedBox(height: 15),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
arrayCell(context, genW.cellController8),
|
||||
arrayCell(context, genW.cellController9),
|
||||
arrayCell(context, genW.cellController10),
|
||||
arrayCell(context, genW.cellController11),
|
||||
]),
|
||||
]),
|
||||
// const Spacer(),
|
||||
if (genW.isSentenceComplete(context))
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: SizedBox(
|
||||
width: 410,
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 4,
|
||||
primary: orangeC, // background
|
||||
onPrimary: Colors.white, // foreground
|
||||
),
|
||||
onPressed: () async {
|
||||
if (await _sub.isMnemonicValid(genW.generatedMnemonic!)) {
|
||||
genW.resetImportView();
|
||||
await Navigator.push(
|
||||
context,
|
||||
FaderTransition(
|
||||
page: skipIntro
|
||||
? const OnboardingStepNine(
|
||||
scanDerivation: true)
|
||||
: const OnboardingStepSeven(
|
||||
scanDerivation: true),
|
||||
isFast: true),
|
||||
);
|
||||
} else {
|
||||
await badMnemonicPopup(context);
|
||||
}
|
||||
},
|
||||
child: const Text(
|
||||
'Restaurer ce coffre',
|
||||
style:
|
||||
TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
|
||||
SizedBox(height: isTall ? 30 : 15),
|
||||
bubbleSpeak('toRestoreEnterMnemonic'.tr()),
|
||||
SizedBox(height: isTall ? 30 : 15),
|
||||
Column(children: <Widget>[
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
arrayCell(context, genW.cellController0),
|
||||
arrayCell(context, genW.cellController1),
|
||||
arrayCell(context, genW.cellController2),
|
||||
arrayCell(context, genW.cellController3),
|
||||
]),
|
||||
const SizedBox(height: 15),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
arrayCell(context, genW.cellController4),
|
||||
arrayCell(context, genW.cellController5),
|
||||
arrayCell(context, genW.cellController6),
|
||||
arrayCell(context, genW.cellController7),
|
||||
]),
|
||||
const SizedBox(height: 15),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
arrayCell(context, genW.cellController8),
|
||||
arrayCell(context, genW.cellController9),
|
||||
arrayCell(context, genW.cellController10),
|
||||
arrayCell(context, genW.cellController11),
|
||||
]),
|
||||
]),
|
||||
// const Spacer(),
|
||||
if (genW.isSentenceComplete(context))
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: SizedBox(
|
||||
width: 410,
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
key: keyGoNext,
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white, elevation: 4,
|
||||
backgroundColor: orangeC, // foreground
|
||||
),
|
||||
onPressed: () async {
|
||||
if (await sub
|
||||
.isMnemonicValid(genW.generatedMnemonic!)) {
|
||||
genW.resetImportView();
|
||||
await Navigator.push(
|
||||
context,
|
||||
FaderTransition(
|
||||
page: skipIntro
|
||||
? const OnboardingStepNine(
|
||||
scanDerivation: true)
|
||||
: const OnboardingStepSeven(
|
||||
scanDerivation: true),
|
||||
isFast: true),
|
||||
);
|
||||
} else {
|
||||
await badMnemonicPopup(context);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
'restoreThisChest'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 24, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// SizedBox(height: isTall ? 80 : 80),
|
||||
))
|
||||
else
|
||||
Column(children: [
|
||||
const SizedBox(height: 20),
|
||||
SizedBox(
|
||||
width: 190,
|
||||
height: 60,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 4,
|
||||
primary: yellowC, // background
|
||||
onPrimary: Colors.black, // foreground
|
||||
),
|
||||
onPressed: () {
|
||||
genW.pasteMnemonic(context);
|
||||
},
|
||||
child: Row(
|
||||
children: const [
|
||||
Icon(
|
||||
Icons.content_paste_go,
|
||||
size: 25,
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
Text(
|
||||
'Coller depuis le\npresse-papier',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 17, fontWeight: FontWeight.w400),
|
||||
),
|
||||
],
|
||||
)),
|
||||
)
|
||||
])
|
||||
// SizedBox(height: isTall ? 80 : 80),
|
||||
))
|
||||
else
|
||||
Column(children: [
|
||||
const SizedBox(height: 20),
|
||||
SizedBox(
|
||||
width: 190,
|
||||
height: 60,
|
||||
child: ElevatedButton(
|
||||
key: keyPastMnemonic,
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.black, elevation: 4,
|
||||
backgroundColor: yellowC, // foreground
|
||||
),
|
||||
onPressed: () {
|
||||
genW.pasteMnemonic(context);
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.content_paste_go,
|
||||
size: 25,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
'pasteFromClipboard'.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontSize: 17, fontWeight: FontWeight.w400),
|
||||
),
|
||||
],
|
||||
)),
|
||||
)
|
||||
])
|
||||
]),
|
||||
CommonElements().offlineInfo(context),
|
||||
]),
|
||||
),
|
||||
),
|
||||
|
@ -169,7 +174,7 @@ class RestoreChest extends StatelessWidget {
|
|||
color: Colors.white,
|
||||
child: Text(
|
||||
text,
|
||||
key: const Key('importText'),
|
||||
key: keyBubbleSpeak,
|
||||
textAlign: TextAlign.justify,
|
||||
style: const TextStyle(
|
||||
color: Colors.black, fontSize: 19, fontWeight: FontWeight.w400),
|
||||
|
@ -184,6 +189,12 @@ class RestoreChest extends StatelessWidget {
|
|||
return Container(
|
||||
width: 102,
|
||||
height: 40 * ratio,
|
||||
// ),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey),
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
),
|
||||
// child: RawKeyboardListener(
|
||||
// focusNode: FocusNode(), // or FocusNode()
|
||||
// onKey: (event) {
|
||||
|
@ -210,12 +221,6 @@ class RestoreChest extends StatelessWidget {
|
|||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(fontSize: 20),
|
||||
),
|
||||
// ),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey),
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import 'dart:typed_data';
|
||||
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';
|
||||
|
@ -23,32 +24,32 @@ class ShowSeed extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
CommonElements common = CommonElements();
|
||||
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
WalletData defaultWallet = _myWalletProvider.getDefaultWallet();
|
||||
WalletData defaultWallet = myWalletProvider.getDefaultWallet();
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text('Ma phrase de restauration'),
|
||||
child: Text('myMnemonic'.tr()),
|
||||
)),
|
||||
body: SafeArea(
|
||||
child: Column(children: <Widget>[
|
||||
const Spacer(flex: 1),
|
||||
FutureBuilder(
|
||||
future: _sub.getSeed(
|
||||
defaultWallet.address!, walletProvider.pinCode),
|
||||
builder: (BuildContext context, AsyncSnapshot<String?> _seed) {
|
||||
if (_seed.connectionState != ConnectionState.done ||
|
||||
_seed.hasError) {
|
||||
return SizedBox(
|
||||
future:
|
||||
sub.getSeed(defaultWallet.address!, walletProvider.pinCode),
|
||||
builder: (BuildContext context, AsyncSnapshot<String?> seed) {
|
||||
if (seed.connectionState != ConnectionState.done ||
|
||||
seed.hasError) {
|
||||
return const SizedBox(
|
||||
height: 15,
|
||||
width: 15,
|
||||
child: CircularProgressIndicator(
|
||||
|
@ -56,7 +57,7 @@ class ShowSeed extends StatelessWidget {
|
|||
strokeWidth: 2,
|
||||
),
|
||||
);
|
||||
} else if (!_seed.hasData) {
|
||||
} else if (!seed.hasData) {
|
||||
return const Text('');
|
||||
}
|
||||
|
||||
|
@ -64,30 +65,24 @@ class ShowSeed extends StatelessWidget {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Column(children: [
|
||||
common.buildText(
|
||||
<TextSpan>[
|
||||
const TextSpan(
|
||||
text:
|
||||
'Tâchez de garder cette phrase bien secrète, car elle permet à quiconque la connaît d’accéder à tous vos portefeuilles.'),
|
||||
],
|
||||
),
|
||||
common.buildText('keepYourMnemonicSecret'.tr()),
|
||||
SizedBox(height: 35 * ratio),
|
||||
sentanceArray(context, _seed.data!.split(' ')),
|
||||
sentanceArray(context, seed.data!.split(' ')),
|
||||
const SizedBox(height: 20),
|
||||
SizedBox(
|
||||
height: 40,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.black,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
elevation: 1,
|
||||
primary: orangeC, // background
|
||||
onPrimary: Colors.black, // foreground
|
||||
backgroundColor: orangeC,
|
||||
elevation: 1, // foreground
|
||||
),
|
||||
onPressed: () {
|
||||
Clipboard.setData(
|
||||
ClipboardData(text: _seed.data));
|
||||
ClipboardData(text: seed.data));
|
||||
snackCopyKey(context);
|
||||
},
|
||||
child: Row(children: <Widget>[
|
||||
|
@ -97,7 +92,7 @@ class ShowSeed extends StatelessWidget {
|
|||
),
|
||||
const SizedBox(width: 7),
|
||||
Text(
|
||||
'Copier',
|
||||
'copy'.tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 15, color: Colors.grey[50]),
|
||||
)
|
||||
|
@ -110,7 +105,7 @@ class ShowSeed extends StatelessWidget {
|
|||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return PrintWallet(_seed.data);
|
||||
return PrintWallet(seed.data);
|
||||
}),
|
||||
);
|
||||
},
|
||||
|
@ -128,15 +123,14 @@ class ShowSeed extends StatelessWidget {
|
|||
height: 60 * ratio,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 4,
|
||||
primary: orangeC, // background
|
||||
onPrimary: Colors.white, // foreground
|
||||
foregroundColor: Colors.white, elevation: 4,
|
||||
backgroundColor: orangeC, // foreground
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(
|
||||
'Fermer',
|
||||
'close'.tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 23 * ratio, fontWeight: FontWeight.w600),
|
||||
),
|
||||
|
@ -157,7 +151,7 @@ class ShowSeed extends StatelessWidget {
|
|||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
}
|
||||
|
||||
Widget sentanceArray(BuildContext context, List _mnemonic) {
|
||||
Widget sentanceArray(BuildContext context, List mnemonic) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 3),
|
||||
child: Container(
|
||||
|
@ -175,24 +169,24 @@ class ShowSeed extends StatelessWidget {
|
|||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Row(children: <Widget>[
|
||||
arrayCell(_mnemonic[0], 1),
|
||||
arrayCell(_mnemonic[1], 2),
|
||||
arrayCell(_mnemonic[2], 3),
|
||||
arrayCell(_mnemonic[3], 4),
|
||||
arrayCell(mnemonic[0], 1),
|
||||
arrayCell(mnemonic[1], 2),
|
||||
arrayCell(mnemonic[2], 3),
|
||||
arrayCell(mnemonic[3], 4),
|
||||
]),
|
||||
const SizedBox(height: 15),
|
||||
Row(children: <Widget>[
|
||||
arrayCell(_mnemonic[4], 5),
|
||||
arrayCell(_mnemonic[5], 6),
|
||||
arrayCell(_mnemonic[6], 7),
|
||||
arrayCell(_mnemonic[7], 8),
|
||||
arrayCell(mnemonic[4], 5),
|
||||
arrayCell(mnemonic[5], 6),
|
||||
arrayCell(mnemonic[6], 7),
|
||||
arrayCell(mnemonic[7], 8),
|
||||
]),
|
||||
const SizedBox(height: 15),
|
||||
Row(children: <Widget>[
|
||||
arrayCell(_mnemonic[8], 9),
|
||||
arrayCell(_mnemonic[9], 10),
|
||||
arrayCell(_mnemonic[10], 11),
|
||||
arrayCell(_mnemonic[11], 12),
|
||||
arrayCell(mnemonic[8], 9),
|
||||
arrayCell(mnemonic[9], 10),
|
||||
arrayCell(mnemonic[10], 11),
|
||||
arrayCell(mnemonic[11], 12),
|
||||
]),
|
||||
])),
|
||||
);
|
||||
|
@ -211,7 +205,7 @@ class ShowSeed extends StatelessWidget {
|
|||
),
|
||||
Text(
|
||||
dataWord,
|
||||
key: Key('word$dataWord'),
|
||||
key: keyMnemonicWord(dataWord),
|
||||
style: TextStyle(fontSize: 17 * ratio, color: Colors.black),
|
||||
),
|
||||
]),
|
||||
|
@ -237,11 +231,11 @@ class PrintWallet extends StatelessWidget {
|
|||
backgroundColor: yellowC,
|
||||
foregroundColor: Colors.black,
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text(
|
||||
'Imprimer ma phrase de restauration',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
'printMyMnemonic'.tr(),
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -254,26 +248,26 @@ class PrintWallet extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
Future<Uint8List> printWallet(String _seed) async {
|
||||
Future<Uint8List> printWallet(String seed) async {
|
||||
final ByteData fontData =
|
||||
await rootBundle.load("assets/OpenSans-Regular.ttf");
|
||||
final pw.Font ttf = pw.Font.ttf(fontData.buffer.asByteData());
|
||||
final pdf = pw.Document();
|
||||
int nbr = 1;
|
||||
|
||||
final _seedList = _seed.split(' ');
|
||||
final seedList = seed.split(' ');
|
||||
|
||||
// const imageProvider = AssetImage('assets/icon/gecko_final.png');
|
||||
// final geckoLogo = await flutterImageProvider(imageProvider);
|
||||
|
||||
pw.Widget arrayCell(String dataWord, int _nbr) {
|
||||
pw.Widget arrayCell(String dataWord, int nbr) {
|
||||
nbr++;
|
||||
|
||||
return pw.SizedBox(
|
||||
width: 120,
|
||||
child: pw.Column(children: <pw.Widget>[
|
||||
pw.Text(
|
||||
_nbr.toString(),
|
||||
nbr.toString(),
|
||||
style: pw.TextStyle(
|
||||
fontSize: 15, color: const PdfColor(0.5, 0, 0), font: ttf),
|
||||
),
|
||||
|
@ -297,22 +291,22 @@ class PrintWallet extends StatelessWidget {
|
|||
// crossAxisAlignment: pw.CrossAxisAlignment.center,
|
||||
children: <pw.Widget>[
|
||||
pw.Row(children: <pw.Widget>[
|
||||
arrayCell(_seedList[0], nbr),
|
||||
arrayCell(_seedList[1], nbr),
|
||||
arrayCell(_seedList[2], nbr),
|
||||
arrayCell(_seedList[3], nbr),
|
||||
arrayCell(seedList[0], nbr),
|
||||
arrayCell(seedList[1], nbr),
|
||||
arrayCell(seedList[2], nbr),
|
||||
arrayCell(seedList[3], nbr),
|
||||
]),
|
||||
pw.Row(children: <pw.Widget>[
|
||||
arrayCell(_seedList[4], nbr),
|
||||
arrayCell(_seedList[5], nbr),
|
||||
arrayCell(_seedList[6], nbr),
|
||||
arrayCell(_seedList[7], nbr),
|
||||
arrayCell(seedList[4], nbr),
|
||||
arrayCell(seedList[5], nbr),
|
||||
arrayCell(seedList[6], nbr),
|
||||
arrayCell(seedList[7], nbr),
|
||||
]),
|
||||
pw.Row(children: <pw.Widget>[
|
||||
arrayCell(_seedList[8], nbr),
|
||||
arrayCell(_seedList[9], nbr),
|
||||
arrayCell(_seedList[10], nbr),
|
||||
arrayCell(_seedList[11], nbr)
|
||||
arrayCell(seedList[8], nbr),
|
||||
arrayCell(seedList[9], nbr),
|
||||
arrayCell(seedList[10], nbr),
|
||||
arrayCell(seedList[11], nbr)
|
||||
]),
|
||||
pw.Expanded(
|
||||
child: pw.Align(
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:gecko/globals.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
// import 'package:gecko/models/home.dart';
|
||||
// import 'package:provider/provider.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class TransactionCommentScreen extends StatelessWidget {
|
||||
TextEditingController tplController = TextEditingController();
|
||||
|
||||
TransactionCommentScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
// HomeProvider _homeProvider = Provider.of<HomeProvider>(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
height: 22,
|
||||
child: Text('Confirmer le paiement'),
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Column(children: <Widget>[
|
||||
const SizedBox(height: 20),
|
||||
TextField(
|
||||
enabled: true,
|
||||
controller: tplController,
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.center,
|
||||
decoration: const InputDecoration(
|
||||
contentPadding: EdgeInsets.all(15.0),
|
||||
),
|
||||
style: const TextStyle(
|
||||
fontSize: 22.0,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w400)),
|
||||
const SizedBox(height: 20),
|
||||
]),
|
||||
));
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
// ignore_for_file: avoid_print
|
||||
// ignore_for_file: must_be_immutable
|
||||
|
||||
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';
|
||||
import 'package:gecko/providers/my_wallets.dart';
|
||||
import 'package:gecko/models/wallet_data.dart';
|
||||
|
@ -13,31 +16,29 @@ import 'package:pin_code_fields/pin_code_fields.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
import 'package:gecko/globals.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class UnlockingWallet extends StatelessWidget {
|
||||
UnlockingWallet({Key? keyUnlockWallet, required this.wallet})
|
||||
: super(key: keyUnlockWallet);
|
||||
WalletData? wallet;
|
||||
UnlockingWallet({required this.wallet}) : super(key: keyUnlockWallet);
|
||||
WalletData wallet;
|
||||
late int currentChestNumber;
|
||||
late ChestData currentChest;
|
||||
bool canUnlock = true;
|
||||
|
||||
// ignore: close_sinks
|
||||
StreamController<ErrorAnimationType>? errorController;
|
||||
final formKey = GlobalKey<FormState>();
|
||||
Color? pinColor = const Color(0xffF9F9F1);
|
||||
var walletPin = '';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
WalletOptionsProvider _walletOptions =
|
||||
WalletOptionsProvider walletOptions =
|
||||
Provider.of<WalletOptionsProvider>(context);
|
||||
// final double statusBarHeight = MediaQuery.of(context).padding.top;
|
||||
|
||||
currentChestNumber = configBox.get('currentChest');
|
||||
currentChest = chestBox.get(currentChestNumber)!;
|
||||
|
||||
int _pinLenght = _walletOptions.getPinLenght(wallet!.number);
|
||||
int pinLenght = walletOptions.getPinLenght(wallet.number);
|
||||
errorController = StreamController<ErrorAnimationType>();
|
||||
|
||||
return Scaffold(
|
||||
|
@ -52,7 +53,7 @@ class UnlockingWallet extends StatelessWidget {
|
|||
left: 15,
|
||||
child: Builder(
|
||||
builder: (context) => IconButton(
|
||||
key: const Key('popButton'),
|
||||
key: keyPopButton,
|
||||
icon: const Icon(
|
||||
Icons.arrow_back,
|
||||
color: Colors.black,
|
||||
|
@ -89,43 +90,46 @@ class UnlockingWallet extends StatelessWidget {
|
|||
)),
|
||||
]),
|
||||
SizedBox(height: 30 * ratio),
|
||||
const SizedBox(
|
||||
SizedBox(
|
||||
width: 400,
|
||||
child: Text(
|
||||
'Pour déverrouiller votre coffre, composez votre code secret à l’abri des lézards indiscrets :',
|
||||
style: TextStyle(
|
||||
'toUnlockEnterPassword'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 19,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w400),
|
||||
)),
|
||||
SizedBox(height: 40 * ratio),
|
||||
pinForm(context, _pinLenght),
|
||||
pinForm(context, pinLenght),
|
||||
SizedBox(height: 3 * ratio),
|
||||
InkWell(
|
||||
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(
|
||||
'Garder ce code en mémoire 15 minutes',
|
||||
style:
|
||||
TextStyle(fontSize: 16, color: Colors.grey[700]),
|
||||
),
|
||||
const Spacer()
|
||||
]),
|
||||
),
|
||||
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: const Key('chooseChest'),
|
||||
key: keyChangeChest,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
|
@ -139,8 +143,8 @@ class UnlockingWallet extends StatelessWidget {
|
|||
height: 50,
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Changer de coffre',
|
||||
style: TextStyle(
|
||||
'changeChest'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 22,
|
||||
color: orangeC,
|
||||
fontWeight: FontWeight.w600),
|
||||
|
@ -153,27 +157,38 @@ class UnlockingWallet extends StatelessWidget {
|
|||
));
|
||||
}
|
||||
|
||||
Widget pinForm(context, _pinLenght) {
|
||||
Widget pinForm(context, pinLenght) {
|
||||
// var _walletPin = '';
|
||||
// ignore: close_sinks
|
||||
StreamController<ErrorAnimationType> errorController =
|
||||
StreamController<ErrorAnimationType>();
|
||||
TextEditingController _enterPin = TextEditingController();
|
||||
WalletOptionsProvider _walletOptions =
|
||||
TextEditingController enterPin = TextEditingController();
|
||||
WalletOptionsProvider walletOptions =
|
||||
Provider.of<WalletOptionsProvider>(context);
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context);
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
WalletData? defaultWallet = _myWalletProvider.getDefaultWallet();
|
||||
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
FocusNode pinFocus = FocusNode();
|
||||
|
||||
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),
|
||||
);
|
||||
}
|
||||
|
||||
return Form(
|
||||
key: formKey,
|
||||
// key: keyPinForm,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 5 * ratio, horizontal: 30),
|
||||
child: PinCodeTextField(
|
||||
key: keyPinForm,
|
||||
focusNode: pinFocus,
|
||||
autoFocus: true,
|
||||
appContext: context,
|
||||
|
@ -181,13 +196,13 @@ class UnlockingWallet extends StatelessWidget {
|
|||
color: Colors.green.shade600,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
length: _pinLenght,
|
||||
length: pinLenght,
|
||||
obscureText: true,
|
||||
obscuringCharacter: '*',
|
||||
animationType: AnimationType.fade,
|
||||
validator: (v) {
|
||||
if (v!.length < _pinLenght) {
|
||||
return "Votre code PIN fait $_pinLenght caractères";
|
||||
if (v!.length < pinLenght) {
|
||||
return "yourPasswordLengthIsX".tr(args: [pinLenght.toString()]);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -201,13 +216,14 @@ class UnlockingWallet extends StatelessWidget {
|
|||
fieldWidth: 50,
|
||||
activeFillColor: Colors.black,
|
||||
),
|
||||
showCursor: kDebugMode ? false : true,
|
||||
cursorColor: Colors.black,
|
||||
animationDuration: const Duration(milliseconds: 300),
|
||||
textStyle: const TextStyle(fontSize: 20, height: 1.6),
|
||||
backgroundColor: const Color(0xffF9F9F1),
|
||||
enableActiveFill: false,
|
||||
errorAnimationController: errorController,
|
||||
controller: _enterPin,
|
||||
controller: enterPin,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
boxShadows: const [
|
||||
BoxShadow(
|
||||
|
@ -216,23 +232,23 @@ class UnlockingWallet extends StatelessWidget {
|
|||
blurRadius: 10,
|
||||
)
|
||||
],
|
||||
onCompleted: (_pin) async {
|
||||
_myWalletProvider.pinCode = _pin.toUpperCase();
|
||||
final isValid = await _sub.checkPassword(
|
||||
defaultWallet.address!, _pin.toUpperCase());
|
||||
onCompleted: (pin) async {
|
||||
myWalletProvider.pinCode = pin.toUpperCase();
|
||||
final isValid = await sub.checkPassword(
|
||||
defaultWallet.address!, pin.toUpperCase());
|
||||
|
||||
if (!isValid) {
|
||||
await Future.delayed(const Duration(milliseconds: 50));
|
||||
errorController.add(ErrorAnimationType
|
||||
.shake); // Triggering error shake animation
|
||||
pinColor = Colors.red[600];
|
||||
_myWalletProvider.pinCode = _myWalletProvider.mnemonic = '';
|
||||
_walletOptions.reloadBuild();
|
||||
myWalletProvider.pinCode = myWalletProvider.mnemonic = '';
|
||||
walletOptions.reload();
|
||||
pinFocus.requestFocus();
|
||||
} else {
|
||||
pinColor = Colors.green[400];
|
||||
_myWalletProvider.resetPinCode();
|
||||
Navigator.pop(context, _pin.toUpperCase());
|
||||
myWalletProvider.resetPinCode();
|
||||
Navigator.pop(context, pin.toUpperCase());
|
||||
}
|
||||
},
|
||||
onChanged: (value) {
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.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/activity.dart';
|
||||
import 'package:gecko/screens/myWallets/manage_membership.dart';
|
||||
import 'package:gecko/screens/qrcode_fullscreen.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
@ -22,28 +27,34 @@ class WalletOptions extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
WalletOptionsProvider _walletOptions =
|
||||
WalletOptionsProvider walletOptions =
|
||||
Provider.of<WalletOptionsProvider>(context, listen: false);
|
||||
WalletsProfilesProvider _historyProvider =
|
||||
WalletsProfilesProvider historyProvider =
|
||||
Provider.of<WalletsProfilesProvider>(context, listen: false);
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
HomeProvider _homeProvider =
|
||||
HomeProvider homeProvider =
|
||||
Provider.of<HomeProvider>(context, listen: false);
|
||||
DuniterIndexer duniterIndexer =
|
||||
Provider.of<DuniterIndexer>(context, listen: false);
|
||||
|
||||
log.d(_walletOptions.address.text);
|
||||
// SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
// sub.spawnBlock();
|
||||
// sub.spawnBlock(0, 20);
|
||||
|
||||
final int _currentChest = _myWalletProvider.getCurrentChest();
|
||||
log.d(walletOptions.address.text);
|
||||
|
||||
final int currentChest = myWalletProvider.getCurrentChest();
|
||||
|
||||
// final currentWallet = _myWalletProvider.getDefaultWallet();
|
||||
// log.d(_walletOptions.getAddress(_currentChest, 3));
|
||||
log.d("Wallet options: $_currentChest:${wallet.derivation}");
|
||||
log.d("Wallet options: $currentChest:${wallet.derivation}");
|
||||
|
||||
return WillPopScope(
|
||||
onWillPop: () {
|
||||
_walletOptions.isEditing = false;
|
||||
_walletOptions.isBalanceBlur = false;
|
||||
_myWalletProvider.rebuildWidget();
|
||||
walletOptions.isEditing = false;
|
||||
walletOptions.isBalanceBlur = false;
|
||||
myWalletProvider.reload();
|
||||
Navigator.pop(context);
|
||||
return Future<bool>.value(true);
|
||||
},
|
||||
|
@ -56,9 +67,9 @@ class WalletOptions extends StatelessWidget {
|
|||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back, color: Colors.black),
|
||||
onPressed: () {
|
||||
_walletOptions.isEditing = false;
|
||||
_walletOptions.isBalanceBlur = false;
|
||||
_myWalletProvider.rebuildWidget();
|
||||
walletOptions.isEditing = false;
|
||||
walletOptions.isBalanceBlur = false;
|
||||
myWalletProvider.reload();
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
title: SizedBox(
|
||||
|
@ -68,124 +79,158 @@ class WalletOptions extends StatelessWidget {
|
|||
return Text(wallet.name!);
|
||||
}),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: _homeProvider.bottomAppBar(context),
|
||||
body: Builder(
|
||||
builder: (ctx) => SafeArea(
|
||||
child: Column(children: <Widget>[
|
||||
Container(
|
||||
height: isTall ? 5 : 0,
|
||||
color: yellowC,
|
||||
),
|
||||
Consumer<WalletOptionsProvider>(
|
||||
builder: (context, walletProvider, _) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
yellowC,
|
||||
backgroundColor,
|
||||
],
|
||||
)),
|
||||
child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: <Widget>[
|
||||
const Spacer(flex: 1),
|
||||
avatar(walletProvider),
|
||||
const Spacer(flex: 1),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
walletName(walletProvider, _walletOptions),
|
||||
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),
|
||||
]),
|
||||
actions: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return QrCodeFullscreen(
|
||||
walletOptions.address.text,
|
||||
);
|
||||
}),
|
||||
);
|
||||
}),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return QrCodeFullscreen(
|
||||
_walletOptions.address.text,
|
||||
);
|
||||
}),
|
||||
);
|
||||
},
|
||||
child: QrImageWidget(
|
||||
data: _walletOptions.address.text,
|
||||
version: QrVersions.auto,
|
||||
size: isTall ? 150 : 80,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 15 * ratio),
|
||||
Consumer<WalletOptionsProvider>(
|
||||
builder: (context, walletProvider, _) {
|
||||
return Column(children: [
|
||||
pubkeyWidget(walletProvider, ctx),
|
||||
SizedBox(height: 10 * ratio),
|
||||
historyWidget(
|
||||
context, _historyProvider, walletProvider),
|
||||
SizedBox(height: 12 * ratio),
|
||||
setDefaultWalletWidget(
|
||||
context,
|
||||
walletProvider,
|
||||
_myWalletProvider,
|
||||
_walletOptions,
|
||||
_currentChest),
|
||||
SizedBox(height: 17 * ratio),
|
||||
// walletProvider.isMember(context, _walletOptions.address.text)
|
||||
FutureBuilder(
|
||||
future: walletProvider.isMember(
|
||||
context, _walletOptions.address.text),
|
||||
builder: (BuildContext context,
|
||||
AsyncSnapshot<bool> _isMember) {
|
||||
if (_isMember.connectionState !=
|
||||
ConnectionState.done ||
|
||||
_isMember.hasError) {
|
||||
return const Text('');
|
||||
}
|
||||
return Column(children: [
|
||||
if (!walletProvider.isDefaultWallet &&
|
||||
!_isMember.data!)
|
||||
deleteWallet(context, walletProvider,
|
||||
_currentChest)
|
||||
else
|
||||
const SizedBox(),
|
||||
if (_isMember.data!)
|
||||
manageMemberStatus(context)
|
||||
]);
|
||||
}),
|
||||
]);
|
||||
}),
|
||||
]),
|
||||
),
|
||||
},
|
||||
child: QrImageWidget(
|
||||
data: walletOptions.address.text,
|
||||
version: QrVersions.auto,
|
||||
size: 80,
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
bottomNavigationBar: homeProvider.bottomAppBar(context),
|
||||
body: Stack(children: [
|
||||
Builder(
|
||||
builder: (ctx) => SafeArea(
|
||||
child: Column(children: <Widget>[
|
||||
Container(
|
||||
height: isTall ? 5 : 0,
|
||||
color: yellowC,
|
||||
),
|
||||
Consumer<WalletOptionsProvider>(
|
||||
builder: (context, walletProvider, _) {
|
||||
return Container(
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
yellowC,
|
||||
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),
|
||||
]),
|
||||
);
|
||||
}),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
// InkWell(
|
||||
// onTap: () {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(builder: (context) {
|
||||
// return QrCodeFullscreen(
|
||||
// _walletOptions.address.text,
|
||||
// );
|
||||
// }),
|
||||
// );
|
||||
// },
|
||||
// child: QrImageWidget(
|
||||
// data: _walletOptions.address.text,
|
||||
// version: QrVersions.auto,
|
||||
// size: isTall ? 150 : 80,
|
||||
// ),
|
||||
// ),
|
||||
SizedBox(height: 30 * ratio),
|
||||
Consumer<WalletOptionsProvider>(
|
||||
builder: (context, walletProvider, _) {
|
||||
return Column(children: [
|
||||
confirmIdentityButton(walletProvider),
|
||||
pubkeyWidget(walletProvider, ctx),
|
||||
SizedBox(height: 10 * ratio),
|
||||
activityWidget(
|
||||
context, historyProvider, walletProvider),
|
||||
SizedBox(height: 12 * ratio),
|
||||
setDefaultWalletWidget(
|
||||
context,
|
||||
walletProvider,
|
||||
myWalletProvider,
|
||||
walletOptions,
|
||||
currentChest),
|
||||
SizedBox(height: 17 * ratio),
|
||||
// walletProvider.isMember(context, _walletOptions.address.text)
|
||||
FutureBuilder(
|
||||
future: walletProvider.isMember(
|
||||
context, walletOptions.address.text),
|
||||
builder: (BuildContext context,
|
||||
AsyncSnapshot<bool> isMember) {
|
||||
if (isMember.connectionState !=
|
||||
ConnectionState.done ||
|
||||
isMember.hasError) {
|
||||
return const Text('');
|
||||
}
|
||||
return Column(children: [
|
||||
if (!walletProvider.isDefaultWallet &&
|
||||
!isMember.data!)
|
||||
deleteWallet(context, walletProvider,
|
||||
currentChest)
|
||||
else
|
||||
const SizedBox(),
|
||||
if (isMember.data!)
|
||||
manageMembership(context)
|
||||
]);
|
||||
}),
|
||||
]);
|
||||
}),
|
||||
]),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
CommonElements().offlineInfo(context),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -195,12 +240,12 @@ class WalletOptions extends StatelessWidget {
|
|||
children: <Widget>[
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
final _newPath = await (walletProvider.changeAvatar());
|
||||
if (_newPath != '') {
|
||||
wallet.imageCustomPath = _newPath;
|
||||
final newPath = await (walletProvider.changeAvatar());
|
||||
if (newPath != '') {
|
||||
wallet.imageCustomPath = newPath;
|
||||
walletBox.put(wallet.key, wallet);
|
||||
}
|
||||
walletProvider.reloadBuild();
|
||||
walletProvider.reload();
|
||||
},
|
||||
child: wallet.imageCustomPath == null || wallet.imageCustomPath == ''
|
||||
? Image.asset(
|
||||
|
@ -228,7 +273,7 @@ class WalletOptions extends StatelessWidget {
|
|||
child: InkWell(
|
||||
onTap: () async {
|
||||
wallet.imageCustomPath = await (walletProvider.changeAvatar());
|
||||
walletProvider.reloadBuild();
|
||||
walletProvider.reload();
|
||||
},
|
||||
child: Image.asset(
|
||||
'assets/walletOptions/camera.png',
|
||||
|
@ -240,66 +285,61 @@ class WalletOptions extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
Widget walletName(WalletOptionsProvider walletProvider,
|
||||
WalletOptionsProvider _walletOptions) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_walletOptions.nameController.text = wallet.name!;
|
||||
// _walletOptions.reloadBuild();
|
||||
Widget confirmIdentityButton(WalletOptionsProvider walletProvider) {
|
||||
return Consumer<SubstrateSdk>(builder: (context, sub, _) {
|
||||
return FutureBuilder(
|
||||
future: sub.idtyStatus(walletProvider.address.text),
|
||||
initialData: '',
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.data == 'Created') {
|
||||
return Column(children: [
|
||||
SizedBox(
|
||||
width: 320,
|
||||
height: 60,
|
||||
child: ElevatedButton(
|
||||
key: keyConfirmIdentity,
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white, elevation: 4,
|
||||
backgroundColor: orangeC, // foreground
|
||||
),
|
||||
onPressed: () {
|
||||
walletProvider.confirmIdentityPopup(context);
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(builder: (context) {
|
||||
// return const SearchResultScreen();
|
||||
// }),
|
||||
// );
|
||||
},
|
||||
child: Text(
|
||||
'confirmMyIdentity'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 21, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 7),
|
||||
Text(
|
||||
"someoneCreatedYourIdentity".tr(args: [currencyName]),
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.grey[600],
|
||||
fontStyle: FontStyle.italic,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 40),
|
||||
]);
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return SizedBox(
|
||||
width: 260,
|
||||
child: Stack(children: <Widget>[
|
||||
TextField(
|
||||
key: const Key('walletName'),
|
||||
autofocus: false,
|
||||
focusNode: walletProvider.walletNameFocus,
|
||||
enabled: walletProvider.isEditing,
|
||||
controller: walletProvider.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 ? 27 : 23,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 0,
|
||||
child: InkWell(
|
||||
key: const Key('renameWallet'),
|
||||
onTap: () async {
|
||||
// _isNewNameValid =
|
||||
walletProvider.editWalletName(wallet.id(), isCesium: false);
|
||||
await Future.delayed(const Duration(milliseconds: 30));
|
||||
walletProvider.walletNameFocus.requestFocus();
|
||||
},
|
||||
child: ClipRRect(
|
||||
child: Image.asset(
|
||||
walletProvider.isEditing
|
||||
? 'assets/walletOptions/android-checkmark.png'
|
||||
: 'assets/walletOptions/edit.png',
|
||||
width: 25,
|
||||
height: 25),
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
Widget pubkeyWidget(WalletOptionsProvider walletProvider, BuildContext ctx) {
|
||||
final String shortPubkey = getShortPubkey(walletProvider.address.text);
|
||||
return GestureDetector(
|
||||
key: const Key('copyPubkey'),
|
||||
key: keyCopyAddress,
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: walletProvider.address.text));
|
||||
snackCopyKey(ctx);
|
||||
|
@ -324,12 +364,12 @@ class WalletOptions extends StatelessWidget {
|
|||
height: 40,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.black,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
elevation: 1,
|
||||
primary: orangeC, // background
|
||||
onPrimary: Colors.black, // foreground
|
||||
backgroundColor: orangeC,
|
||||
elevation: 1, // foreground
|
||||
),
|
||||
onPressed: () {
|
||||
Clipboard.setData(
|
||||
|
@ -343,7 +383,7 @@ class WalletOptions extends StatelessWidget {
|
|||
),
|
||||
const SizedBox(width: 7),
|
||||
Text(
|
||||
'Copier',
|
||||
'copy'.tr(),
|
||||
style: TextStyle(fontSize: 15, color: Colors.grey[50]),
|
||||
)
|
||||
]),
|
||||
|
@ -354,30 +394,30 @@ class WalletOptions extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
Widget historyWidget(
|
||||
Widget activityWidget(
|
||||
BuildContext context,
|
||||
WalletsProfilesProvider _historyProvider,
|
||||
WalletsProfilesProvider historyProvider,
|
||||
WalletOptionsProvider walletProvider) {
|
||||
return InkWell(
|
||||
key: const Key('displayHistory'),
|
||||
key: keyOpenActivity,
|
||||
onTap: () {
|
||||
_historyProvider.nPage = 1;
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(builder: (context) {
|
||||
// return HistoryScreen(
|
||||
// pubkey: walletProvider.address.text,
|
||||
// avatar: wallet.imageCustomPath == null
|
||||
// ? Image.asset(
|
||||
// 'assets/avatars/${wallet.imageDefaultPath}',
|
||||
// width: 110,
|
||||
// )
|
||||
// : Image.asset(
|
||||
// wallet.imageCustomPath!,
|
||||
// width: 110,
|
||||
// ));
|
||||
// }),
|
||||
// );
|
||||
// _historyProvider.nPage = 1;
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return ActivityScreen(
|
||||
address: walletProvider.address.text,
|
||||
avatar: wallet.imageCustomPath == null
|
||||
? Image.asset(
|
||||
'assets/avatars/${wallet.imageDefaultPath}',
|
||||
width: 110,
|
||||
)
|
||||
: Image.asset(
|
||||
wallet.imageCustomPath!,
|
||||
width: 110,
|
||||
));
|
||||
}),
|
||||
);
|
||||
},
|
||||
child: SizedBox(
|
||||
height: 50,
|
||||
|
@ -388,24 +428,25 @@ class WalletOptions extends StatelessWidget {
|
|||
height: 45,
|
||||
),
|
||||
const SizedBox(width: 22),
|
||||
Text('Historique des transactions',
|
||||
style: TextStyle(fontSize: 20, color: Colors.grey[500])),
|
||||
Text("displayActivity".tr(),
|
||||
style:
|
||||
const TextStyle(fontSize: 20, fontWeight: FontWeight.w500)),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget manageMemberStatus(BuildContext context) {
|
||||
WalletOptionsProvider _walletOptions =
|
||||
Widget manageMembership(BuildContext context) {
|
||||
WalletOptionsProvider walletOptions =
|
||||
Provider.of<WalletOptionsProvider>(context, listen: false);
|
||||
return InkWell(
|
||||
key: const Key('manageStatus'),
|
||||
key: keyManageMembership,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return ManageMembership(
|
||||
address: _walletOptions.address.text,
|
||||
address: walletOptions.address.text,
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
@ -419,7 +460,7 @@ class WalletOptions extends StatelessWidget {
|
|||
height: 45,
|
||||
),
|
||||
const SizedBox(width: 22),
|
||||
const Text('Gérer mon adhésion', style: TextStyle(fontSize: 20)),
|
||||
Text('manageMembership'.tr(), style: const TextStyle(fontSize: 20)),
|
||||
]),
|
||||
),
|
||||
);
|
||||
|
@ -428,18 +469,17 @@ class WalletOptions extends StatelessWidget {
|
|||
Widget setDefaultWalletWidget(
|
||||
BuildContext context,
|
||||
WalletOptionsProvider walletProvider,
|
||||
MyWalletsProvider _myWalletProvider,
|
||||
WalletOptionsProvider _walletOptions,
|
||||
int _currentChest) {
|
||||
return Consumer<MyWalletsProvider>(
|
||||
builder: (context, _myWalletProvider, _) {
|
||||
WalletData defaultWallet = _myWalletProvider.getDefaultWallet();
|
||||
_walletOptions.isDefaultWallet = (defaultWallet.number == wallet.id()[1]);
|
||||
MyWalletsProvider myWalletProvider,
|
||||
WalletOptionsProvider walletOptions,
|
||||
int currentChest) {
|
||||
return Consumer<MyWalletsProvider>(builder: (context, myWalletProvider, _) {
|
||||
WalletData defaultWallet = myWalletProvider.getDefaultWallet();
|
||||
walletOptions.isDefaultWallet = (defaultWallet.number == wallet.id()[1]);
|
||||
return InkWell(
|
||||
key: const Key('setDefaultWallet'),
|
||||
key: keySetDefaultWallet,
|
||||
onTap: !walletProvider.isDefaultWallet
|
||||
? () async {
|
||||
await setDefaultWallet(context, _currentChest);
|
||||
await setDefaultWallet(context, currentChest);
|
||||
}
|
||||
: null,
|
||||
child: SizedBox(
|
||||
|
@ -457,8 +497,8 @@ class WalletOptions extends StatelessWidget {
|
|||
const SizedBox(width: 22),
|
||||
Text(
|
||||
walletProvider.isDefaultWallet
|
||||
? 'Ce portefeuille est celui par defaut'
|
||||
: 'Définir comme portefeuille par défaut',
|
||||
? 'thisWalletIsDefault'.tr()
|
||||
: 'defineWalletAsDefault'.tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: walletProvider.isDefaultWallet
|
||||
|
@ -470,49 +510,53 @@ class WalletOptions extends StatelessWidget {
|
|||
});
|
||||
}
|
||||
|
||||
Future setDefaultWallet(BuildContext context, int _currentChest) async {
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
Future setDefaultWallet(BuildContext context, int currentChest) async {
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
WalletOptionsProvider walletOptions =
|
||||
Provider.of<WalletOptionsProvider>(context, listen: false);
|
||||
|
||||
// WalletData defaultWallet = _myWalletProvider.getDefaultWallet()!;
|
||||
// defaultWallet = wallet;
|
||||
await _sub.setCurrentWallet(wallet);
|
||||
_myWalletProvider.readAllWallets(_currentChest);
|
||||
_myWalletProvider.rebuildWidget();
|
||||
await sub.setCurrentWallet(wallet);
|
||||
myWalletProvider.readAllWallets(currentChest);
|
||||
myWalletProvider.reload();
|
||||
walletOptions.reload();
|
||||
}
|
||||
|
||||
Widget deleteWallet(BuildContext context,
|
||||
WalletOptionsProvider walletProvider, int _currentChest) {
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
WalletOptionsProvider walletProvider, int currentChest) {
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
|
||||
final _defaultWallet = _myWalletProvider.getDefaultWallet();
|
||||
final defaultWallet = myWalletProvider.getDefaultWallet();
|
||||
final bool isDefaultWallet =
|
||||
walletProvider.address.text == _defaultWallet.address;
|
||||
walletProvider.address.text == defaultWallet.address;
|
||||
// return Consumer<MyWalletsProvider>(
|
||||
// builder: (context, _myWalletProvider, _) {
|
||||
return FutureBuilder(
|
||||
future: _sub.hasAccountConsumers(wallet.address!),
|
||||
builder: (BuildContext context, AsyncSnapshot<bool> _hasConsumers) {
|
||||
if (_hasConsumers.connectionState != ConnectionState.done ||
|
||||
_hasConsumers.hasError) {
|
||||
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]!;
|
||||
final double balance =
|
||||
balanceCache[walletProvider.address.text] ?? -1;
|
||||
final bool canDelete = !isDefaultWallet &&
|
||||
!_hasConsumers.data! &&
|
||||
(_balance > 2 || _balance == 0);
|
||||
!hasConsumers.data! &&
|
||||
(balance > 2 || balance == 0);
|
||||
return InkWell(
|
||||
key: const Key('deleteWallet'),
|
||||
key: keyDeleteWallet,
|
||||
onTap: canDelete
|
||||
? () async {
|
||||
await walletProvider.deleteWallet(context, wallet);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_myWalletProvider.listWallets =
|
||||
_myWalletProvider.readAllWallets(_currentChest);
|
||||
_myWalletProvider.rebuildWidget();
|
||||
myWalletProvider.listWallets =
|
||||
myWalletProvider.readAllWallets(currentChest);
|
||||
myWalletProvider.reload();
|
||||
});
|
||||
}
|
||||
: null,
|
||||
|
@ -524,9 +568,9 @@ class WalletOptions extends StatelessWidget {
|
|||
height: 45,
|
||||
),
|
||||
const SizedBox(width: 19),
|
||||
const Text('Supprimer ce portefeuille',
|
||||
style:
|
||||
TextStyle(fontSize: 20, color: Color(0xffD80000))),
|
||||
Text('deleteThisWallet'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 20, color: Color(0xffD80000))),
|
||||
])
|
||||
: const SizedBox(width: 30),
|
||||
);
|
||||
|
|
|
@ -1,18 +1,27 @@
|
|||
// 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:provider/provider.dart';
|
||||
|
||||
class WalletsHome extends StatelessWidget {
|
||||
|
@ -23,17 +32,16 @@ class WalletsHome extends StatelessWidget {
|
|||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context);
|
||||
HomeProvider _homeProvider =
|
||||
HomeProvider homeProvider =
|
||||
Provider.of<HomeProvider>(context, listen: false);
|
||||
|
||||
final int? _currentChestNumber = myWalletProvider.getCurrentChest();
|
||||
final ChestData _currentChest = chestBox.get(_currentChestNumber)!;
|
||||
final int currentChestNumber = myWalletProvider.getCurrentChest();
|
||||
final ChestData currentChest = chestBox.get(currentChestNumber)!;
|
||||
myWalletProvider.listWallets =
|
||||
myWalletProvider.readAllWallets(_currentChestNumber);
|
||||
myWalletProvider.readAllWallets(currentChestNumber);
|
||||
|
||||
return WillPopScope(
|
||||
onWillPop: () {
|
||||
// myWalletProvider.pinCode = myWalletProvider.mnemonic = '';
|
||||
Navigator.popUntil(
|
||||
context,
|
||||
ModalRoute.withName('/'),
|
||||
|
@ -48,31 +56,65 @@ class WalletsHome extends StatelessWidget {
|
|||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back, color: Colors.black),
|
||||
onPressed: () {
|
||||
// myWalletProvider.pinCode = myWalletProvider.mnemonic = '';
|
||||
Navigator.popUntil(
|
||||
context,
|
||||
ModalRoute.withName('/'),
|
||||
);
|
||||
}),
|
||||
title: Text(_currentChest.name!,
|
||||
key: const Key('myWallets'),
|
||||
title: Text(currentChest.name!,
|
||||
style: TextStyle(color: Colors.grey[850])),
|
||||
backgroundColor: const Color(0xffFFD58D),
|
||||
),
|
||||
bottomNavigationBar: _homeProvider.bottomAppBar(context),
|
||||
bottomNavigationBar: myWalletProvider.lastFlyBy == ''
|
||||
? homeProvider.bottomAppBar(context)
|
||||
: dragInfo(context),
|
||||
body: SafeArea(
|
||||
child: myWalletsTiles(context, _currentChestNumber!),
|
||||
child: Stack(children: [
|
||||
myWalletsTiles(context, currentChestNumber),
|
||||
CommonElements().offlineInfo(context),
|
||||
]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget dragInfo(BuildContext context) {
|
||||
final myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
|
||||
final walletDataFrom =
|
||||
myWalletProvider.getWalletDataByAddress(myWalletProvider.dragAddress);
|
||||
final walletDataTo =
|
||||
myWalletProvider.getWalletDataByAddress(myWalletProvider.lastFlyBy);
|
||||
|
||||
final bool isSameAddress =
|
||||
myWalletProvider.dragAddress == myWalletProvider.lastFlyBy;
|
||||
|
||||
final double screenWidth = MediaQuery.of(homeContext).size.width;
|
||||
return Container(
|
||||
color: yellowC,
|
||||
width: screenWidth,
|
||||
height: 80,
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 5),
|
||||
Text('${'executeATransfer'.tr()}:'),
|
||||
MarkdownBody(data: '${'from'.tr()} **${walletDataFrom!.name}**'),
|
||||
if (isSameAddress) Text('chooseATargetWallet'.tr()),
|
||||
if (!isSameAddress)
|
||||
MarkdownBody(data: 'Vers: **${walletDataTo!.name}**'),
|
||||
],
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
Widget chestOptions(
|
||||
BuildContext context, MyWalletsProvider _myWalletProvider) {
|
||||
BuildContext context, MyWalletsProvider myWalletProvider) {
|
||||
return Column(children: [
|
||||
const SizedBox(height: 50),
|
||||
SizedBox(
|
||||
height: 90,
|
||||
height: 80,
|
||||
width: 420,
|
||||
child: ElevatedButton.icon(
|
||||
icon: Image.asset(
|
||||
|
@ -80,19 +122,18 @@ class WalletsHome extends StatelessWidget {
|
|||
height: 60,
|
||||
),
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 2,
|
||||
primary: floattingYellow, // background
|
||||
onPrimary: Colors.black, // foreground
|
||||
foregroundColor: Colors.black, elevation: 2,
|
||||
backgroundColor: floattingYellow, // foreground
|
||||
),
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return ChestOptions(walletProvider: _myWalletProvider);
|
||||
return ChestOptions(walletProvider: myWalletProvider);
|
||||
}),
|
||||
),
|
||||
label: const Text(
|
||||
" Paramétrer ce coffre",
|
||||
style: TextStyle(
|
||||
label: Text(
|
||||
" ${"manageChest".tr()}",
|
||||
style: const TextStyle(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Color(0xff8a3c0f),
|
||||
|
@ -101,7 +142,29 @@ class WalletsHome extends StatelessWidget {
|
|||
)),
|
||||
const SizedBox(height: 30),
|
||||
InkWell(
|
||||
key: const Key('createNewChest'),
|
||||
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))),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
InkWell(
|
||||
key: keyChangeChest,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
|
@ -112,10 +175,10 @@ class WalletsHome extends StatelessWidget {
|
|||
},
|
||||
child: SizedBox(
|
||||
width: 400,
|
||||
height: 50,
|
||||
height: 60,
|
||||
child: Center(
|
||||
child: Text('Changer de coffre',
|
||||
style: TextStyle(
|
||||
child: Text('changeChest'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 22,
|
||||
color: orangeC,
|
||||
fontWeight: FontWeight.w500))),
|
||||
|
@ -125,18 +188,19 @@ class WalletsHome extends StatelessWidget {
|
|||
]);
|
||||
}
|
||||
|
||||
Widget myWalletsTiles(BuildContext context, int _currentChestNumber) {
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
Widget myWalletsTiles(BuildContext context, int currentChestNumber) {
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context);
|
||||
WalletOptionsProvider _walletOptions =
|
||||
WalletOptionsProvider walletOptions =
|
||||
Provider.of<WalletOptionsProvider>(context, listen: false);
|
||||
final bool isWalletsExists = _myWalletProvider.checkIfWalletExist();
|
||||
final bool isWalletsExists = myWalletProvider.checkIfWalletExist();
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
if (!isWalletsExists) {
|
||||
return const Text('');
|
||||
}
|
||||
|
||||
if (_myWalletProvider.listWallets.isEmpty) {
|
||||
if (myWalletProvider.listWallets.isEmpty) {
|
||||
return Expanded(
|
||||
child: Column(children: const <Widget>[
|
||||
Center(
|
||||
|
@ -147,8 +211,8 @@ class WalletsHome extends StatelessWidget {
|
|||
]));
|
||||
}
|
||||
|
||||
List _listWallets = _myWalletProvider.listWallets;
|
||||
WalletData? defaultWallet = _myWalletProvider.getDefaultWallet();
|
||||
List listWallets = myWalletProvider.listWallets;
|
||||
WalletData? defaultWallet = myWalletProvider.getDefaultWallet();
|
||||
final double screenWidth = MediaQuery.of(context).size.width;
|
||||
int nTule = 2;
|
||||
|
||||
|
@ -157,183 +221,226 @@ class WalletsHome extends StatelessWidget {
|
|||
} else if (screenWidth >= 650) {
|
||||
nTule = 3;
|
||||
}
|
||||
// Offset followDragAnchorStrategy(
|
||||
// Draggable<Object> d, BuildContext context, Offset point) {
|
||||
// return Offset(d.feedbackOffset.dx - 30, d.feedbackOffset.dy - 0);
|
||||
// }
|
||||
|
||||
return CustomScrollView(slivers: <Widget>[
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 20)),
|
||||
|
||||
SliverGrid.count(
|
||||
key: const Key('listWallets'),
|
||||
key: keyListWallets,
|
||||
crossAxisCount: nTule,
|
||||
childAspectRatio: 1,
|
||||
crossAxisSpacing: 0,
|
||||
mainAxisSpacing: 0,
|
||||
children: <Widget>[
|
||||
for (WalletData _repository in _listWallets as Iterable<WalletData>)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
// _walletOptions.readLocalWallet(context, _repository,
|
||||
// _myWalletProvider.pinCode, pinLength);
|
||||
_walletOptions.getAddress(
|
||||
_currentChestNumber, _repository.derivation!);
|
||||
Navigator.push(
|
||||
context,
|
||||
SmoothTransition(
|
||||
page: WalletOptions(
|
||||
wallet: _repository,
|
||||
for (WalletData repository in listWallets as Iterable<WalletData>)
|
||||
LongPressDraggable<String>(
|
||||
delay: const Duration(milliseconds: 200),
|
||||
data: repository.address!,
|
||||
dragAnchorStrategy:
|
||||
(Draggable<Object> _, BuildContext __, Offset ___) =>
|
||||
const Offset(0, 0),
|
||||
// feedbackOffset: const Offset(-500, -500),
|
||||
// dragAnchorStrategy: childDragAnchorStrategy,
|
||||
onDragStarted: () =>
|
||||
myWalletProvider.dragAddress = repository.address!,
|
||||
onDragEnd: (_) {
|
||||
myWalletProvider.lastFlyBy = '';
|
||||
myWalletProvider.dragAddress = '';
|
||||
myWalletProvider.reload();
|
||||
},
|
||||
feedback: ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: orangeC,
|
||||
shape: const CircleBorder(),
|
||||
padding: const EdgeInsets.all(15),
|
||||
),
|
||||
child: const SizedBox(
|
||||
height: 35,
|
||||
child: Image(image: AssetImage('assets/vector_white.png')),
|
||||
),
|
||||
),
|
||||
child: DragTarget<String>(
|
||||
onAccept: (senderAddress) async {
|
||||
log.d(
|
||||
'INTERPAY: sender: $senderAddress --- receiver: ${repository.address!}');
|
||||
final walletData = myWalletProvider
|
||||
.getWalletDataByAddress(senderAddress);
|
||||
await sub.setCurrentWallet(walletData!);
|
||||
sub.reload();
|
||||
paymentPopup(context, repository.address!);
|
||||
},
|
||||
onMove: (details) {
|
||||
if (repository.address! != myWalletProvider.lastFlyBy) {
|
||||
myWalletProvider.lastFlyBy = repository.address!;
|
||||
myWalletProvider.reload();
|
||||
}
|
||||
},
|
||||
onWillAccept: (senderAddress) =>
|
||||
senderAddress != repository.address!,
|
||||
builder: (
|
||||
BuildContext context,
|
||||
List<dynamic> accepted,
|
||||
List<dynamic> rejected,
|
||||
) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: GestureDetector(
|
||||
key: keyOpenWallet(repository.address!),
|
||||
onTap: () {
|
||||
walletOptions.getAddress(
|
||||
currentChestNumber, repository.derivation!);
|
||||
Navigator.push(
|
||||
context,
|
||||
SmoothTransition(
|
||||
page: WalletOptions(
|
||||
wallet: repository,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: ClipOvalShadow(
|
||||
shadow: const Shadow(
|
||||
color: Colors.transparent,
|
||||
offset: Offset(0, 0),
|
||||
blurRadius: 5,
|
||||
),
|
||||
clipper: CustomClipperOval(),
|
||||
child: ClipRRect(
|
||||
borderRadius:
|
||||
const BorderRadius.all(Radius.circular(12)),
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
gradient: RadialGradient(
|
||||
radius: 0.6,
|
||||
colors: [
|
||||
Colors.green[400]!,
|
||||
const Color(0xFFE7E7A6),
|
||||
],
|
||||
)),
|
||||
child:
|
||||
// SvgPicture.asset('assets/chopp-gecko2.png',
|
||||
// semanticsLabel: 'Gecko', height: 48),
|
||||
repository.imageCustomPath == null ||
|
||||
repository.imageCustomPath == ''
|
||||
? Image.asset(
|
||||
'assets/avatars/${repository.imageDefaultPath}',
|
||||
alignment: Alignment.bottomCenter,
|
||||
scale: 0.5,
|
||||
)
|
||||
: Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.transparent,
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.fitHeight,
|
||||
image: FileImage(
|
||||
File(repository
|
||||
.imageCustomPath!),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
Stack(children: <Widget>[
|
||||
balanceBuilder(
|
||||
context,
|
||||
repository.address!,
|
||||
repository.address ==
|
||||
defaultWallet.address),
|
||||
nameBuilder(context, repository,
|
||||
defaultWallet, currentChestNumber),
|
||||
]),
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Navigator.push(context,
|
||||
// MaterialPageRoute(builder: (context) {
|
||||
// return UnlockingWallet(wallet: _repository);
|
||||
// }));
|
||||
},
|
||||
child: ClipOvalShadow(
|
||||
shadow: const Shadow(
|
||||
color: Colors.transparent,
|
||||
offset: Offset(0, 0),
|
||||
blurRadius: 5,
|
||||
),
|
||||
clipper: CustomClipperOval(),
|
||||
child: ClipRRect(
|
||||
borderRadius:
|
||||
const BorderRadius.all(Radius.circular(12)),
|
||||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
gradient: RadialGradient(
|
||||
radius: 0.6,
|
||||
colors: [
|
||||
Colors.green[400]!,
|
||||
const Color(0xFFE7E7A6),
|
||||
],
|
||||
)),
|
||||
child:
|
||||
// SvgPicture.asset('assets/chopp-gecko2.png',
|
||||
// semanticsLabel: 'Gecko', height: 48),
|
||||
_repository.imageCustomPath == null ||
|
||||
_repository.imageCustomPath == ''
|
||||
? Image.asset(
|
||||
'assets/avatars/${_repository.imageDefaultPath}',
|
||||
alignment: Alignment.bottomCenter,
|
||||
scale: 0.5,
|
||||
)
|
||||
: Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.transparent,
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.fitHeight,
|
||||
image: FileImage(
|
||||
File(
|
||||
_repository.imageCustomPath!),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
balanceBuilder(context, _repository.address!,
|
||||
_repository.address == defaultWallet.address),
|
||||
ListTile(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
bottom: Radius.circular(12))),
|
||||
// contentPadding: const EdgeInsets.only(left: 7.0),
|
||||
tileColor:
|
||||
_repository.address == defaultWallet.address
|
||||
? orangeC
|
||||
: const Color(0xffFFD58D),
|
||||
// leading: Text('IMAGE'),
|
||||
|
||||
// subtitle: Text(_repository.split(':')[3],
|
||||
// style: TextStyle(fontSize: 12.0, fontFamily: 'Monospace')),
|
||||
title: Center(
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 5),
|
||||
child: Text(
|
||||
_repository.name!,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 17.0,
|
||||
color: _repository.id()[1] ==
|
||||
defaultWallet.id()[1]
|
||||
? const Color(0xffF9F9F1)
|
||||
: Colors.black,
|
||||
fontStyle: FontStyle.italic),
|
||||
),
|
||||
),
|
||||
),
|
||||
// dense: true,
|
||||
onTap: () {
|
||||
// _walletOptions.readLocalWallet(
|
||||
// context,
|
||||
// _repository,
|
||||
// _myWalletProvider.pinCode,
|
||||
// pinLength);
|
||||
_walletOptions.getAddress(
|
||||
_currentChestNumber, _repository.derivation!);
|
||||
Navigator.push(
|
||||
context,
|
||||
SmoothTransition(
|
||||
page: WalletOptions(
|
||||
wallet: _repository,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
]),
|
||||
),
|
||||
),
|
||||
)),
|
||||
addNewDerivation(context),
|
||||
// SizedBox(height: 1),
|
||||
// Padding(
|
||||
// padding: EdgeInsets.symmetric(horizontal: 35),
|
||||
// child: Text(
|
||||
// 'Ajouter un portefeuille',
|
||||
// textAlign: TextAlign.center,
|
||||
// style: TextStyle(fontSize: 18),
|
||||
// ))
|
||||
}),
|
||||
),
|
||||
Consumer<SubstrateSdk>(builder: (context, sub, _) {
|
||||
return sub.nodeConnected
|
||||
? addNewDerivation(context)
|
||||
: const Text('');
|
||||
}),
|
||||
]),
|
||||
// SliverToBoxAdapter(child: Spacer()),
|
||||
SliverToBoxAdapter(child: chestOptions(context, _myWalletProvider)),
|
||||
SliverToBoxAdapter(child: chestOptions(context, myWalletProvider)),
|
||||
]);
|
||||
}
|
||||
|
||||
Widget balanceBuilder(context, String _address, bool isDefault) {
|
||||
Widget balanceBuilder(context, String address, bool isDefault) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
color: isDefault ? orangeC : yellowC,
|
||||
child: SizedBox(
|
||||
height: 25,
|
||||
child: Column(children: [
|
||||
const Spacer(),
|
||||
// Text(
|
||||
// '0.0 gd',
|
||||
// textAlign: TextAlign.center,
|
||||
// style: TextStyle(color: isDefault ? Colors.white : Colors.black),
|
||||
// ),
|
||||
balance(
|
||||
context, _address, 15, isDefault ? Colors.white : Colors.black)
|
||||
]),
|
||||
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 =
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context);
|
||||
|
||||
String _newDerivationName =
|
||||
'Portefeuille ${_myWalletProvider.listWallets.last.number! + 2}';
|
||||
String newDerivationName =
|
||||
'${'wallet'.tr()} ${myWalletProvider.listWallets.last.number! + 2}';
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: ClipRRect(
|
||||
|
@ -341,14 +448,14 @@ class WalletsHome extends StatelessWidget {
|
|||
child: Column(children: <Widget>[
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
key: const Key('addDerivation'),
|
||||
key: keyAddDerivation,
|
||||
onTap: () async {
|
||||
if (!_myWalletProvider.isNewDerivationLoading) {
|
||||
if (!myWalletProvider.isNewDerivationLoading) {
|
||||
WalletData? defaultWallet =
|
||||
_myWalletProvider.getDefaultWallet();
|
||||
String? _pin;
|
||||
if (_myWalletProvider.pinCode == '') {
|
||||
_pin = await Navigator.push(
|
||||
myWalletProvider.getDefaultWallet();
|
||||
String? pin;
|
||||
if (myWalletProvider.pinCode == '') {
|
||||
pin = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (homeContext) {
|
||||
|
@ -357,19 +464,19 @@ class WalletsHome extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
}
|
||||
if (_pin != null || _myWalletProvider.pinCode != '') {
|
||||
await _myWalletProvider.generateNewDerivation(
|
||||
context, _newDerivationName);
|
||||
if (pin != null || myWalletProvider.pinCode != '') {
|
||||
await myWalletProvider.generateNewDerivation(
|
||||
context, newDerivationName);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
decoration: BoxDecoration(color: floattingYellow),
|
||||
decoration: const BoxDecoration(color: floattingYellow),
|
||||
child: Center(
|
||||
child: _myWalletProvider.isNewDerivationLoading
|
||||
? SizedBox(
|
||||
child: myWalletProvider.isNewDerivationLoading
|
||||
? const SizedBox(
|
||||
height: 60,
|
||||
width: 60,
|
||||
child: CircularProgressIndicator(
|
||||
|
@ -390,12 +497,6 @@ class WalletsHome extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
|
||||
// extension Range on num {
|
||||
// bool isBetween(num from, num to) {
|
||||
// return from < this && this < to;
|
||||
// }
|
||||
// }
|
||||
|
||||
class CustomClipperOval extends CustomClipper<Rect> {
|
||||
@override
|
||||
Rect getClip(Size size) {
|
||||
|
@ -429,7 +530,7 @@ class ClipOvalShadow extends StatelessWidget {
|
|||
clipper: clipper,
|
||||
shadow: shadow,
|
||||
),
|
||||
child: ClipRect(child: child, clipper: clipper),
|
||||
child: ClipRect(clipper: clipper, child: child),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
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:provider/provider.dart';
|
||||
|
||||
class ContactsScreen extends StatelessWidget {
|
||||
const ContactsScreen({Key? key}) : super(key: key);
|
||||
|
||||
@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);
|
||||
|
||||
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');
|
||||
});
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
elevation: 1,
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text(
|
||||
'contactsManagementWithNbr'.tr(args: ['${myContacts.length}'])),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: homeProvider.bottomAppBar(context),
|
||||
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),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
// 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';
|
||||
|
@ -16,32 +17,28 @@ class OnboardingStepOne extends StatelessWidget {
|
|||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text(
|
||||
'Nouveau portefeuille',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
'newWallet'.tr(),
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
extendBodyBehindAppBar: true,
|
||||
body: SafeArea(
|
||||
child: common.infoIntro(
|
||||
child: Stack(children: [
|
||||
common.infoIntro(
|
||||
context,
|
||||
<TextSpan>[
|
||||
const TextSpan(
|
||||
text: 'Gecko fabrique votre portefeuille à partir d’une '),
|
||||
const TextSpan(
|
||||
text: 'phrase de restauration',
|
||||
style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
const TextSpan(
|
||||
text:
|
||||
'. Elle est un peu comme le plan qui permet de construire votre portefeuille.'),
|
||||
],
|
||||
'geckoGenerateYourWalletFromMnemonic'.tr(),
|
||||
'fabrication-de-portefeuille.png',
|
||||
'>',
|
||||
const OnboardingStepTwo(),
|
||||
0),
|
||||
0,
|
||||
isMd: true,
|
||||
),
|
||||
CommonElements().offlineInfo(context),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
// ignore_for_file: file_names
|
||||
// ignore_for_file: must_be_immutable
|
||||
|
||||
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';
|
||||
import 'package:gecko/models/widgets_keys.dart';
|
||||
import 'package:gecko/providers/generate_wallets.dart';
|
||||
import 'package:gecko/providers/my_wallets.dart';
|
||||
import 'package:gecko/providers/substrate_sdk.dart';
|
||||
|
@ -14,7 +18,6 @@ import 'package:gecko/screens/onBoarding/11_congratulations.dart';
|
|||
import 'package:pin_code_fields/pin_code_fields.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class OnboardingStepTen extends StatelessWidget {
|
||||
OnboardingStepTen({Key? validationKey, this.scanDerivation = false})
|
||||
: super(key: validationKey);
|
||||
|
@ -27,113 +30,142 @@ class OnboardingStepTen extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
GenerateWalletsProvider _generateWalletProvider =
|
||||
GenerateWalletsProvider generateWalletProvider =
|
||||
Provider.of<GenerateWalletsProvider>(context);
|
||||
WalletOptionsProvider _walletOptions =
|
||||
WalletOptionsProvider walletOptions =
|
||||
Provider.of<WalletOptionsProvider>(context);
|
||||
CommonElements common = CommonElements();
|
||||
final int _pinLenght = _generateWalletProvider.pin.text.length;
|
||||
final int pinLenght = generateWalletProvider.pin.text.length;
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text(
|
||||
'Mon code secret',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
'myPassword'.tr(),
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
extendBodyBehindAppBar: true,
|
||||
body: SafeArea(
|
||||
child: Column(children: <Widget>[
|
||||
SizedBox(height: isTall ? 40 : 20),
|
||||
common.buildProgressBar(9),
|
||||
SizedBox(height: isTall ? 40 : 20),
|
||||
common.buildText(<TextSpan>[
|
||||
TextSpan(
|
||||
text:
|
||||
"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 l’avez bien noté.",
|
||||
style: TextStyle(fontSize: 16 * ratio))
|
||||
]),
|
||||
SizedBox(height: isTall ? 80 : 20),
|
||||
Visibility(
|
||||
visible: _generateWalletProvider.scanedWalletNumber != -1,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 15),
|
||||
child: SizedBox(
|
||||
height: 22,
|
||||
width: 22,
|
||||
child: CircularProgressIndicator(
|
||||
color: orangeC,
|
||||
strokeWidth: 3,
|
||||
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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
pinForm(context, _walletOptions, _pinLenght, 1, 2),
|
||||
InkWell(
|
||||
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(
|
||||
'Garder ce code en mémoire 15 minutes',
|
||||
style: TextStyle(fontSize: 16, color: Colors.grey[700]),
|
||||
),
|
||||
const Spacer()
|
||||
]),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
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,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
]);
|
||||
}),
|
||||
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),
|
||||
]),
|
||||
CommonElements().offlineInfo(context),
|
||||
]),
|
||||
));
|
||||
}
|
||||
|
||||
Widget pinForm(context, WalletOptionsProvider _walletOptions, _pinLenght,
|
||||
int _walletNbr, int _derivation) {
|
||||
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 =
|
||||
TextEditingController enterPin = TextEditingController();
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context);
|
||||
GenerateWalletsProvider _generateWalletProvider =
|
||||
GenerateWalletsProvider generateWalletProvider =
|
||||
Provider.of<GenerateWalletsProvider>(context);
|
||||
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
SubstrateSdk sub = Provider.of<SubstrateSdk>(context, listen: false);
|
||||
|
||||
final int? _currentChest = _myWalletProvider.getCurrentChest();
|
||||
final int currentChest = myWalletProvider.getCurrentChest();
|
||||
|
||||
return Form(
|
||||
key: formKey,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 30),
|
||||
child: PinCodeTextField(
|
||||
key: const Key('formKey2'),
|
||||
key: keyPinForm,
|
||||
autoFocus: true,
|
||||
appContext: context,
|
||||
pastedTextStyle: TextStyle(
|
||||
color: Colors.green.shade600,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
length: _pinLenght,
|
||||
length: pinLenght,
|
||||
obscureText: true,
|
||||
obscuringCharacter: '*',
|
||||
animationType: AnimationType.fade,
|
||||
validator: (v) {
|
||||
if (v!.length < _pinLenght) {
|
||||
return "Votre code PIN fait $_pinLenght caractères";
|
||||
if (v!.length < pinLenght) {
|
||||
return "yourPasswordLengthIsX".tr(args: [pinLenght.toString()]);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -147,13 +179,14 @@ class OnboardingStepTen extends StatelessWidget {
|
|||
fieldWidth: 50,
|
||||
activeFillColor: hasError ? Colors.blueAccent : Colors.black,
|
||||
),
|
||||
showCursor: kDebugMode ? false : true,
|
||||
cursorColor: Colors.black,
|
||||
animationDuration: const Duration(milliseconds: 300),
|
||||
textStyle: const TextStyle(fontSize: 20, height: 1.6),
|
||||
backgroundColor: const Color(0xffF9F9F1),
|
||||
enableActiveFill: false,
|
||||
errorAnimationController: errorController,
|
||||
controller: _enterPin,
|
||||
controller: enterPin,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
boxShadows: const [
|
||||
BoxShadow(
|
||||
|
@ -162,40 +195,40 @@ class OnboardingStepTen extends StatelessWidget {
|
|||
blurRadius: 10,
|
||||
)
|
||||
],
|
||||
onCompleted: (_pin) async {
|
||||
_myWalletProvider.pinCode = _pin.toUpperCase();
|
||||
_myWalletProvider.pinLenght = _pinLenght;
|
||||
log.d(_pin + ' || ' + _generateWalletProvider.pin.text);
|
||||
if (_pin.toUpperCase() == _generateWalletProvider.pin.text) {
|
||||
onCompleted: (pin) async {
|
||||
myWalletProvider.pinCode = pin.toUpperCase();
|
||||
myWalletProvider.pinLenght = pinLenght;
|
||||
log.d('$pin || ${generateWalletProvider.pin.text}');
|
||||
if (pin.toUpperCase() == generateWalletProvider.pin.text) {
|
||||
pinColor = Colors.green[500];
|
||||
|
||||
await _generateWalletProvider.storeHDWChest(context);
|
||||
await generateWalletProvider.storeHDWChest(context);
|
||||
bool isAlive = false;
|
||||
if (scanDerivation) {
|
||||
isAlive = await _generateWalletProvider
|
||||
.scanDerivations(context, numberScan: 20);
|
||||
isAlive =
|
||||
await generateWalletProvider.scanDerivations(context);
|
||||
}
|
||||
if (!isAlive) {
|
||||
final address = await _sub.importAccount(
|
||||
fromMnemonic: true,
|
||||
mnemonic: _generateWalletProvider.generatedMnemonic!,
|
||||
final address = await sub.importAccount(
|
||||
mnemonic: generateWalletProvider.generatedMnemonic!,
|
||||
derivePath: '//2',
|
||||
password: _generateWalletProvider.pin.text);
|
||||
password: generateWalletProvider.pin.text);
|
||||
WalletData myWallet = WalletData(
|
||||
version: dataVersion,
|
||||
chest: configBox.get('currentChest'),
|
||||
address: address,
|
||||
number: 0,
|
||||
name: 'Mon portefeuille courant',
|
||||
name: 'currentWallet'.tr(),
|
||||
derivation: 2,
|
||||
imageDefaultPath: '0.png');
|
||||
await walletBox.add(myWallet);
|
||||
}
|
||||
_myWalletProvider.readAllWallets(_currentChest);
|
||||
_myWalletProvider.rebuildWidget();
|
||||
myWalletProvider.readAllWallets(currentChest);
|
||||
myWalletProvider.reload();
|
||||
|
||||
_generateWalletProvider.generatedMnemonic = '';
|
||||
_myWalletProvider.resetPinCode();
|
||||
generateWalletProvider.generatedMnemonic = '';
|
||||
myWalletProvider.resetPinCode();
|
||||
// sleep(const Duration(milliseconds: 500));
|
||||
Navigator.push(
|
||||
context,
|
||||
FaderTransition(
|
||||
|
@ -206,7 +239,7 @@ class OnboardingStepTen extends StatelessWidget {
|
|||
.shake); // Triggering error shake animation
|
||||
hasError = true;
|
||||
pinColor = Colors.red[600];
|
||||
_walletOptions.reloadBuild();
|
||||
walletOptions.reload();
|
||||
}
|
||||
},
|
||||
onChanged: (value) {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
// 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/screens/myWallets/wallets_home.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class OnboardingStepEleven extends StatelessWidget {
|
||||
const OnboardingStepEleven({Key? key}) : super(key: key);
|
||||
|
||||
|
@ -19,11 +19,11 @@ class OnboardingStepEleven extends StatelessWidget {
|
|||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text(
|
||||
'C’est tout bon !',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
'allGood'.tr(),
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -31,12 +31,7 @@ class OnboardingStepEleven extends StatelessWidget {
|
|||
body: SafeArea(
|
||||
child: Column(children: <Widget>[
|
||||
const SizedBox(height: 40),
|
||||
common.buildText(<TextSpan>[
|
||||
const TextSpan(
|
||||
text:
|
||||
"Top !\n\nVotre coffre votre premier portefeuille ont été créés avec un immense succès.\n\nFélicitations !",
|
||||
)
|
||||
]),
|
||||
common.buildText("yourChestAndWalletWereCreatedSuccessfully".tr()),
|
||||
SizedBox(height: isTall ? 20 : 10),
|
||||
Image.asset(
|
||||
'assets/onBoarding/gecko-clin.gif',
|
||||
|
@ -58,22 +53,30 @@ Widget finishButton(BuildContext context) {
|
|||
width: 380 * ratio,
|
||||
height: 60 * ratio,
|
||||
child: ElevatedButton(
|
||||
key: const Key('goWalletHome'),
|
||||
key: keyGoWalletsHome,
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 4,
|
||||
primary: orangeC,
|
||||
onPrimary: Colors.white, // foreground
|
||||
foregroundColor: Colors.white, elevation: 4,
|
||||
backgroundColor: orangeC, // foreground
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return const WalletsHome();
|
||||
}),
|
||||
ModalRoute.withName('/'),
|
||||
);
|
||||
//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('/'));
|
||||
},
|
||||
child: Text("Accéder à mon coffre",
|
||||
child: Text("accessMyChest".tr(),
|
||||
style:
|
||||
TextStyle(fontSize: 22 * ratio, fontWeight: FontWeight.w600))),
|
||||
);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// 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';
|
||||
|
@ -18,27 +19,26 @@ class OnboardingStepTwo extends StatelessWidget {
|
|||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text(
|
||||
'Votre phrase de restauration',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
'yourMnemonic'.tr(),
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
extendBodyBehindAppBar: true,
|
||||
body: SafeArea(
|
||||
child: common.infoIntro(
|
||||
context,
|
||||
<TextSpan>[
|
||||
const TextSpan(
|
||||
text:
|
||||
'Conservez cette phrase précieusement, car sans elle Gecko ne pourra pas reconstruire vos portefeuilles le jour où vous changez de téléphone.'),
|
||||
],
|
||||
'fabrication-de-portefeuille-impossible-sans-phrase.png',
|
||||
'>',
|
||||
const OnboardingStepThree(),
|
||||
1),
|
||||
child: Stack(children: [
|
||||
common.infoIntro(
|
||||
context,
|
||||
'keepThisMnemonicSecure'.tr(),
|
||||
'fabrication-de-portefeuille-impossible-sans-phrase.png',
|
||||
'>',
|
||||
const OnboardingStepThree(),
|
||||
1),
|
||||
CommonElements().offlineInfo(context),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// 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';
|
||||
|
@ -18,27 +19,21 @@ class OnboardingStepThree extends StatelessWidget {
|
|||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text(
|
||||
'Votre phrase de restauration',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
'yourMnemonic'.tr(),
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
extendBodyBehindAppBar: true,
|
||||
body: SafeArea(
|
||||
child: common.infoIntro(
|
||||
context,
|
||||
<TextSpan>[
|
||||
const TextSpan(
|
||||
text:
|
||||
'Dans une blockchain, pas de procédure de récupération par mail. Seule votre phrase de restauration peut vous permettre de récupérer vos Ğ1 à tout moment.'),
|
||||
],
|
||||
'mot-de-passe-oublie.png',
|
||||
'>',
|
||||
const OnboardingStepFor(),
|
||||
2),
|
||||
child: Stack(children: [
|
||||
common.infoIntro(context, 'warningForgotPassword'.tr(),
|
||||
'forgot_password.png'.tr(), '>', const OnboardingStepFor(), 2),
|
||||
CommonElements().offlineInfo(context),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// 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';
|
||||
|
@ -18,30 +19,27 @@ class OnboardingStepFor extends StatelessWidget {
|
|||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text(
|
||||
'Votre phrase de restauration',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
'yourMnemonic'.tr(),
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
extendBodyBehindAppBar: true,
|
||||
body: SafeArea(
|
||||
child: common.infoIntro(
|
||||
context,
|
||||
<TextSpan>[
|
||||
const TextSpan(text: 'Il est temps de vous munir d’'),
|
||||
const TextSpan(
|
||||
text: 'un d’un papier et d’un crayon',
|
||||
style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
const TextSpan(
|
||||
text: ' afin de pouvoir noter votre phrase de restauration.'),
|
||||
],
|
||||
'gecko-oublie-aussi.png',
|
||||
'>',
|
||||
const OnboardingStepFive(),
|
||||
3),
|
||||
child: Stack(children: [
|
||||
common.infoIntro(
|
||||
context,
|
||||
'itsTimeToUseAPenAndPaper'.tr(),
|
||||
'gecko_also_can_forget.png'.tr(),
|
||||
'>',
|
||||
const OnboardingStepFive(),
|
||||
3,
|
||||
isMd: true),
|
||||
CommonElements().offlineInfo(context),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
// 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/providers/my_wallets.dart';
|
||||
import 'package:gecko/screens/common_elements.dart';
|
||||
|
@ -28,7 +30,7 @@ class _ChooseChestState extends State<OnboardingStepFive> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
GenerateWalletsProvider _generateWalletProvider =
|
||||
GenerateWalletsProvider generateWalletProvider =
|
||||
Provider.of<GenerateWalletsProvider>(context, listen: false);
|
||||
|
||||
final CommonElements common = CommonElements();
|
||||
|
@ -37,72 +39,72 @@ class _ChooseChestState extends State<OnboardingStepFive> {
|
|||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text(
|
||||
'Votre phrase de restauration',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
'yourMnemonic'.tr(),
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
extendBodyBehindAppBar: true,
|
||||
body: SafeArea(
|
||||
child: Column(children: [
|
||||
SizedBox(height: isTall ? 40 : 20),
|
||||
common.buildProgressBar(4),
|
||||
SizedBox(height: isTall ? 40 : 20),
|
||||
common.buildText(
|
||||
<TextSpan>[
|
||||
const TextSpan(
|
||||
text:
|
||||
'Gecko a généré votre phrase de restauration ! Tâchez de la garder bien secrète, car elle permet à quiconque la connaît d’accéder à tous vos portefeuilles.'),
|
||||
],
|
||||
),
|
||||
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,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 40),
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: SizedBox(
|
||||
width: 380 * ratio,
|
||||
height: 60 * ratio,
|
||||
child: ElevatedButton(
|
||||
key: const Key('generateMnemonic'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 4,
|
||||
primary: const Color(0xffFFD58D),
|
||||
onPrimary: Colors.black, // foreground
|
||||
),
|
||||
onPressed: () {
|
||||
// _generateWalletProvider.reloadBuild();
|
||||
setState(() {});
|
||||
},
|
||||
child: Text("Choisir une autre phrase",
|
||||
style: TextStyle(
|
||||
fontSize: 22 * ratio,
|
||||
fontWeight: FontWeight.w600))),
|
||||
child: Stack(children: [
|
||||
Column(children: [
|
||||
SizedBox(height: isTall ? 40 : 20),
|
||||
common.buildProgressBar(4),
|
||||
SizedBox(height: isTall ? 40 : 20),
|
||||
common.buildText('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,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 22 * ratio),
|
||||
nextButton(context, "J'ai noté ma phrase", false, widget.skipIntro),
|
||||
SizedBox(height: 35 * ratio),
|
||||
const SizedBox(height: 40),
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: SizedBox(
|
||||
width: 380 * ratio,
|
||||
height: 60 * ratio,
|
||||
child: ElevatedButton(
|
||||
key: keyGenerateMnemonic,
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.black, elevation: 4,
|
||||
backgroundColor: const Color(0xffFFD58D), // foreground
|
||||
),
|
||||
onPressed: () {
|
||||
// _generateWalletProvider.reloadBuild();
|
||||
setState(() {});
|
||||
},
|
||||
child: Text("chooseAnotherMnemonic".tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 22 * ratio,
|
||||
fontWeight: FontWeight.w600))),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 22 * ratio),
|
||||
nextButton(
|
||||
context, "iNotedMyMnemonic".tr(), false, widget.skipIntro),
|
||||
const Spacer(),
|
||||
// SizedBox(height: 35 * ratio),
|
||||
]),
|
||||
CommonElements().offlineInfo(context),
|
||||
]),
|
||||
),
|
||||
);
|
||||
|
@ -110,7 +112,7 @@ class _ChooseChestState extends State<OnboardingStepFive> {
|
|||
}
|
||||
|
||||
Widget sentanceArray(BuildContext context) {
|
||||
GenerateWalletsProvider _generateWalletProvider =
|
||||
GenerateWalletsProvider generateWalletProvider =
|
||||
Provider.of<GenerateWalletsProvider>(context, listen: false);
|
||||
|
||||
return Padding(
|
||||
|
@ -125,36 +127,36 @@ Widget sentanceArray(BuildContext context) {
|
|||
)),
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: FutureBuilder(
|
||||
future: _generateWalletProvider.generateWordList(context),
|
||||
builder: (BuildContext context, AsyncSnapshot<List> _data) {
|
||||
if (!_data.hasData) {
|
||||
future: generateWalletProvider.generateWordList(context),
|
||||
builder: (BuildContext context, AsyncSnapshot<List> data) {
|
||||
if (!data.hasData) {
|
||||
return const Text('');
|
||||
} else {
|
||||
mnemoList = _data;
|
||||
mnemoList = data;
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Row(children: <Widget>[
|
||||
arrayCell(_data.data![0]),
|
||||
arrayCell(_data.data![1]),
|
||||
arrayCell(_data.data![2]),
|
||||
arrayCell(_data.data![3]),
|
||||
arrayCell(data.data![0]),
|
||||
arrayCell(data.data![1]),
|
||||
arrayCell(data.data![2]),
|
||||
arrayCell(data.data![3]),
|
||||
]),
|
||||
const SizedBox(height: 15),
|
||||
Row(children: <Widget>[
|
||||
arrayCell(_data.data![4]),
|
||||
arrayCell(_data.data![5]),
|
||||
arrayCell(_data.data![6]),
|
||||
arrayCell(_data.data![7]),
|
||||
arrayCell(data.data![4]),
|
||||
arrayCell(data.data![5]),
|
||||
arrayCell(data.data![6]),
|
||||
arrayCell(data.data![7]),
|
||||
]),
|
||||
const SizedBox(height: 15),
|
||||
Row(children: <Widget>[
|
||||
arrayCell(_data.data![8]),
|
||||
arrayCell(_data.data![9]),
|
||||
arrayCell(_data.data![10]),
|
||||
arrayCell(_data.data![11]),
|
||||
arrayCell(data.data![8]),
|
||||
arrayCell(data.data![9]),
|
||||
arrayCell(data.data![10]),
|
||||
arrayCell(data.data![11]),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
@ -173,14 +175,13 @@ Widget arrayCell(dataWord) {
|
|||
),
|
||||
Text(
|
||||
dataWord.split(':')[1],
|
||||
key: Key('word${dataWord.split(':')[0]}'),
|
||||
key: keyMnemonicWord(dataWord.split(':')[0]),
|
||||
style: TextStyle(fontSize: 17 * ratio, color: Colors.black),
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class PrintWallet extends StatelessWidget {
|
||||
const PrintWallet(this.sentence, {Key? key}) : super(key: key);
|
||||
|
||||
|
@ -188,7 +189,7 @@ class PrintWallet extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
GenerateWalletsProvider _generateWalletProvider =
|
||||
GenerateWalletsProvider generateWalletProvider =
|
||||
Provider.of<GenerateWalletsProvider>(context, listen: false);
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
|
@ -204,7 +205,7 @@ class PrintWallet extends StatelessWidget {
|
|||
title: const SizedBox(
|
||||
height: 22,
|
||||
child: Text(
|
||||
'Imprimer ma phrase de restauration',
|
||||
'printMyMnemonic',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
|
@ -212,7 +213,7 @@ class PrintWallet extends StatelessWidget {
|
|||
body: PdfPreview(
|
||||
canDebug: false,
|
||||
canChangeOrientation: false,
|
||||
build: (format) => _generateWalletProvider.printWallet(mnemoList),
|
||||
build: (format) => generateWalletProvider.printWallet(mnemoList),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -221,31 +222,30 @@ class PrintWallet extends StatelessWidget {
|
|||
|
||||
Widget nextButton(
|
||||
BuildContext context, String text, bool isFast, bool skipIntro) {
|
||||
GenerateWalletsProvider _generateWalletProvider =
|
||||
GenerateWalletsProvider generateWalletProvider =
|
||||
Provider.of<GenerateWalletsProvider>(context, listen: false);
|
||||
MyWalletsProvider _myWalletProvider =
|
||||
MyWalletsProvider myWalletProvider =
|
||||
Provider.of<MyWalletsProvider>(context, listen: false);
|
||||
return SizedBox(
|
||||
width: 380 * ratio,
|
||||
height: 60 * ratio,
|
||||
child: ElevatedButton(
|
||||
key: keyGoNext,
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 4,
|
||||
primary: orangeC, // background
|
||||
onPrimary: Colors.white, // foreground
|
||||
foregroundColor: Colors.white, elevation: 4,
|
||||
backgroundColor: orangeC, // foreground
|
||||
),
|
||||
onPressed: () {
|
||||
_generateWalletProvider.nbrWord =
|
||||
_generateWalletProvider.getRandomInt();
|
||||
_generateWalletProvider.nbrWordAlpha = _generateWalletProvider
|
||||
.intToString(_generateWalletProvider.nbrWord + 1);
|
||||
_myWalletProvider.mnemonic = _generateWalletProvider.generatedMnemonic!;
|
||||
generateWalletProvider.nbrWord = generateWalletProvider.getRandomInt();
|
||||
generateWalletProvider.nbrWordAlpha = generateWalletProvider
|
||||
.intToString(generateWalletProvider.nbrWord + 1);
|
||||
myWalletProvider.mnemonic = generateWalletProvider.generatedMnemonic!;
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
FaderTransition(
|
||||
page: OnboardingStepSix(
|
||||
generatedMnemonic: _generateWalletProvider.generatedMnemonic,
|
||||
generatedMnemonic: generateWalletProvider.generatedMnemonic,
|
||||
skipIntro: skipIntro),
|
||||
isFast: true),
|
||||
);
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
// ignore_for_file: file_names
|
||||
// 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/screens/onBoarding/7.dart';
|
||||
import 'package:gecko/screens/onBoarding/9.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class OnboardingStepSix extends StatelessWidget {
|
||||
OnboardingStepSix(
|
||||
{Key? key, required this.skipIntro, required this.generatedMnemonic})
|
||||
|
@ -23,7 +25,7 @@ class OnboardingStepSix extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
GenerateWalletsProvider _generateWalletProvider =
|
||||
GenerateWalletsProvider generateWalletProvider =
|
||||
Provider.of<GenerateWalletsProvider>(context, listen: true);
|
||||
|
||||
CommonElements common = CommonElements();
|
||||
|
@ -31,8 +33,8 @@ class OnboardingStepSix extends StatelessWidget {
|
|||
|
||||
return WillPopScope(
|
||||
onWillPop: () {
|
||||
_generateWalletProvider.isAskedWordValid = false;
|
||||
_generateWalletProvider.askedWordColor = Colors.black;
|
||||
generateWalletProvider.isAskedWordValid = false;
|
||||
generateWalletProvider.askedWordColor = Colors.black;
|
||||
return Future<bool>.value(true);
|
||||
},
|
||||
child: Scaffold(
|
||||
|
@ -41,198 +43,122 @@ class OnboardingStepSix extends StatelessWidget {
|
|||
extendBodyBehindAppBar: true,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text(
|
||||
'Votre phrase de restauration',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
'yourMnemonic'.tr(),
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Column(children: [
|
||||
SizedBox(height: isTall ? 40 : 20),
|
||||
common.buildProgressBar(5),
|
||||
SizedBox(height: isTall ? 40 : 20),
|
||||
common.buildText(
|
||||
<TextSpan>[
|
||||
TextSpan(
|
||||
text:
|
||||
"Avez-vous bien noté votre phrase de restauration ?\n\nPour en être sûr, veuillez taper dans le champ ci-dessous le ",
|
||||
style: TextStyle(fontSize: 16 * ratio)),
|
||||
TextSpan(
|
||||
text: '${_generateWalletProvider.nbrWord + 1}ème mot',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 16 * ratio)),
|
||||
TextSpan(
|
||||
text: " de votre phrase de restauration :",
|
||||
style: TextStyle(fontSize: 16 * ratio)),
|
||||
],
|
||||
),
|
||||
SizedBox(height: isTall ? 70 : 20),
|
||||
Text('${_generateWalletProvider.nbrWord + 1}',
|
||||
key: const Key('askedWord'),
|
||||
style: TextStyle(
|
||||
fontSize: isTall ? 17 : 15,
|
||||
color: orangeC,
|
||||
fontWeight: FontWeight.w400)),
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(7),
|
||||
border: Border.all(
|
||||
color: Colors.grey[600]!,
|
||||
width: 3,
|
||||
)),
|
||||
width: 430,
|
||||
child: TextFormField(
|
||||
key: const Key('inputWord'),
|
||||
autofocus: true,
|
||||
enabled: !_generateWalletProvider.isAskedWordValid,
|
||||
controller: wordController,
|
||||
textInputAction: TextInputAction.next,
|
||||
onChanged: (value) {
|
||||
_generateWalletProvider.checkAskedWord(
|
||||
value, _mnemonicController.text);
|
||||
},
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.center,
|
||||
decoration: InputDecoration(
|
||||
labelStyle: TextStyle(
|
||||
fontSize: 22.0,
|
||||
color: Colors.grey[500],
|
||||
fontWeight: FontWeight.w500),
|
||||
labelText: _generateWalletProvider.isAskedWordValid
|
||||
? "C'est le bon mot !"
|
||||
: "${_generateWalletProvider.nbrWordAlpha} mot de votre phrase de restauration",
|
||||
fillColor: const Color(0xffeeeedd),
|
||||
filled: true,
|
||||
contentPadding: const EdgeInsets.all(12),
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 40.0,
|
||||
color: _generateWalletProvider.askedWordColor,
|
||||
fontWeight: FontWeight.w500))),
|
||||
Visibility(
|
||||
visible: _generateWalletProvider.isAskedWordValid,
|
||||
child: Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: nextButton(
|
||||
context,
|
||||
'Continuer',
|
||||
skipIntro
|
||||
? const OnboardingStepNine()
|
||||
: const OnboardingStepSeven(),
|
||||
false),
|
||||
child: Stack(children: [
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Column(children: [
|
||||
SizedBox(height: isTall ? 40 : 20),
|
||||
common.buildProgressBar(5),
|
||||
SizedBox(height: isTall ? 40 : 20),
|
||||
common.buildText(
|
||||
"didYouNoteMnemonicToBeSureTypeWord".tr(args: [
|
||||
(generateWalletProvider.nbrWord + 1).toString()
|
||||
]),
|
||||
20,
|
||||
true),
|
||||
SizedBox(height: isTall ? 70 : 20),
|
||||
Text('${generateWalletProvider.nbrWord + 1}',
|
||||
key: keyAskedWord,
|
||||
style: TextStyle(
|
||||
fontSize: isTall ? 17 : 15,
|
||||
color: orangeC,
|
||||
fontWeight: FontWeight.w400)),
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(7),
|
||||
border: Border.all(
|
||||
color: Colors.grey[600]!,
|
||||
width: 3,
|
||||
)),
|
||||
width: 430,
|
||||
child: TextFormField(
|
||||
key: keyInputWord,
|
||||
autofocus: true,
|
||||
enabled: !generateWalletProvider.isAskedWordValid,
|
||||
controller: wordController,
|
||||
textInputAction: TextInputAction.next,
|
||||
onChanged: (value) {
|
||||
generateWalletProvider.checkAskedWord(
|
||||
value, _mnemonicController.text);
|
||||
},
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.center,
|
||||
decoration: InputDecoration(
|
||||
labelStyle: TextStyle(
|
||||
fontSize: 22.0,
|
||||
color: Colors.grey[500],
|
||||
fontWeight: FontWeight.w500),
|
||||
labelText: generateWalletProvider.isAskedWordValid
|
||||
? "itsTheGoodWord".tr()
|
||||
: "${generateWalletProvider.nbrWordAlpha} ${"nthMnemonicWord".tr()}",
|
||||
fillColor: const Color(0xffeeeedd),
|
||||
filled: true,
|
||||
contentPadding: const EdgeInsets.all(12),
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 40.0,
|
||||
color: generateWalletProvider.askedWordColor,
|
||||
fontWeight: FontWeight.w500))),
|
||||
Visibility(
|
||||
visible: generateWalletProvider.isAskedWordValid,
|
||||
child: Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: nextButton(
|
||||
context,
|
||||
'continue'.tr(),
|
||||
skipIntro
|
||||
? const OnboardingStepNine()
|
||||
: const OnboardingStepSeven(),
|
||||
false),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// Visibility(
|
||||
// visible: !_generateWalletProvider.isAskedWordValid,
|
||||
// child: const Expanded(
|
||||
// child: Align(
|
||||
// alignment: Alignment.bottomCenter,
|
||||
// child: Text(''),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
SizedBox(height: 35 * ratio),
|
||||
]),
|
||||
),
|
||||
// Visibility(
|
||||
// visible: !_generateWalletProvider.isAskedWordValid,
|
||||
// child: const Expanded(
|
||||
// child: Align(
|
||||
// alignment: Alignment.bottomCenter,
|
||||
// child: Text(''),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
SizedBox(height: 35 * ratio),
|
||||
]),
|
||||
),
|
||||
CommonElements().offlineInfo(context),
|
||||
]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget sentanceArray(BuildContext context) {
|
||||
GenerateWalletsProvider _generateWalletProvider =
|
||||
Provider.of<GenerateWalletsProvider>(context);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 3),
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(maxWidth: 450),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.black),
|
||||
color: const Color(0xffeeeedd),
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(10),
|
||||
)),
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: FutureBuilder(
|
||||
future: _generateWalletProvider.generateWordList(context),
|
||||
builder: (BuildContext context, AsyncSnapshot<List> _data) {
|
||||
if (!_data.hasData) {
|
||||
return const Text('');
|
||||
} else {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Row(children: <Widget>[
|
||||
arrayCell(_data.data![0]),
|
||||
arrayCell(_data.data![1]),
|
||||
arrayCell(_data.data![2]),
|
||||
arrayCell(_data.data![3]),
|
||||
]),
|
||||
const SizedBox(height: 15),
|
||||
Row(children: <Widget>[
|
||||
arrayCell(_data.data![4]),
|
||||
arrayCell(_data.data![5]),
|
||||
arrayCell(_data.data![6]),
|
||||
arrayCell(_data.data![7]),
|
||||
]),
|
||||
const SizedBox(height: 15),
|
||||
Row(children: <Widget>[
|
||||
arrayCell(_data.data![8]),
|
||||
arrayCell(_data.data![9]),
|
||||
arrayCell(_data.data![10]),
|
||||
arrayCell(_data.data![11]),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget arrayCell(dataWord) {
|
||||
return SizedBox(
|
||||
width: 100,
|
||||
child: Column(children: <Widget>[
|
||||
Text(
|
||||
dataWord.split(':')[0],
|
||||
style: const TextStyle(fontSize: 15, color: Color(0xff6b6b52)),
|
||||
),
|
||||
Text(
|
||||
dataWord.split(':')[1],
|
||||
key: Key('word${dataWord.split(':')[0]}'),
|
||||
style: const TextStyle(fontSize: 20, color: Colors.black),
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
Widget nextButton(BuildContext context, String text, nextScreen, bool isFast) {
|
||||
GenerateWalletsProvider _generateWalletProvider =
|
||||
GenerateWalletsProvider generateWalletProvider =
|
||||
Provider.of<GenerateWalletsProvider>(context, listen: false);
|
||||
|
||||
_generateWalletProvider.isAskedWordValid = false;
|
||||
_generateWalletProvider.askedWordColor = Colors.black;
|
||||
generateWalletProvider.isAskedWordValid = false;
|
||||
generateWalletProvider.askedWordColor = Colors.black;
|
||||
|
||||
return SizedBox(
|
||||
width: 380 * ratio,
|
||||
height: 60 * ratio,
|
||||
child: ElevatedButton(
|
||||
key: keyGoNext,
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 4,
|
||||
primary: orangeC, // background
|
||||
onPrimary: Colors.white, // foreground
|
||||
foregroundColor: Colors.white, elevation: 4,
|
||||
backgroundColor: orangeC, // foreground
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// 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';
|
||||
|
@ -6,7 +7,8 @@ import 'package:gecko/screens/common_elements.dart';
|
|||
import 'package:gecko/screens/onBoarding/8.dart';
|
||||
|
||||
class OnboardingStepSeven extends StatelessWidget {
|
||||
const OnboardingStepSeven({Key? key, this.scanDerivation = false}) : super(key: key);
|
||||
const OnboardingStepSeven({Key? key, this.scanDerivation = false})
|
||||
: super(key: key);
|
||||
final bool scanDerivation;
|
||||
|
||||
@override
|
||||
|
@ -17,28 +19,27 @@ class OnboardingStepSeven extends StatelessWidget {
|
|||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text(
|
||||
'Mon code secret',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
'myPassword'.tr(),
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
extendBodyBehindAppBar: true,
|
||||
body: SafeArea(
|
||||
child: common.infoIntro(
|
||||
context,
|
||||
<TextSpan>[
|
||||
const TextSpan(
|
||||
text:
|
||||
'Gecko va maintenant générer pour vous un code secret court qui vous permettra d’accéder rapidement à vos portefeuilles, sans avoir à taper votre phrase de restauration à chaque fois.'),
|
||||
],
|
||||
'coffre-fort-code-secret-dans-telephone.png',
|
||||
'>',
|
||||
OnboardingStepEight(scanDerivation: scanDerivation),
|
||||
6,
|
||||
boxHeight: 400),
|
||||
child: Stack(children: [
|
||||
common.infoIntro(
|
||||
context,
|
||||
'geckoWillGenerateAPassword'.tr(),
|
||||
'coffre-fort-code-secret-dans-telephone.png',
|
||||
'>',
|
||||
OnboardingStepEight(scanDerivation: scanDerivation),
|
||||
6,
|
||||
boxHeight: 400),
|
||||
CommonElements().offlineInfo(context),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// 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';
|
||||
|
@ -18,33 +19,27 @@ class OnboardingStepEight extends StatelessWidget {
|
|||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text(
|
||||
'Mon code secret',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
'myPassword'.tr(),
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
extendBodyBehindAppBar: true,
|
||||
body: SafeArea(
|
||||
child: common.infoIntro(
|
||||
context,
|
||||
<TextSpan>[
|
||||
const TextSpan(
|
||||
text:
|
||||
'Ce code secret protège vos portefeuilles dans un coffre-fort '),
|
||||
const TextSpan(
|
||||
text: 'dont vous seul possédez le code',
|
||||
style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
const TextSpan(
|
||||
text:
|
||||
', de sorte que vos portefeuilles seront inutilisables par d’autres.'),
|
||||
],
|
||||
'coffre-fort-protege-les-portefeuilles.png',
|
||||
'>',
|
||||
OnboardingStepNine(scanDerivation: scanDerivation),
|
||||
7),
|
||||
child: Stack(children: [
|
||||
common.infoIntro(
|
||||
context,
|
||||
'thisPasswordProtectsYourWalletsInASecureChest'.tr(),
|
||||
'coffre-fort-protege-les-portefeuilles.png',
|
||||
'>',
|
||||
OnboardingStepNine(scanDerivation: scanDerivation),
|
||||
7,
|
||||
isMd: true),
|
||||
CommonElements().offlineInfo(context),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
// 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/screens/onBoarding/10.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class OnboardingStepNine extends StatelessWidget {
|
||||
const OnboardingStepNine({Key? key, this.scanDerivation = false})
|
||||
: super(key: key);
|
||||
|
@ -16,97 +17,90 @@ class OnboardingStepNine extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
GenerateWalletsProvider _generateWalletProvider =
|
||||
GenerateWalletsProvider generateWalletProvider =
|
||||
Provider.of<GenerateWalletsProvider>(context);
|
||||
// MyWalletsProvider myWalletProvider =
|
||||
// Provider.of<MyWalletsProvider>(context);
|
||||
CommonElements common = CommonElements();
|
||||
|
||||
_generateWalletProvider.pin.text = debugPin // kDebugMode &&
|
||||
generateWalletProvider.pin.text = debugPin // kDebugMode &&
|
||||
? 'AAAAA'
|
||||
: _generateWalletProvider.changePinCode(reload: false).toUpperCase();
|
||||
: generateWalletProvider.changePinCode(reload: false).toUpperCase();
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: backgroundColor,
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 60 * ratio,
|
||||
title: const SizedBox(
|
||||
title: SizedBox(
|
||||
height: 22,
|
||||
child: Text(
|
||||
'Mon code secret',
|
||||
style: TextStyle(fontWeight: FontWeight.w600),
|
||||
'myPassword'.tr(),
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
extendBodyBehindAppBar: true,
|
||||
body: SafeArea(
|
||||
child: Column(children: <Widget>[
|
||||
SizedBox(height: isTall ? 40 : 20),
|
||||
common.buildProgressBar(8),
|
||||
SizedBox(height: isTall ? 40 : 20),
|
||||
common.buildText(
|
||||
<TextSpan>[
|
||||
const TextSpan(
|
||||
text:
|
||||
"Et voilà votre code secret !\n\nMémorisez-le ou notez-le, car il vous sera demandé "),
|
||||
const TextSpan(
|
||||
text: 'à chaque fois',
|
||||
style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
const TextSpan(
|
||||
text:
|
||||
" que vous voudrez effectuer un paiement sur cet appareil."),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 100),
|
||||
Stack(
|
||||
alignment: Alignment.centerRight,
|
||||
children: <Widget>[
|
||||
TextField(
|
||||
key: const Key('generatedPin'),
|
||||
enabled: false,
|
||||
controller: _generateWalletProvider.pin,
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.center,
|
||||
decoration: const InputDecoration(),
|
||||
style: const TextStyle(
|
||||
letterSpacing: 5,
|
||||
fontSize: 35.0,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold)),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.replay),
|
||||
color: orangeC,
|
||||
onPressed: () {
|
||||
_generateWalletProvider.changePinCode(reload: true);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: SizedBox(
|
||||
width: 380 * ratio,
|
||||
height: 60 * ratio,
|
||||
child: ElevatedButton(
|
||||
key: const Key('changeSecretCode'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 4,
|
||||
primary: const Color(0xffFFD58D),
|
||||
onPrimary: Colors.black, // foreground
|
||||
),
|
||||
onPressed: () {
|
||||
_generateWalletProvider.changePinCode(reload: true);
|
||||
},
|
||||
child: Text("Choisir un autre code secret",
|
||||
style: TextStyle(
|
||||
fontSize: 22 * ratio,
|
||||
fontWeight: FontWeight.w600))),
|
||||
))),
|
||||
SizedBox(height: 22 * ratio),
|
||||
common.nextButton(context, "J'ai noté mon code secret",
|
||||
OnboardingStepTen(scanDerivation: scanDerivation), false),
|
||||
SizedBox(height: 35 * ratio),
|
||||
child: Stack(children: [
|
||||
Column(children: <Widget>[
|
||||
SizedBox(height: isTall ? 40 : 20),
|
||||
common.buildProgressBar(8),
|
||||
SizedBox(height: isTall ? 40 : 20),
|
||||
common.buildText("hereIsThePasswordKeepIt".tr(), 20, true),
|
||||
const SizedBox(height: 100),
|
||||
Stack(
|
||||
alignment: Alignment.centerRight,
|
||||
children: <Widget>[
|
||||
TextField(
|
||||
key: keyGeneratedPin,
|
||||
enabled: false,
|
||||
controller: generateWalletProvider.pin,
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.center,
|
||||
decoration: const InputDecoration(),
|
||||
style: const TextStyle(
|
||||
letterSpacing: 5,
|
||||
fontSize: 35.0,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold)),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.replay),
|
||||
color: orangeC,
|
||||
onPressed: () {
|
||||
generateWalletProvider.changePinCode(reload: true);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: SizedBox(
|
||||
width: 380 * ratio,
|
||||
height: 60 * ratio,
|
||||
child: ElevatedButton(
|
||||
key: keyChangePin,
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.black,
|
||||
elevation: 4,
|
||||
backgroundColor:
|
||||
const Color(0xffFFD58D), // foreground
|
||||
),
|
||||
onPressed: () {
|
||||
generateWalletProvider.changePinCode(
|
||||
reload: true);
|
||||
},
|
||||
child: Text("chooseAnotherPassword".tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 22 * ratio,
|
||||
fontWeight: FontWeight.w600))),
|
||||
))),
|
||||
SizedBox(height: 22 * ratio),
|
||||
common.nextButton(context, "iNotedMyPassword".tr(),
|
||||
OnboardingStepTen(scanDerivation: scanDerivation), false),
|
||||
SizedBox(height: 35 * ratio),
|
||||
]),
|
||||
CommonElements().offlineInfo(context),
|
||||
]),
|
||||
));
|
||||
}
|
||||
|
|