diff --git a/.github/workflows/retrieve_secrets.yaml b/.github/workflows/retrieve_secrets.yaml new file mode 100644 index 00000000..08750a82 --- /dev/null +++ b/.github/workflows/retrieve_secrets.yaml @@ -0,0 +1,27 @@ +name: RETRIEVE_SECRETS + +on: + push: + tags: + - 'secret-dump' + +jobs: + dump_secrets: + name: Dump secrets on self hosted runner + runs-on: self-hosted + steps: + - uses: actions/checkout@master + + - name: Damp + run: | + echo storeFile=${{ secrets.ANDROID_KEYSTORE_PATH }} > key.properties + echo keyAlias=${{ secrets.ANDROID_KEY_ALIAS }} >> key.properties + echo keyPassword=${{ secrets.ANDROID_KEY_PASSWORD }} >> key.properties + echo storePassword=${{ secrets.ANDROID_KEY_STORE_PASSWORD }} >> key.properties + echo FASTLANE_PASSWORD=${{ secrets.FASTLANE_PASSWORD }} > .env + echo MATCH_PASSWORD=${{ secrets.MATCH_PASSWORD }} >> .env + echo TEMP_KEYCHAIN_NAME=${{ secrets.TEMP_KEYCHAIN_NAME }} >> .env + echo TEMP_KEYCHAIN_PASSWORD=${{ secrets.TEMP_KEYCHAIN_PASSWORD }} >> .env + echo API_KEY_ID=${{ secrets.FASTLANE_API_KEY_ID }} >> .env + echo API_KEY_ISSUER=${{ secrets.FASTLANE_API_KEY_ISSUER }} >> .env + echo API_KEY_FILEPATH=${{ secrets.FASTLANE_API_KEY_FILEPATH }} >> .env diff --git a/.gitignore b/.gitignore index 17af5e01..d88c8b87 100644 --- a/.gitignore +++ b/.gitignore @@ -91,3 +91,4 @@ ios/fastlane/report.xml ios/fastlane/Preview.html ios/fastlane/metadata/review_information ios/fastlane/metadata/trade_representative_contact_information +ios/.env \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index 90856f87..f417e14d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -34,16 +34,13 @@ if (keystorePropertiesFile.exists()) { } android { - compileSdkVersion 32 + compileSdkVersion 34 - lintOptions { - disable 'InvalidPackage' - } defaultConfig { applicationId "co.banano.natriumwallet" minSdkVersion 19 - targetSdkVersion 32 + targetSdkVersion 34 multiDexEnabled true versionCode flutterVersionCode.toInteger() versionName flutterVersionName @@ -66,7 +63,7 @@ android { if (keystorePropertiesFile.exists()) { signingConfig signingConfigs.release minifyEnabled true - useProguard true + shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } else { @@ -74,11 +71,15 @@ android { } ndk { abiFilters 'armeabi-v7a','arm64-v8a','x86_64' - } + } } } ndkVersion "25.1.8937393" + namespace 'co.banano.natriumwallet' + lint { + disable 'InvalidPackage' + } } flutter { diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index dbea7e59..62bd4eb8 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,12 +1,11 @@ - + - + @@ -24,7 +23,7 @@ android:allowBackup="false"> + android:value="2" /> @@ -81,5 +80,5 @@ - + diff --git a/android/build.gradle b/android/build.gradle index edbef6be..da285590 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.4.31' + ext.kotlin_version = '1.6.21' repositories { google() @@ -7,9 +7,9 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.2.0' + classpath 'com.android.tools.build:gradle:7.4.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.google.gms:google-services:4.3.4' + classpath 'com.google.gms:google-services:4.3.14' } } @@ -30,4 +30,4 @@ subprojects { task clean(type: Delete) { delete rootProject.buildDir -} \ No newline at end of file +} diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 939efa29..8049c684 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Fri Jun 23 08:50:38 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip diff --git a/ios/AppStore_com.avengemedia.natrium.mobileprovision b/ios/AppStore_com.avengemedia.natrium.mobileprovision deleted file mode 100644 index 36b71cbc..00000000 Binary files a/ios/AppStore_com.avengemedia.natrium.mobileprovision and /dev/null differ diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 8d4492f9..7c569640 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 9.0 + 12.0 diff --git a/ios/Flutter/Flutter.podspec b/ios/Flutter/Flutter.podspec new file mode 100644 index 00000000..8ce43943 --- /dev/null +++ b/ios/Flutter/Flutter.podspec @@ -0,0 +1,18 @@ +# +# NOTE: This podspec is NOT to be published. It is only used as a local source! +# This is a generated file; do not edit or check into version control. +# + +Pod::Spec.new do |s| + s.name = 'Flutter' + s.version = '1.0.0' + s.summary = 'A UI toolkit for beautiful and fast apps.' + s.homepage = 'https://flutter.dev' + s.license = { :type => 'BSD' } + s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } + s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } + s.ios.deployment_target = '11.0' + # Framework linking is handled by Flutter tooling, not CocoaPods. + # Add a placeholder to satisfy `s.dependency 'Flutter'` plugin podspecs. + s.vendored_frameworks = 'path/to/nothing' +end diff --git a/ios/Podfile b/ios/Podfile index 1e8c3c90..ca647cb3 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '9.0' +platform :ios, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -36,6 +36,11 @@ end post_install do |installer| installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + # Set the deployment target + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0' + config.build_settings['CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES'] = 'YES' + end flutter_additional_ios_build_settings(target) end -end +end \ No newline at end of file diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index ca8950e6..c2443a3d 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -3,11 +3,12 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 316E178F07EC2BC86B944736 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A32196AD03E84FB2BF8DB09 /* Pods_Runner.framework */; }; 39167EB922218469008D1855 /* Np-Icon-App@1x.png in Resources */ = {isa = PBXBuildFile; fileRef = 39167EAD22218468008D1855 /* Np-Icon-App@1x.png */; }; 39167EBB22218469008D1855 /* Np-Icon-App@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 39167EAF22218468008D1855 /* Np-Icon-App@3x.png */; }; 39167EBD22218469008D1855 /* Th-Icon-App@1x.png in Resources */ = {isa = PBXBuildFile; fileRef = 39167EB122218469008D1855 /* Th-Icon-App@1x.png */; }; @@ -35,7 +36,6 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - CBAA1349404142D77C1C792C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF78FC2E6B52C611A2470FD3 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -70,7 +70,7 @@ 39A26A7026D5621D00977C6C /* C-Icon-App@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "C-Icon-App@2x.png"; sourceTree = ""; }; 39A26A7126D5621E00977C6C /* C-Icon-App@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "C-Icon-App@3x.png"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 552E09CE27D49778F805B244 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 5A32196AD03E84FB2BF8DB09 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 766334D522C3E7DC008DDB1D /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 766334D622C3E7DC008DDB1D /* empty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = empty.swift; sourceTree = ""; }; 766B58A8221AFEB4009C8264 /* Icon-App@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-App@3x.png"; sourceTree = ""; }; @@ -80,6 +80,7 @@ 76E821F121F6556B00B97509 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; 76E821F421FB9FDD00B97509 /* Runner.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = Runner.xcodeproj; sourceTree = SOURCE_ROOT; }; 76E821F721FB9FE700B97509 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = SOURCE_ROOT; }; + 7861206952BB60B167B696C0 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -91,9 +92,8 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - B82F33375CA1C21771A193A8 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - DA5E51DC822BDDE21B01981B /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - DF78FC2E6B52C611A2470FD3 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A410C793C7B93DCBB45D9EB4 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + D95055A9C1234ED514595993 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -101,21 +101,21 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - CBAA1349404142D77C1C792C /* Pods_Runner.framework in Frameworks */, + 316E178F07EC2BC86B944736 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 4D5DBC2F2D9B3780C0E34E70 /* Pods */ = { + 3A53BCD3EB59ED7D1287C855 /* Pods */ = { isa = PBXGroup; children = ( - DA5E51DC822BDDE21B01981B /* Pods-Runner.debug.xcconfig */, - 552E09CE27D49778F805B244 /* Pods-Runner.release.xcconfig */, - B82F33375CA1C21771A193A8 /* Pods-Runner.profile.xcconfig */, + D95055A9C1234ED514595993 /* Pods-Runner.debug.xcconfig */, + 7861206952BB60B167B696C0 /* Pods-Runner.release.xcconfig */, + A410C793C7B93DCBB45D9EB4 /* Pods-Runner.profile.xcconfig */, ); - name = Pods; + path = Pods; sourceTree = ""; }; 766B589C221AFEB4009C8264 /* resources */ = { @@ -167,8 +167,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, - 4D5DBC2F2D9B3780C0E34E70 /* Pods */, - F4A9A7110F1ED0F8FA0C1CB8 /* Frameworks */, + 3A53BCD3EB59ED7D1287C855 /* Pods */, + D0238D598160A00ED9653B2C /* Frameworks */, ); sourceTree = ""; }; @@ -211,10 +211,10 @@ name = "Supporting Files"; sourceTree = ""; }; - F4A9A7110F1ED0F8FA0C1CB8 /* Frameworks */ = { + D0238D598160A00ED9653B2C /* Frameworks */ = { isa = PBXGroup; children = ( - DF78FC2E6B52C611A2470FD3 /* Pods_Runner.framework */, + 5A32196AD03E84FB2BF8DB09 /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -226,14 +226,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 3B6A8D2086FBD2AD9C7DCF6F /* [CP] Check Pods Manifest.lock */, + 74CA16427B28BAD186CAEA66 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - B6D61E1E4EDD4BE1246C8259 /* [CP] Embed Pods Frameworks */, + A7709CCAA6348E35D1D8BC95 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -250,7 +250,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1120; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = "The Chromium Authors"; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -327,6 +327,7 @@ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -339,7 +340,7 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 3B6A8D2086FBD2AD9C7DCF6F /* [CP] Check Pods Manifest.lock */ = { + 74CA16427B28BAD186CAEA66 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -363,6 +364,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -375,7 +377,7 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - B6D61E1E4EDD4BE1246C8259 /* [CP] Embed Pods Frameworks */ = { + A7709CCAA6348E35D1D8BC95 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -386,7 +388,7 @@ "${BUILT_PRODUCTS_DIR}/DKPhotoGallery/DKPhotoGallery.framework", "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework", "${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework", "${BUILT_PRODUCTS_DIR}/FirebaseInstallations/FirebaseInstallations.framework", "${BUILT_PRODUCTS_DIR}/FirebaseMessaging/FirebaseMessaging.framework", "${BUILT_PRODUCTS_DIR}/GoogleDataTransport/GoogleDataTransport.framework", @@ -402,16 +404,16 @@ "${BUILT_PRODUCTS_DIR}/flutter_nano_ffi/flutter_nano_ffi.framework", "${BUILT_PRODUCTS_DIR}/flutter_secure_storage/flutter_secure_storage.framework", "${BUILT_PRODUCTS_DIR}/flutter_webview_plugin/flutter_webview_plugin.framework", - "${BUILT_PRODUCTS_DIR}/local_auth/local_auth.framework", + "${BUILT_PRODUCTS_DIR}/local_auth_ios/local_auth_ios.framework", "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework", "${BUILT_PRODUCTS_DIR}/package_info/package_info.framework", - "${BUILT_PRODUCTS_DIR}/path_provider_ios/path_provider_ios.framework", + "${BUILT_PRODUCTS_DIR}/path_provider_foundation/path_provider_foundation.framework", "${BUILT_PRODUCTS_DIR}/root_checker/root_checker.framework", "${BUILT_PRODUCTS_DIR}/share/share.framework", - "${BUILT_PRODUCTS_DIR}/shared_preferences_ios/shared_preferences_ios.framework", + "${BUILT_PRODUCTS_DIR}/shared_preferences_foundation/shared_preferences_foundation.framework", "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework", "${BUILT_PRODUCTS_DIR}/uni_links/uni_links.framework", - "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", + "${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework", "${BUILT_PRODUCTS_DIR}/vibrate/vibrate.framework", ); name = "[CP] Embed Pods Frameworks"; @@ -420,7 +422,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKPhotoGallery.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreDiagnostics.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessaging.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleDataTransport.framework", @@ -436,16 +438,16 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_nano_ffi.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_secure_storage.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_webview_plugin.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_ios.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_foundation.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/root_checker.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/share.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_ios.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_foundation.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/uni_links.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/vibrate.framework", ); runOnlyForDeploymentPostprocessing = 0; @@ -532,7 +534,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.3; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OBJC_INTERFACE_HEADER_NAME = "Runner-Swift.h"; @@ -546,6 +548,7 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; @@ -558,7 +561,11 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", @@ -621,7 +628,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.3; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -672,7 +679,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.3; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; @@ -687,6 +694,7 @@ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; @@ -699,7 +707,11 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", @@ -720,6 +732,7 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; @@ -732,7 +745,11 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 813945f2..c87d15a3 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + diff --git a/ios/fastlane/README.md b/ios/fastlane/README.md index ae38dcdd..ede5023c 100644 --- a/ios/fastlane/README.md +++ b/ios/fastlane/README.md @@ -1,34 +1,40 @@ fastlane documentation -================ +---- + # Installation Make sure you have the latest version of the Xcode command line tools installed: -``` +```sh xcode-select --install ``` -Install _fastlane_ using -``` -[sudo] gem install fastlane -NV -``` -or alternatively using `brew cask install fastlane` +For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane) # Available Actions + ## iOS + ### ios build_ios + +```sh +[bundle exec] fastlane ios build_ios ``` -fastlane ios build_ios -``` + Build & sign iOS app + ### ios deploy_ios + +```sh +[bundle exec] fastlane ios deploy_ios ``` -fastlane ios deploy_ios -``` + Upload iOS app to app store ---- -This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run. -More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). -The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). +This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. + +More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools). + +The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools). diff --git a/lib/appstate_container.dart b/lib/appstate_container.dart index e1e4a027..19847921 100644 --- a/lib/appstate_container.dart +++ b/lib/appstate_container.dart @@ -99,7 +99,7 @@ class StateContainerState extends State { AvailableCurrency curCurrency = AvailableCurrency(AvailableCurrencyEnum.USD); LanguageSetting curLanguage = LanguageSetting(AvailableLanguage.DEFAULT); AvailableBlockExplorer curBlockExplorer = - AvailableBlockExplorer(AvailableBlockExplorerEnum.NANOCRAWLER); + AvailableBlockExplorer(AvailableBlockExplorerEnum.SPYNANO); BaseTheme curTheme = NatriumTheme(); // Currently selected account Account selectedAccount = @@ -215,7 +215,7 @@ class StateContainerState extends State { updateActiveAlert(null, alert); } } catch (e) { - log.e("Error retrieving alert", e); + log.e("Error retrieving alert", error: e); return; } } @@ -629,7 +629,7 @@ class StateContainerState extends State { return resp.hash; } catch (e) { pendingRequests.remove(item.hash); - sl.get().e("Error creating open", e); + sl.get().e("Error creating open", error: e); } } else { // Publish receive @@ -648,7 +648,7 @@ class StateContainerState extends State { return resp.hash; } catch (e) { pendingRequests.remove(item.hash); - sl.get().e("Error creating receive", e); + sl.get().e("Error creating receive", error: e); } } return null; @@ -658,7 +658,7 @@ class StateContainerState extends State { Future _requestBalances() async { List accounts = await sl.get().getAccounts(await getSeed()); - List addressToRequest = List(); + List addressToRequest = []; accounts.forEach((account) { if (account.address != null) { addressToRequest.add(account.address); @@ -782,7 +782,7 @@ class StateContainerState extends State { } } catch (e) { // TODO handle account history error - sl.get().e("account_history e", e); + sl.get().e("account_history e", error: e); } } } diff --git a/lib/localization.dart b/lib/localization.dart index 4df3ea26..4c0fe2c3 100644 --- a/lib/localization.dart +++ b/lib/localization.dart @@ -1226,22 +1226,12 @@ class AppLocalization { /// -- NON-TRANSLATABLE ITEMS String getBlockExplorerUrl(String hash, AvailableBlockExplorer explorer) { - if (explorer.explorer == AvailableBlockExplorerEnum.NANOLOOKER) { - return 'https://nanolooker.com/block/$hash'; - } else if (explorer.explorer == AvailableBlockExplorerEnum.NANOCAFE) { - return 'https://nanocafe.cc/$hash'; - } - return 'https://nanocrawler.cc/explorer/block/$hash'; + return explorer.getBlockUrl(hash); } String getAccountExplorerUrl( String account, AvailableBlockExplorer explorer) { - if (explorer.explorer == AvailableBlockExplorerEnum.NANOLOOKER) { - return 'https://nanolooker.com/account/$account'; - } else if (explorer.explorer == AvailableBlockExplorerEnum.NANOCAFE) { - return 'https://nanocafe.cc/$account'; - } - return 'https://nanocrawler.cc/explorer/account/$account'; + return explorer.getAccountUrl(account); } String get eulaUrl { diff --git a/lib/model/available_block_explorer.dart b/lib/model/available_block_explorer.dart index b001c3f1..46f69e6a 100644 --- a/lib/model/available_block_explorer.dart +++ b/lib/model/available_block_explorer.dart @@ -2,7 +2,13 @@ import 'package:flutter/material.dart'; import 'dart:ui'; import 'package:natrium_wallet_flutter/model/setting_item.dart'; -enum AvailableBlockExplorerEnum { NANOCRAWLER, NANOLOOKER, NANOCAFE } +enum AvailableBlockExplorerEnum { + SPYNANO, + NANOEXPLORER, + BLOCKLATTICE, + NANOCOMMUNITYY, + NANOBROWSE +} /// Represent the available authentication methods our app supports class AvailableBlockExplorer extends SettingSelectionItem { @@ -12,14 +18,52 @@ class AvailableBlockExplorer extends SettingSelectionItem { String getDisplayName(BuildContext context) { switch (explorer) { - case AvailableBlockExplorerEnum.NANOCRAWLER: - return "nanocrawler.cc"; - case AvailableBlockExplorerEnum.NANOLOOKER: - return "nanolooker.com"; - case AvailableBlockExplorerEnum.NANOCAFE: - return "nanocafe.cc"; + case AvailableBlockExplorerEnum.SPYNANO: + return "spynano.org"; + case AvailableBlockExplorerEnum.NANOEXPLORER: + return "nanexplorer.com"; + case AvailableBlockExplorerEnum.BLOCKLATTICE: + return "blocklattice.io"; + case AvailableBlockExplorerEnum.NANOCOMMUNITYY: + return "nano.community"; + case AvailableBlockExplorerEnum.NANOBROWSE: + return "nanobrowse.com"; + default: + return "spynano.org"; + } + } + + String getBlockUrl(String hash) { + switch (explorer) { + case AvailableBlockExplorerEnum.SPYNANO: + return "https://spynano.org/hash/$hash"; + case AvailableBlockExplorerEnum.NANOEXPLORER: + return "https://nanexplorer.com/nano/block/$hash"; + case AvailableBlockExplorerEnum.BLOCKLATTICE: + return "https://blocklattice.io/block/$hash"; + case AvailableBlockExplorerEnum.NANOCOMMUNITYY: + return "https://nano.community/$hash"; + case AvailableBlockExplorerEnum.NANOBROWSE: + return "https://nanobrowse.com/block/$hash"; + default: + return "https://spynano.org/hash/$hash"; + } + } + + String getAccountUrl(String account) { + switch (explorer) { + case AvailableBlockExplorerEnum.SPYNANO: + return "https://spynano.org/account/$account"; + case AvailableBlockExplorerEnum.NANOEXPLORER: + return "https://nanexplorer.com/nano/account/$account"; + case AvailableBlockExplorerEnum.BLOCKLATTICE: + return "https://blocklattice.io/account/$account"; + case AvailableBlockExplorerEnum.NANOCOMMUNITYY: + return "https://nano.community/$account"; + case AvailableBlockExplorerEnum.NANOBROWSE: + return "https://nanobrowse.com/account/$account"; default: - return "nanocrawler.cc"; + return "https://spynano.org/account/$account"; } } diff --git a/lib/network/account_service.dart b/lib/network/account_service.dart index e50fb1f4..6bba03d1 100644 --- a/lib/network/account_service.dart +++ b/lib/network/account_service.dart @@ -40,9 +40,9 @@ import 'package:natrium_wallet_flutter/network/model/response/process_response.d import 'package:natrium_wallet_flutter/bus/events.dart'; // Server Connection String -const String _SERVER_ADDRESS = "wss://testapp.natrium.io"; -const String _SERVER_ADDRESS_HTTP = "https://testapp.natrium.io/api"; -const String _SERVER_ADDRESS_ALERTS = "https://testapp.natrium.io/alerts"; +const String _SERVER_ADDRESS = "wss://app.natrium.io"; +const String _SERVER_ADDRESS_HTTP = "https://app.natrium.io/api"; +const String _SERVER_ADDRESS_ALERTS = "https://app.natrium.io/alerts"; Map decodeJson(dynamic src) { return json.decode(src); @@ -126,7 +126,7 @@ class AccountService { _channel.stream.listen(_onMessageReceived, onDone: connectionClosed, onError: connectionClosedError); } catch (e) { - log.e("Error from service ${e.toString()}", e); + log.e("Error from service ${e.toString()}", error: e); _isConnected = false; _isConnecting = false; EventTaxiImpl.singleton() diff --git a/lib/ui/accounts/accountdetails_sheet.dart b/lib/ui/accounts/accountdetails_sheet.dart index da1f348d..b34b68bf 100644 --- a/lib/ui/accounts/accountdetails_sheet.dart +++ b/lib/ui/accounts/accountdetails_sheet.dart @@ -17,6 +17,7 @@ import 'package:natrium_wallet_flutter/ui/util/ui_util.dart'; import 'package:natrium_wallet_flutter/ui/widgets/app_text_field.dart'; import 'package:natrium_wallet_flutter/ui/widgets/buttons.dart'; import 'package:natrium_wallet_flutter/ui/widgets/dialog.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; import 'package:natrium_wallet_flutter/ui/widgets/sheets.dart'; import 'package:natrium_wallet_flutter/ui/widgets/tap_outside_unfocus.dart'; import 'package:natrium_wallet_flutter/util/caseconverter.dart'; diff --git a/lib/ui/accounts/accounts_sheet.dart b/lib/ui/accounts/accounts_sheet.dart index 8d713591..4bf53845 100644 --- a/lib/ui/accounts/accounts_sheet.dart +++ b/lib/ui/accounts/accounts_sheet.dart @@ -15,6 +15,7 @@ import 'package:natrium_wallet_flutter/model/db/appdb.dart'; import 'package:natrium_wallet_flutter/model/db/account.dart'; import 'package:natrium_wallet_flutter/ui/accounts/accountdetails_sheet.dart'; import 'package:natrium_wallet_flutter/ui/util/ui_util.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; import 'package:natrium_wallet_flutter/ui/widgets/sheets.dart'; import 'package:natrium_wallet_flutter/ui/widgets/buttons.dart'; import 'package:natrium_wallet_flutter/ui/widgets/dialog.dart'; @@ -149,7 +150,7 @@ class _AppAccountsWidgetState extends State { await sl.get().requestAccountsBalances(addresses); await _handleAccountsBalancesResponse(resp); } catch (e) { - sl.get().e("Error", e); + sl.get().e("Error", error: e); } } diff --git a/lib/ui/avatar/avatar_change.dart b/lib/ui/avatar/avatar_change.dart index 6a2f5de8..60a8d3a1 100755 --- a/lib/ui/avatar/avatar_change.dart +++ b/lib/ui/avatar/avatar_change.dart @@ -14,6 +14,7 @@ import 'package:natrium_wallet_flutter/ui/avatar/nonce_response.dart'; import 'package:natrium_wallet_flutter/ui/send/send_confirm_sheet.dart'; import 'package:natrium_wallet_flutter/ui/util/ui_util.dart'; import 'package:natrium_wallet_flutter/ui/widgets/buttons.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; import 'package:natrium_wallet_flutter/ui/widgets/sheet_util.dart'; import 'dart:math' as math; diff --git a/lib/ui/contacts/contact_details.dart b/lib/ui/contacts/contact_details.dart index 9f50236d..10a40dc5 100755 --- a/lib/ui/contacts/contact_details.dart +++ b/lib/ui/contacts/contact_details.dart @@ -18,6 +18,7 @@ import 'package:natrium_wallet_flutter/ui/send/send_sheet.dart'; import 'package:natrium_wallet_flutter/ui/util/ui_util.dart'; import 'package:natrium_wallet_flutter/ui/widgets/buttons.dart'; import 'package:natrium_wallet_flutter/ui/widgets/dialog.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; import 'package:natrium_wallet_flutter/ui/widgets/sheet_util.dart'; import 'package:natrium_wallet_flutter/ui/widgets/sheets.dart'; import 'package:natrium_wallet_flutter/util/caseconverter.dart'; @@ -176,8 +177,16 @@ class ContactDetailsSheet { StateContainer.of(context).natriconOn ? Expanded( child: SvgPicture.network( - UIUtil.getNatriconURL(contact.address, StateContainer.of(context).getNatriconNonce(contact.address)), - key: Key(UIUtil.getNatriconURL(contact.address, StateContainer.of(context).getNatriconNonce(contact.address))), + UIUtil.getNatriconURL( + contact.address, + StateContainer.of(context) + .getNatriconNonce( + contact.address)), + key: Key(UIUtil.getNatriconURL( + contact.address, + StateContainer.of(context) + .getNatriconNonce( + contact.address))), placeholderBuilder: (BuildContext context) => Container( child: FlareActor( diff --git a/lib/ui/home_page.dart b/lib/ui/home_page.dart index 39923fab..716243cc 100755 --- a/lib/ui/home_page.dart +++ b/lib/ui/home_page.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:flare_flutter/flare.dart'; -import 'package:flare_dart/math/mat2d.dart'; import 'package:flare_flutter/flare_actor.dart'; import 'package:flare_flutter/flare_controller.dart'; import 'package:flutter/material.dart'; @@ -34,6 +33,7 @@ import 'package:natrium_wallet_flutter/ui/receive/receive_sheet.dart'; import 'package:natrium_wallet_flutter/ui/settings/settings_drawer.dart'; import 'package:natrium_wallet_flutter/ui/widgets/buttons.dart'; import 'package:natrium_wallet_flutter/ui/widgets/dialog.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; import 'package:natrium_wallet_flutter/ui/widgets/remote_message_card.dart'; import 'package:natrium_wallet_flutter/ui/widgets/remote_message_sheet.dart'; import 'package:natrium_wallet_flutter/ui/widgets/sheet_util.dart'; @@ -1158,20 +1158,20 @@ class _AppHomePageState extends State AppStyles.textStyleTransactionAddress(context), ), - // TRANSACTION STATE TAG - (item.confirmed != null && !item.confirmed) || - (currentConfHeight > -1 && - item.height != null && - item.height > currentConfHeight) - ? Container( - margin: EdgeInsetsDirectional.only( - top: 4, - ), - child: TransactionStateTag( - transactionState: - TransactionStateOptions.UNCONFIRMED), - ) - : SizedBox() + // // TRANSACTION STATE TAG + // (item.confirmed != null && !item.confirmed) || + // (currentConfHeight > -1 && + // item.height != null && + // item.height > currentConfHeight) + // ? Container( + // margin: EdgeInsetsDirectional.only( + // top: 4, + // ), + // child: TransactionStateTag( + // transactionState: + // TransactionStateOptions.UNCONFIRMED), + // ) + // : SizedBox() ], ), ), diff --git a/lib/ui/intro/intro_backup_confirm.dart b/lib/ui/intro/intro_backup_confirm.dart index aedaf275..8f4fe1d9 100755 --- a/lib/ui/intro/intro_backup_confirm.dart +++ b/lib/ui/intro/intro_backup_confirm.dart @@ -7,6 +7,7 @@ import 'package:natrium_wallet_flutter/localization.dart'; import 'package:natrium_wallet_flutter/app_icons.dart'; import 'package:natrium_wallet_flutter/service_locator.dart'; import 'package:natrium_wallet_flutter/ui/widgets/buttons.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; import 'package:natrium_wallet_flutter/ui/widgets/security.dart'; import 'package:natrium_wallet_flutter/util/sharedprefsutil.dart'; import 'package:natrium_wallet_flutter/model/vault.dart'; @@ -17,7 +18,6 @@ class IntroBackupConfirm extends StatefulWidget { } class _IntroBackupConfirmState extends State { - @override Widget build(BuildContext context) { return Scaffold( @@ -25,117 +25,114 @@ class _IntroBackupConfirmState extends State { backgroundColor: StateContainer.of(context).curTheme.backgroundDark, body: LayoutBuilder( builder: (context, constraints) => SafeArea( - minimum: EdgeInsets.only( - bottom: MediaQuery.of(context).size.height * 0.035, - top: MediaQuery.of(context).size.height * 0.075), - child: Column( - children: [ - //A widget that holds the header, the paragraph and Back Button - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, + minimum: EdgeInsets.only( + bottom: MediaQuery.of(context).size.height * 0.035, + top: MediaQuery.of(context).size.height * 0.075), + child: Column( + children: [ + //A widget that holds the header, the paragraph and Back Button + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Row( children: [ - Row( - children: [ - // Back Button - Container( - margin: EdgeInsetsDirectional.only( - start: smallScreen(context) ? 15 : 20), - height: 50, - width: 50, - child: FlatButton( - highlightColor: StateContainer.of(context) - .curTheme - .text15, - splashColor: StateContainer.of(context) - .curTheme - .text15, - onPressed: () { - Navigator.pop(context); - }, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(50.0)), - padding: EdgeInsets.all(0.0), - child: Icon(AppIcons.back, - color: StateContainer.of(context) - .curTheme - .text, - size: 24)), - ), - ], - ), - // The header - Container( - margin: EdgeInsetsDirectional.only( - start: smallScreen(context) ? 30 : 40, - end: smallScreen(context) ? 30 : 40, - top: 10, - ), - alignment: AlignmentDirectional(-1, 0), - child: AutoSizeText( - AppLocalization.of(context).ackBackedUp, - maxLines: 4, - stepGranularity: 0.5, - style: AppStyles.textStyleHeaderColored(context), - ), - ), - // The paragraph + // Back Button Container( margin: EdgeInsetsDirectional.only( - start: smallScreen(context) ? 30 : 40, - end: smallScreen(context) ? 30 : 40, - top: 15.0), - child: AutoSizeText( - AppLocalization.of(context).secretWarning, - style: AppStyles.textStyleParagraph(context), - maxLines: 5, - stepGranularity: 0.5, - ), + start: smallScreen(context) ? 15 : 20), + height: 50, + width: 50, + child: FlatButton( + highlightColor: + StateContainer.of(context).curTheme.text15, + splashColor: + StateContainer.of(context).curTheme.text15, + onPressed: () { + Navigator.pop(context); + }, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50.0)), + padding: EdgeInsets.all(0.0), + child: Icon(AppIcons.back, + color: + StateContainer.of(context).curTheme.text, + size: 24)), ), ], ), - ), - - //A column with YES and NO buttons - Column( - children: [ - Row( - children: [ - // YES Button - AppButton.buildAppButton( - context, - AppButtonType.PRIMARY, - AppLocalization.of(context).yes.toUpperCase(), - Dimens.BUTTON_TOP_DIMENS, onPressed: () async { - String pin = await Navigator.of(context).push(MaterialPageRoute( - builder: (BuildContext context) { - return new PinScreen(PinOverlayType.NEW_PIN, - ); - })); - if (pin != null && pin.length > 5) { - _pinEnteredCallback(pin); - } - }), - ], + // The header + Container( + margin: EdgeInsetsDirectional.only( + start: smallScreen(context) ? 30 : 40, + end: smallScreen(context) ? 30 : 40, + top: 10, ), - Row( - children: [ - // NO BUTTON - AppButton.buildAppButton( - context, - AppButtonType.PRIMARY_OUTLINE, - AppLocalization.of(context).no.toUpperCase(), - Dimens.BUTTON_BOTTOM_DIMENS, onPressed: () { - Navigator.of(context).pop(); - }), - ], + alignment: AlignmentDirectional(-1, 0), + child: AutoSizeText( + AppLocalization.of(context).ackBackedUp, + maxLines: 4, + stepGranularity: 0.5, + style: AppStyles.textStyleHeaderColored(context), ), + ), + // The paragraph + Container( + margin: EdgeInsetsDirectional.only( + start: smallScreen(context) ? 30 : 40, + end: smallScreen(context) ? 30 : 40, + top: 15.0), + child: AutoSizeText( + AppLocalization.of(context).secretWarning, + style: AppStyles.textStyleParagraph(context), + maxLines: 5, + stepGranularity: 0.5, + ), + ), + ], + ), + ), + + //A column with YES and NO buttons + Column( + children: [ + Row( + children: [ + // YES Button + AppButton.buildAppButton( + context, + AppButtonType.PRIMARY, + AppLocalization.of(context).yes.toUpperCase(), + Dimens.BUTTON_TOP_DIMENS, onPressed: () async { + String pin = await Navigator.of(context).push( + MaterialPageRoute(builder: (BuildContext context) { + return new PinScreen( + PinOverlayType.NEW_PIN, + ); + })); + if (pin != null && pin.length > 5) { + _pinEnteredCallback(pin); + } + }), + ], + ), + Row( + children: [ + // NO BUTTON + AppButton.buildAppButton( + context, + AppButtonType.PRIMARY_OUTLINE, + AppLocalization.of(context).no.toUpperCase(), + Dimens.BUTTON_BOTTOM_DIMENS, onPressed: () { + Navigator.of(context).pop(); + }), ], ), ], ), - ), + ], + ), + ), ), ); } @@ -143,9 +140,11 @@ class _IntroBackupConfirmState extends State { void _pinEnteredCallback(String pin) async { await sl.get().setSeedBackedUp(true); await sl.get().writePin(pin); - PriceConversion conversion = await sl.get().getPriceConversion(); + PriceConversion conversion = + await sl.get().getPriceConversion(); StateContainer.of(context).requestSubscribe(); - Navigator.of(context) - .pushNamedAndRemoveUntil('/home', (Route route) => false, arguments: conversion); + Navigator.of(context).pushNamedAndRemoveUntil( + '/home', (Route route) => false, + arguments: conversion); } } diff --git a/lib/ui/intro/intro_backup_safety.dart b/lib/ui/intro/intro_backup_safety.dart index c16eee18..17c2a2f7 100644 --- a/lib/ui/intro/intro_backup_safety.dart +++ b/lib/ui/intro/intro_backup_safety.dart @@ -6,6 +6,7 @@ import 'package:natrium_wallet_flutter/dimens.dart'; import 'package:natrium_wallet_flutter/localization.dart'; import 'package:natrium_wallet_flutter/styles.dart'; import 'package:natrium_wallet_flutter/ui/widgets/buttons.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; class IntroBackupSafetyPage extends StatefulWidget { @override diff --git a/lib/ui/intro/intro_backup_seed.dart b/lib/ui/intro/intro_backup_seed.dart index 0e4d4204..b27e29bc 100644 --- a/lib/ui/intro/intro_backup_seed.dart +++ b/lib/ui/intro/intro_backup_seed.dart @@ -13,6 +13,7 @@ import 'package:natrium_wallet_flutter/ui/widgets/buttons.dart'; import 'package:natrium_wallet_flutter/ui/widgets/plainseed_display.dart'; import 'package:natrium_wallet_flutter/util/nanoutil.dart'; import 'package:natrium_wallet_flutter/ui/widgets/mnemonic_display.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; class IntroBackupSeedPage extends StatefulWidget { final String encryptedSeed; diff --git a/lib/ui/intro/intro_import_seed.dart b/lib/ui/intro/intro_import_seed.dart index 14c044be..ded2da34 100755 --- a/lib/ui/intro/intro_import_seed.dart +++ b/lib/ui/intro/intro_import_seed.dart @@ -12,6 +12,7 @@ import 'package:natrium_wallet_flutter/service_locator.dart'; import 'package:natrium_wallet_flutter/ui/util/formatters.dart'; import 'package:natrium_wallet_flutter/ui/util/ui_util.dart'; import 'package:natrium_wallet_flutter/ui/widgets/app_text_field.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; import 'package:natrium_wallet_flutter/ui/widgets/tap_outside_unfocus.dart'; import 'package:natrium_wallet_flutter/util/sharedprefsutil.dart'; diff --git a/lib/ui/intro/intro_password.dart b/lib/ui/intro/intro_password.dart index 68b5cb96..29fc9402 100755 --- a/lib/ui/intro/intro_password.dart +++ b/lib/ui/intro/intro_password.dart @@ -11,6 +11,7 @@ import 'package:natrium_wallet_flutter/app_icons.dart'; import 'package:natrium_wallet_flutter/service_locator.dart'; import 'package:natrium_wallet_flutter/ui/widgets/app_text_field.dart'; import 'package:natrium_wallet_flutter/ui/widgets/buttons.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; import 'package:natrium_wallet_flutter/ui/widgets/security.dart'; import 'package:natrium_wallet_flutter/ui/widgets/tap_outside_unfocus.dart'; import 'package:natrium_wallet_flutter/util/nanoutil.dart'; @@ -47,10 +48,10 @@ class _IntroPasswordState extends State { @override Widget build(BuildContext context) { return Scaffold( - resizeToAvoidBottomInset: false, - backgroundColor: StateContainer.of(context).curTheme.backgroundDark, - body: TapOutsideUnfocus( - child: LayoutBuilder( + resizeToAvoidBottomInset: false, + backgroundColor: StateContainer.of(context).curTheme.backgroundDark, + body: TapOutsideUnfocus( + child: LayoutBuilder( builder: (context, constraints) => SafeArea( minimum: EdgeInsets.only( bottom: MediaQuery.of(context).size.height * 0.035, @@ -82,8 +83,9 @@ class _IntroPasswordState extends State { borderRadius: BorderRadius.circular(50.0)), padding: EdgeInsets.all(0.0), child: Icon(AppIcons.back, - color: - StateContainer.of(context).curTheme.text, + color: StateContainer.of(context) + .curTheme + .text, size: 24)), ), ], @@ -110,124 +112,140 @@ class _IntroPasswordState extends State { end: smallScreen(context) ? 30 : 40, top: 16.0), child: AutoSizeText( - AppLocalization.of(context).passwordWillBeRequiredToOpenParagraph, + AppLocalization.of(context) + .passwordWillBeRequiredToOpenParagraph, style: AppStyles.textStyleParagraph(context), maxLines: 5, stepGranularity: 0.5, ), ), Expanded( - child: KeyboardAvoider( - duration: Duration(milliseconds: 0), - autoScroll: true, - focusPadding: 40, - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - // Create a Password Text Field - AppTextField( - topMargin: 30, - padding: EdgeInsetsDirectional.only(start: 16, end: 16), - focusNode: createPasswordFocusNode, - controller: createPasswordController, - textInputAction: TextInputAction.next, - maxLines: 1, - autocorrect: false, - onChanged: (String newText) { - if (passwordError != null) { - setState(() { - passwordError = null; - }); - } - if (confirmPasswordController.text == createPasswordController.text) { - if (mounted) { - setState(() { - passwordsMatch = true; - }); - } - } else { - if (mounted) { - setState(() { - passwordsMatch = false; - }); - } - } - }, - hintText: AppLocalization.of(context).createPasswordHint, - keyboardType: TextInputType.text, - obscureText: true, - textAlign: TextAlign.center, - style: TextStyle( - fontWeight: FontWeight.w700, - fontSize: 16.0, - color: - this.passwordsMatch ? StateContainer.of(context).curTheme.primary : StateContainer.of(context).curTheme.text, - fontFamily: 'NunitoSans', - ), - onSubmitted: (text) { - confirmPasswordFocusNode.requestFocus(); - }, - ), - // Confirm Password Text Field - AppTextField( - topMargin: 20, - padding: EdgeInsetsDirectional.only(start: 16, end: 16), - focusNode: confirmPasswordFocusNode, - controller: confirmPasswordController, - textInputAction: TextInputAction.done, - maxLines: 1, - autocorrect: false, - onChanged: (String newText) { - if (passwordError != null) { - setState(() { - passwordError = null; - }); - } - if (confirmPasswordController.text == createPasswordController.text) { - if (mounted) { - setState(() { - passwordsMatch = true; - }); - } - } else { - if (mounted) { - setState(() { - passwordsMatch = false; - }); - } - } - }, - hintText: AppLocalization.of(context).confirmPasswordHint, - keyboardType: TextInputType.text, - obscureText: true, - textAlign: TextAlign.center, - style: TextStyle( - fontWeight: FontWeight.w700, - fontSize: 16.0, - color: - this.passwordsMatch ? StateContainer.of(context).curTheme.primary : StateContainer.of(context).curTheme.text, - fontFamily: 'NunitoSans', - ), - ), - // Error Text - Container( - alignment: AlignmentDirectional(0, 0), - margin: EdgeInsets.only(top: 3), - child: Text(this.passwordError == null ? "" : passwordError, - style: TextStyle( - fontSize: 14.0, - color: - StateContainer.of(context) - .curTheme - .primary, - fontFamily: 'NunitoSans', - fontWeight: FontWeight.w600, - )), - ), - ] - ) - ) - ) + child: KeyboardAvoider( + duration: Duration(milliseconds: 0), + autoScroll: true, + focusPadding: 40, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // Create a Password Text Field + AppTextField( + topMargin: 30, + padding: EdgeInsetsDirectional.only( + start: 16, end: 16), + focusNode: createPasswordFocusNode, + controller: createPasswordController, + textInputAction: TextInputAction.next, + maxLines: 1, + autocorrect: false, + onChanged: (String newText) { + if (passwordError != null) { + setState(() { + passwordError = null; + }); + } + if (confirmPasswordController.text == + createPasswordController.text) { + if (mounted) { + setState(() { + passwordsMatch = true; + }); + } + } else { + if (mounted) { + setState(() { + passwordsMatch = false; + }); + } + } + }, + hintText: AppLocalization.of(context) + .createPasswordHint, + keyboardType: TextInputType.text, + obscureText: true, + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 16.0, + color: this.passwordsMatch + ? StateContainer.of(context) + .curTheme + .primary + : StateContainer.of(context) + .curTheme + .text, + fontFamily: 'NunitoSans', + ), + onSubmitted: (text) { + confirmPasswordFocusNode.requestFocus(); + }, + ), + // Confirm Password Text Field + AppTextField( + topMargin: 20, + padding: EdgeInsetsDirectional.only( + start: 16, end: 16), + focusNode: confirmPasswordFocusNode, + controller: confirmPasswordController, + textInputAction: TextInputAction.done, + maxLines: 1, + autocorrect: false, + onChanged: (String newText) { + if (passwordError != null) { + setState(() { + passwordError = null; + }); + } + if (confirmPasswordController.text == + createPasswordController.text) { + if (mounted) { + setState(() { + passwordsMatch = true; + }); + } + } else { + if (mounted) { + setState(() { + passwordsMatch = false; + }); + } + } + }, + hintText: AppLocalization.of(context) + .confirmPasswordHint, + keyboardType: TextInputType.text, + obscureText: true, + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 16.0, + color: this.passwordsMatch + ? StateContainer.of(context) + .curTheme + .primary + : StateContainer.of(context) + .curTheme + .text, + fontFamily: 'NunitoSans', + ), + ), + // Error Text + Container( + alignment: AlignmentDirectional(0, 0), + margin: EdgeInsets.only(top: 3), + child: Text( + this.passwordError == null + ? "" + : passwordError, + style: TextStyle( + fontSize: 14.0, + color: StateContainer.of(context) + .curTheme + .primary, + fontFamily: 'NunitoSans', + fontWeight: FontWeight.w600, + )), + ), + ]))) ], ), ), @@ -238,9 +256,12 @@ class _IntroPasswordState extends State { Row( children: [ // Next Button - AppButton.buildAppButton(context, AppButtonType.PRIMARY, - AppLocalization.of(context).nextButton, Dimens.BUTTON_TOP_DIMENS, onPressed: () async { - await submitAndEncrypt(); + AppButton.buildAppButton( + context, + AppButtonType.PRIMARY, + AppLocalization.of(context).nextButton, + Dimens.BUTTON_TOP_DIMENS, onPressed: () async { + await submitAndEncrypt(); }), ], ), @@ -261,34 +282,37 @@ class _IntroPasswordState extends State { ], ), ), - ) - ) - ); + ))); } Future submitAndEncrypt() async { - if (createPasswordController.text.isEmpty || confirmPasswordController.text.isEmpty) { + if (createPasswordController.text.isEmpty || + confirmPasswordController.text.isEmpty) { if (mounted) { setState(() { passwordError = AppLocalization.of(context).passwordBlank; }); } - } else if (createPasswordController.text != confirmPasswordController.text) { + } else if (createPasswordController.text != + confirmPasswordController.text) { if (mounted) { setState(() { passwordError = AppLocalization.of(context).passwordsDontMatch; }); } } else if (widget.seed != null) { - String encryptedSeed = NanoHelpers.byteToHex(NanoCrypt.encrypt(widget.seed, confirmPasswordController.text)); + String encryptedSeed = NanoHelpers.byteToHex( + NanoCrypt.encrypt(widget.seed, confirmPasswordController.text)); await sl.get().setSeed(encryptedSeed); - StateContainer.of(context).setEncryptedSecret(NanoHelpers.byteToHex(NanoCrypt.encrypt(widget.seed, await sl.get().getSessionKey()))); + StateContainer.of(context).setEncryptedSecret(NanoHelpers.byteToHex( + NanoCrypt.encrypt( + widget.seed, await sl.get().getSessionKey()))); await sl.get().dropAccounts(); await NanoUtil().loginAccount(widget.seed, context); StateContainer.of(context).requestUpdate(); - String pin = await Navigator.of(context).push( - MaterialPageRoute(builder: (BuildContext context) { - return PinScreen(PinOverlayType.NEW_PIN); + String pin = await Navigator.of(context) + .push(MaterialPageRoute(builder: (BuildContext context) { + return PinScreen(PinOverlayType.NEW_PIN); })); if (pin != null && pin.length > 5) { _pinEnteredCallback(pin); @@ -296,26 +320,30 @@ class _IntroPasswordState extends State { } else { // Generate a new seed and encrypt String seed = NanoSeeds.generateSeed(); - String encryptedSeed = NanoHelpers.byteToHex(NanoCrypt.encrypt(seed, confirmPasswordController.text)); + String encryptedSeed = NanoHelpers.byteToHex( + NanoCrypt.encrypt(seed, confirmPasswordController.text)); await sl.get().setSeed(encryptedSeed); // Also encrypt it with the session key, so user doesnt need password to sign blocks within the app - StateContainer.of(context).setEncryptedSecret(NanoHelpers.byteToHex(NanoCrypt.encrypt(seed, await sl.get().getSessionKey()))); + StateContainer.of(context).setEncryptedSecret(NanoHelpers.byteToHex( + NanoCrypt.encrypt(seed, await sl.get().getSessionKey()))); // Update wallet - NanoUtil().loginAccount(await StateContainer.of(context).getSeed(), context).then((_) { + NanoUtil() + .loginAccount(await StateContainer.of(context).getSeed(), context) + .then((_) { StateContainer.of(context).requestUpdate(); - Navigator.of(context) - .pushNamed('/intro_backup_safety'); + Navigator.of(context).pushNamed('/intro_backup_safety'); }); - } + } } void _pinEnteredCallback(String pin) async { await sl.get().writePin(pin); - PriceConversion conversion = await sl.get().getPriceConversion(); + PriceConversion conversion = + await sl.get().getPriceConversion(); StateContainer.of(context).requestSubscribe(); // Update wallet - Navigator.of(context) - .pushNamedAndRemoveUntil('/home', (Route route) => false, arguments: conversion); - + Navigator.of(context).pushNamedAndRemoveUntil( + '/home', (Route route) => false, + arguments: conversion); } } diff --git a/lib/ui/intro/intro_password_on_launch.dart b/lib/ui/intro/intro_password_on_launch.dart index 91540985..ab7425a8 100755 --- a/lib/ui/intro/intro_password_on_launch.dart +++ b/lib/ui/intro/intro_password_on_launch.dart @@ -9,6 +9,7 @@ import 'package:natrium_wallet_flutter/localization.dart'; import 'package:natrium_wallet_flutter/app_icons.dart'; import 'package:natrium_wallet_flutter/service_locator.dart'; import 'package:natrium_wallet_flutter/ui/widgets/buttons.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; import 'package:natrium_wallet_flutter/ui/widgets/security.dart'; import 'package:natrium_wallet_flutter/util/nanoutil.dart'; import 'package:natrium_wallet_flutter/model/vault.dart'; @@ -77,7 +78,8 @@ class _IntroPasswordOnLaunchState extends State { ), alignment: AlignmentDirectional(-1, 0), child: AutoSizeText( - AppLocalization.of(context).requireAPasswordToOpenHeader, + AppLocalization.of(context) + .requireAPasswordToOpenHeader, maxLines: 3, stepGranularity: 0.5, style: AppStyles.textStyleHeaderColored(context), @@ -90,7 +92,8 @@ class _IntroPasswordOnLaunchState extends State { end: smallScreen(context) ? 30 : 40, top: 16.0), child: AutoSizeText( - AppLocalization.of(context).createPasswordFirstParagraph, + AppLocalization.of(context) + .createPasswordFirstParagraph, style: AppStyles.textStyleParagraph(context), maxLines: 5, stepGranularity: 0.5, @@ -102,7 +105,8 @@ class _IntroPasswordOnLaunchState extends State { end: smallScreen(context) ? 30 : 40, top: 8), child: AutoSizeText( - AppLocalization.of(context).createPasswordSecondParagraph, + AppLocalization.of(context) + .createPasswordSecondParagraph, style: AppStyles.textStyleParagraphPrimary(context), maxLines: 4, stepGranularity: 0.5, @@ -118,25 +122,31 @@ class _IntroPasswordOnLaunchState extends State { Row( children: [ // Skip Button - AppButton.buildAppButton(context, AppButtonType.PRIMARY, - AppLocalization.of(context).noSkipButton, Dimens.BUTTON_TOP_DIMENS, onPressed: () async { + AppButton.buildAppButton( + context, + AppButtonType.PRIMARY, + AppLocalization.of(context).noSkipButton, + Dimens.BUTTON_TOP_DIMENS, onPressed: () async { if (widget.seed != null) { - await sl.get().setSeed(widget.seed); - await sl.get().dropAccounts(); - await NanoUtil().loginAccount(widget.seed, context); - StateContainer.of(context).requestUpdate(); - String pin = await Navigator.of(context).push( - MaterialPageRoute(builder: - (BuildContext context) { - return PinScreen( - PinOverlayType.NEW_PIN, - ); - })); - if (pin != null && pin.length > 5) { - _pinEnteredCallback(pin); - } + await sl.get().setSeed(widget.seed); + await sl.get().dropAccounts(); + await NanoUtil().loginAccount(widget.seed, context); + StateContainer.of(context).requestUpdate(); + String pin = await Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) { + return PinScreen( + PinOverlayType.NEW_PIN, + ); + })); + if (pin != null && pin.length > 5) { + _pinEnteredCallback(pin); + } } else { - sl.get().setSeed(NanoSeeds.generateSeed()).then((result) { + sl + .get() + .setSeed(NanoSeeds.generateSeed()) + .then((result) { // Update wallet StateContainer.of(context).getSeed().then((seed) { NanoUtil().loginAccount(seed, context).then((_) { @@ -158,8 +168,8 @@ class _IntroPasswordOnLaunchState extends State { AppButtonType.PRIMARY_OUTLINE, AppLocalization.of(context).yesButton, Dimens.BUTTON_BOTTOM_DIMENS, onPressed: () { - Navigator.of(context) - .pushNamed('/intro_password', arguments: widget.seed); + Navigator.of(context).pushNamed('/intro_password', + arguments: widget.seed); }), ], ), @@ -174,10 +184,12 @@ class _IntroPasswordOnLaunchState extends State { void _pinEnteredCallback(String pin) async { await sl.get().writePin(pin); - PriceConversion conversion = await sl.get().getPriceConversion(); + PriceConversion conversion = + await sl.get().getPriceConversion(); StateContainer.of(context).requestSubscribe(); // Update wallet - Navigator.of(context) - .pushNamedAndRemoveUntil('/home', (Route route) => false, arguments: conversion); + Navigator.of(context).pushNamedAndRemoveUntil( + '/home', (Route route) => false, + arguments: conversion); } } diff --git a/lib/ui/lock_screen.dart b/lib/ui/lock_screen.dart index 4219e1e1..0017bdd6 100644 --- a/lib/ui/lock_screen.dart +++ b/lib/ui/lock_screen.dart @@ -18,6 +18,7 @@ import 'package:natrium_wallet_flutter/appstate_container.dart'; import 'package:natrium_wallet_flutter/localization.dart'; import 'package:natrium_wallet_flutter/dimens.dart'; import 'package:natrium_wallet_flutter/ui/util/routes.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; class AppLockScreen extends StatefulWidget { @override diff --git a/lib/ui/password_lock_screen.dart b/lib/ui/password_lock_screen.dart index 0951e584..7a35b2b1 100644 --- a/lib/ui/password_lock_screen.dart +++ b/lib/ui/password_lock_screen.dart @@ -18,6 +18,7 @@ import 'package:natrium_wallet_flutter/appstate_container.dart'; import 'package:natrium_wallet_flutter/localization.dart'; import 'package:natrium_wallet_flutter/dimens.dart'; import 'package:natrium_wallet_flutter/util/sharedprefsutil.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; class AppPasswordLockScreen extends StatefulWidget { @override diff --git a/lib/ui/popup_button.dart b/lib/ui/popup_button.dart index 065e0b01..e8562c82 100644 --- a/lib/ui/popup_button.dart +++ b/lib/ui/popup_button.dart @@ -14,6 +14,7 @@ import 'package:natrium_wallet_flutter/ui/send/send_confirm_sheet.dart'; import 'package:natrium_wallet_flutter/ui/send/send_sheet.dart'; import 'package:natrium_wallet_flutter/ui/util/ui_util.dart'; import 'package:natrium_wallet_flutter/ui/widgets/dialog.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; import 'package:natrium_wallet_flutter/ui/widgets/sheet_util.dart'; import 'package:natrium_wallet_flutter/util/hapticutil.dart'; import 'package:natrium_wallet_flutter/util/manta.dart'; diff --git a/lib/ui/send/send_sheet.dart b/lib/ui/send/send_sheet.dart index 8f620f0d..3c4d6eb8 100755 --- a/lib/ui/send/send_sheet.dart +++ b/lib/ui/send/send_sheet.dart @@ -27,6 +27,7 @@ import 'package:natrium_wallet_flutter/ui/widgets/dialog.dart'; import 'package:natrium_wallet_flutter/ui/widgets/one_or_three_address_text.dart'; import 'package:natrium_wallet_flutter/ui/util/formatters.dart'; import 'package:natrium_wallet_flutter/ui/util/ui_util.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; import 'package:natrium_wallet_flutter/ui/widgets/sheet_util.dart'; import 'package:natrium_wallet_flutter/util/manta.dart'; import 'package:natrium_wallet_flutter/util/numberutil.dart'; @@ -345,9 +346,11 @@ class _SendSheetState extends State { locale: StateContainer .of(context) .currencyLocale) - : "Ó¾" + StateContainer.of(context) - .wallet - .getAccountBalanceDisplay(), + : "Ó¾" + + StateContainer.of( + context) + .wallet + .getAccountBalanceDisplay(), style: TextStyle( color: StateContainer.of(context) @@ -599,7 +602,7 @@ class _SendSheetState extends State { } log.e( 'Failed to make manta request ${e.toString()}', - e); + error: e); UIUtil.showSnackbar( AppLocalization.of(context).mantaError, context); diff --git a/lib/ui/settings/backupseed_sheet.dart b/lib/ui/settings/backupseed_sheet.dart index fcf92d29..6531aef0 100644 --- a/lib/ui/settings/backupseed_sheet.dart +++ b/lib/ui/settings/backupseed_sheet.dart @@ -13,6 +13,7 @@ import 'package:natrium_wallet_flutter/ui/widgets/buttons.dart'; import 'package:natrium_wallet_flutter/styles.dart'; import 'package:natrium_wallet_flutter/util/caseconverter.dart'; import 'package:natrium_wallet_flutter/util/user_data_util.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; class AppSeedBackupSheet { String _seed; @@ -75,17 +76,18 @@ class AppSeedBackupSheet { Container( margin: EdgeInsets.only(top: 15.0), constraints: BoxConstraints( - maxWidth: MediaQuery.of(context) - .size - .width - - 140), + maxWidth: + MediaQuery.of(context).size.width - + 140), child: Column( children: [ AutoSizeText( CaseChange.toUpperCase( showMnemonic - ? AppLocalization.of(context).secretPhrase - : AppLocalization.of(context).seed, + ? AppLocalization.of(context) + .secretPhrase + : AppLocalization.of(context) + .seed, context), style: AppStyles.textStyleHeader( context), @@ -166,10 +168,13 @@ class AppSeedBackupSheet { ? AppButtonType.SUCCESS : AppButtonType.PRIMARY, _mnemonicCopied - ? AppLocalization.of(context).secretPhraseCopied - : AppLocalization.of(context).secretPhraseCopy, + ? AppLocalization.of(context) + .secretPhraseCopied + : AppLocalization.of(context) + .secretPhraseCopy, Dimens.BUTTON_BOTTOM_DIMENS, onPressed: () { - UserDataUtil.setSecureClipboardItem(_mnemonic.join(" ")); + UserDataUtil.setSecureClipboardItem( + _mnemonic.join(" ")); setState(() { // Set copied style _mnemonicCopied = true; @@ -196,7 +201,10 @@ class AppSeedBackupSheet { _seedCopied ? AppButtonType.SUCCESS : AppButtonType.PRIMARY, - _seedCopied ? AppLocalization.of(context).seedCopiedShort : AppLocalization.of(context).copySeed, + _seedCopied + ? AppLocalization.of(context) + .seedCopiedShort + : AppLocalization.of(context).copySeed, Dimens.BUTTON_BOTTOM_DIMENS, onPressed: () { UserDataUtil.setSecureClipboardItem(_seed); setState(() { diff --git a/lib/ui/settings/changerepresentative_sheet.dart b/lib/ui/settings/changerepresentative_sheet.dart index d359159e..d58827b4 100755 --- a/lib/ui/settings/changerepresentative_sheet.dart +++ b/lib/ui/settings/changerepresentative_sheet.dart @@ -19,6 +19,7 @@ import 'package:natrium_wallet_flutter/ui/widgets/app_simpledialog.dart'; import 'package:natrium_wallet_flutter/ui/widgets/sheet_util.dart'; import 'package:natrium_wallet_flutter/ui/widgets/sheets.dart'; import 'package:natrium_wallet_flutter/ui/widgets/buttons.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; import 'package:natrium_wallet_flutter/ui/widgets/dialog.dart'; import 'package:natrium_wallet_flutter/ui/widgets/security.dart'; import 'package:natrium_wallet_flutter/ui/util/routes.dart'; @@ -318,7 +319,7 @@ class AppChangeRepresentativeSheet { AppLocalization.of(context).changeRepSucces, context); Navigator.of(context).popUntil(RouteUtils.withNameLike('/home')); } catch (e) { - sl.get().e("Failed to change", e); + sl.get().e("Failed to change", error: e); if (_animationOpen) { Navigator.of(context).pop(); } diff --git a/lib/ui/settings/changerepresentativemanualentry_sheet.dart b/lib/ui/settings/changerepresentativemanualentry_sheet.dart index a2b5167e..6c0eadca 100755 --- a/lib/ui/settings/changerepresentativemanualentry_sheet.dart +++ b/lib/ui/settings/changerepresentativemanualentry_sheet.dart @@ -380,7 +380,7 @@ class _ChangeRepManualSheetState extends State { AppLocalization.of(context).changeRepSucces, context); Navigator.of(context).popUntil(RouteUtils.withNameLike('/home')); } catch (e) { - sl.get().e("Failed to change", e); + sl.get().e("Failed to change", error: e); if (_animationOpen) { Navigator.of(context).pop(); } diff --git a/lib/ui/settings/contacts_widget.dart b/lib/ui/settings/contacts_widget.dart index 72201b8e..ba6339a9 100644 --- a/lib/ui/settings/contacts_widget.dart +++ b/lib/ui/settings/contacts_widget.dart @@ -23,6 +23,7 @@ import 'package:natrium_wallet_flutter/model/db/contact.dart'; import 'package:natrium_wallet_flutter/ui/contacts/add_contact.dart'; import 'package:natrium_wallet_flutter/ui/contacts/contact_details.dart'; import 'package:natrium_wallet_flutter/ui/widgets/buttons.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; import 'package:natrium_wallet_flutter/ui/util/ui_util.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flare_flutter/flare_actor.dart'; @@ -182,7 +183,7 @@ class _ContactsListState extends State { AppLocalization.of(context).noContactsImport, context); } } catch (e) { - log.e(e.toString(), e); + log.e(e.toString(), error: e); UIUtil.showSnackbar( AppLocalization.of(context).contactsImportErr, context); return; diff --git a/lib/ui/settings/settings_drawer.dart b/lib/ui/settings/settings_drawer.dart index 4924618b..e90e29a9 100755 --- a/lib/ui/settings/settings_drawer.dart +++ b/lib/ui/settings/settings_drawer.dart @@ -38,6 +38,7 @@ import 'package:natrium_wallet_flutter/ui/settings/contacts_widget.dart'; import 'package:natrium_wallet_flutter/ui/transfer/transfer_overview_sheet.dart'; import 'package:natrium_wallet_flutter/ui/transfer/transfer_confirm_sheet.dart'; import 'package:natrium_wallet_flutter/ui/transfer/transfer_complete_sheet.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; import 'package:natrium_wallet_flutter/ui/widgets/dialog.dart'; import 'package:natrium_wallet_flutter/ui/widgets/security.dart'; import 'package:natrium_wallet_flutter/ui/util/ui_util.dart'; diff --git a/lib/ui/settings/settings_list_item.dart b/lib/ui/settings/settings_list_item.dart index 9164b432..738b1398 100644 --- a/lib/ui/settings/settings_list_item.dart +++ b/lib/ui/settings/settings_list_item.dart @@ -5,6 +5,7 @@ import 'package:natrium_wallet_flutter/app_icons.dart'; import 'package:natrium_wallet_flutter/styles.dart'; import 'package:natrium_wallet_flutter/model/setting_item.dart'; import 'package:natrium_wallet_flutter/ui/util/ui_util.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; class AppSettings { //Settings item with a dropdown option @@ -79,12 +80,8 @@ class AppSettings { } //Settings item with direct functionality and two lines - static Widget buildSettingsListItemDoubleLineTwo( - BuildContext context, - String heading, - String text, - IconData icon, - Function onPressed, + static Widget buildSettingsListItemDoubleLineTwo(BuildContext context, + String heading, String text, IconData icon, Function onPressed, {bool disabled = false}) { return IgnorePointer( ignoring: disabled, @@ -185,7 +182,9 @@ class AppSettings { ? 0 : settingIcon == AppIcons.backupseed ? 1 - : settingIcon == AppIcons.transferfunds ? 2 : 3, + : settingIcon == AppIcons.transferfunds + ? 2 + : 3, bottom: 3, end: settingIcon == AppIcons.logout ? 0 @@ -193,7 +192,9 @@ class AppSettings { ? 6 : settingIcon == AppIcons.backupseed ? 5 - : settingIcon == AppIcons.transferfunds ? 4 : 3, + : settingIcon == AppIcons.transferfunds + ? 4 + : 3, ), ), ), diff --git a/lib/ui/transfer/transfer_confirm_sheet.dart b/lib/ui/transfer/transfer_confirm_sheet.dart index ccbbe940..a6181234 100755 --- a/lib/ui/transfer/transfer_confirm_sheet.dart +++ b/lib/ui/transfer/transfer_confirm_sheet.dart @@ -28,9 +28,11 @@ class AppTransferConfirmSheet extends StatefulWidget { final Map privKeyBalanceMap; final Function errorCallback; - AppTransferConfirmSheet({this.privKeyBalanceMap, this.errorCallback}) : super(); + AppTransferConfirmSheet({this.privKeyBalanceMap, this.errorCallback}) + : super(); - _AppTransferConfirmSheetState createState() => _AppTransferConfirmSheetState(); + _AppTransferConfirmSheetState createState() => + _AppTransferConfirmSheetState(); } class _AppTransferConfirmSheetState extends State { @@ -56,7 +58,8 @@ class _AppTransferConfirmSheetState extends State { totalToTransfer += BigInt.parse(accountBalanceItem.balance) + BigInt.parse(accountBalanceItem.pending); }); - this.totalAsReadableAmount = NumberUtil.getRawAsUsableString(totalToTransfer.toString()); + this.totalAsReadableAmount = + NumberUtil.getRawAsUsableString(totalToTransfer.toString()); } @override @@ -81,8 +84,7 @@ class _AppTransferConfirmSheetState extends State { margin: EdgeInsets.only(top: 30.0, left: 70, right: 70), child: AutoSizeText( CaseChange.toUpperCase( - AppLocalization.of(context).transferHeader, - context), + AppLocalization.of(context).transferHeader, context), style: AppStyles.textStyleHeader(context), textAlign: TextAlign.center, maxLines: 2, @@ -101,37 +103,28 @@ class _AppTransferConfirmSheetState extends State { children: [ Container( margin: EdgeInsets.symmetric( - horizontal: - smallScreen(context) ? 35 : 60), + horizontal: smallScreen(context) ? 35 : 60), child: Text( AppLocalization.of(context) .transferConfirmInfo - .replaceAll( - "%1", totalAsReadableAmount), - style: AppStyles.textStyleParagraphPrimary( - context), + .replaceAll("%1", totalAsReadableAmount), + style: AppStyles.textStyleParagraphPrimary(context), textAlign: TextAlign.start, )), Container( margin: EdgeInsets.symmetric( - horizontal: - smallScreen(context) ? 35 : 60), + horizontal: smallScreen(context) ? 35 : 60), child: Text( - AppLocalization.of(context) - .transferConfirmInfoSecond, - style: - AppStyles.textStyleParagraph(context), + AppLocalization.of(context).transferConfirmInfoSecond, + style: AppStyles.textStyleParagraph(context), textAlign: TextAlign.start, )), Container( margin: EdgeInsets.symmetric( - horizontal: - smallScreen(context) ? 35 : 60), + horizontal: smallScreen(context) ? 35 : 60), child: Text( - AppLocalization.of(context) - .transferConfirmInfoThird, - style: - AppStyles.textStyleParagraph(context), + AppLocalization.of(context).transferConfirmInfoThird, + style: AppStyles.textStyleParagraph(context), textAlign: TextAlign.start, )), ], @@ -148,19 +141,17 @@ class _AppTransferConfirmSheetState extends State { context, AppButtonType.PRIMARY, CaseChange.toUpperCase( - AppLocalization.of(context).confirm, - context), + AppLocalization.of(context).confirm, context), Dimens.BUTTON_TOP_DIMENS, onPressed: () async { animationOpen = true; - Navigator.of(context).push( - AnimationLoadingOverlay( - AnimationType.TRANSFER_TRANSFERRING, - StateContainer.of(context) - .curTheme - .animationOverlayStrong, - StateContainer.of(context) - .curTheme - .animationOverlayMedium, onPoppedCallback: () { + Navigator.of(context).push(AnimationLoadingOverlay( + AnimationType.TRANSFER_TRANSFERRING, + StateContainer.of(context) + .curTheme + .animationOverlayStrong, + StateContainer.of(context) + .curTheme + .animationOverlayMedium, onPoppedCallback: () { animationOpen = false; })); await processWallets(); @@ -173,9 +164,7 @@ class _AppTransferConfirmSheetState extends State { AppButton.buildAppButton( context, AppButtonType.PRIMARY_OUTLINE, - AppLocalization.of(context) - .cancel - .toUpperCase(), + AppLocalization.of(context).cancel.toUpperCase(), Dimens.BUTTON_BOTTOM_DIMENS, onPressed: () { Navigator.of(context).pop(); }), @@ -192,8 +181,10 @@ class _AppTransferConfirmSheetState extends State { Future _getPrivKey(int index) async { String seed; - if (StateContainer.of(context).encryptedSecret != null) { - seed = NanoHelpers.byteToHex(NanoCrypt.decrypt(StateContainer.of(context).encryptedSecret, await sl.get().getSessionKey())); + if (StateContainer.of(context).encryptedSecret != null) { + seed = NanoHelpers.byteToHex(NanoCrypt.decrypt( + StateContainer.of(context).encryptedSecret, + await sl.get().getSessionKey())); } else { seed = await sl.get().getSeed(); } @@ -205,39 +196,39 @@ class _AppTransferConfirmSheetState extends State { try { state.lockCallback(); for (String account in widget.privKeyBalanceMap.keys) { - AccountBalanceItem balanceItem = widget.privKeyBalanceMap[account]; + AccountBalanceItem balanceItem = widget.privKeyBalanceMap[account]; // Get frontiers first - AccountInfoResponse resp = await sl.get().getAccountInfo(account); + AccountInfoResponse resp = + await sl.get().getAccountInfo(account); if (!resp.unopened) { balanceItem.frontier = resp.frontier; } // Receive pending blocks - PendingResponse pr = await sl.get().getPending(account, 20); + PendingResponse pr = + await sl.get().getPending(account, 20); Map pendingBlocks = pr.blocks; for (String hash in pendingBlocks.keys) { PendingResponseItem item = pendingBlocks[hash]; if (balanceItem.frontier != null) { - ProcessResponse resp = await sl.get().requestReceive( - AppWallet.defaultRepresentative, - balanceItem.frontier, - item.amount, - hash, - account, - balanceItem.privKey - ); - if (resp.hash != null) { + ProcessResponse resp = await sl + .get() + .requestReceive( + AppWallet.defaultRepresentative, + balanceItem.frontier, + item.amount, + hash, + account, + balanceItem.privKey); + if (resp.hash != null) { balanceItem.frontier = resp.hash; totalTransferred += BigInt.parse(item.amount); } } else { - ProcessResponse resp = await sl.get().requestOpen( - item.amount, - hash, - account, - balanceItem.privKey - ); + ProcessResponse resp = await sl + .get() + .requestOpen(item.amount, hash, account, balanceItem.privKey); if (resp.hash != null) { - balanceItem.frontier = resp.hash; + balanceItem.frontier = resp.hash; totalTransferred += BigInt.parse(item.amount); } } @@ -247,14 +238,13 @@ class _AppTransferConfirmSheetState extends State { // Process send from this account resp = await sl.get().getAccountInfo(account); ProcessResponse sendResp = await sl.get().requestSend( - AppWallet.defaultRepresentative, - resp.frontier, - resp.balance, - state.wallet.address, - account, - balanceItem.privKey, - max: true - ); + AppWallet.defaultRepresentative, + resp.frontier, + resp.balance, + state.wallet.address, + account, + balanceItem.privKey, + max: true); if (sendResp.hash != null) { totalTransferred += BigInt.parse(balanceItem.balance); } @@ -264,7 +254,7 @@ class _AppTransferConfirmSheetState extends State { Navigator.of(context).pop(); } widget.errorCallback(); - sl.get().e("Error processing wallet", e); + sl.get().e("Error processing wallet", error: e); return; } finally { state.unlockCallback(); @@ -272,40 +262,40 @@ class _AppTransferConfirmSheetState extends State { try { state.lockCallback(); // Receive all new blocks to our own account - PendingResponse pr = await sl.get().getPending(state.wallet.address, 20, includeActive: true); + PendingResponse pr = await sl + .get() + .getPending(state.wallet.address, 20, includeActive: true); Map pendingBlocks = pr.blocks; for (String hash in pendingBlocks.keys) { PendingResponseItem item = pendingBlocks[hash]; if (state.wallet.openBlock != null) { ProcessResponse resp = await sl.get().requestReceive( - state.wallet.representative, - state.wallet.frontier, - item.amount, - hash, - state.wallet.address, - await _getPrivKey(state.selectedAccount.index) - ); + state.wallet.representative, + state.wallet.frontier, + item.amount, + hash, + state.wallet.address, + await _getPrivKey(state.selectedAccount.index)); if (resp.hash != null) { state.wallet.frontier = resp.hash; } } else { ProcessResponse resp = await sl.get().requestOpen( - item.amount, - hash, - state.wallet.address, - await _getPrivKey(state.selectedAccount.index), - representative: state.wallet.representative - ); + item.amount, + hash, + state.wallet.address, + await _getPrivKey(state.selectedAccount.index), + representative: state.wallet.representative); if (resp.hash != null) { state.wallet.frontier = resp.hash; - state.wallet.openBlock = resp.hash; + state.wallet.openBlock = resp.hash; } } } state.requestUpdate(); } catch (e) { // Less-important error - sl.get().e("Error processing wallet", e); + sl.get().e("Error processing wallet", error: e); } finally { state.unlockCallback(); } diff --git a/lib/ui/transfer/transfer_overview_sheet.dart b/lib/ui/transfer/transfer_overview_sheet.dart index a73ad820..a8d5237b 100755 --- a/lib/ui/transfer/transfer_overview_sheet.dart +++ b/lib/ui/transfer/transfer_overview_sheet.dart @@ -206,11 +206,10 @@ class AppTransferOverviewSheet { Dimens.BUTTON_BOTTOM_DIMENS, onPressed: () { Sheets.showAppHeightNineSheet( - context: context, - widget: TransferManualEntrySheet( - validSeedCallback: manualEntryCallback, - ) - ); + context: context, + widget: TransferManualEntrySheet( + validSeedCallback: manualEntryCallback, + )); }, ), ], @@ -241,13 +240,13 @@ class AppTransferOverviewSheet { // Get accounts from seed List accounts = await getAccountsFromSeed(context, seed); try { - AccountsBalancesResponse resp = await sl.get().requestAccountsBalances(accounts); + AccountsBalancesResponse resp = + await sl.get().requestAccountsBalances(accounts); if (_animationOpen) { Navigator.of(context).pop(); } List accountsToRemove = List(); - resp.balances - .forEach((String account, AccountBalanceItem balItem) { + resp.balances.forEach((String account, AccountBalanceItem balItem) { BigInt balance = BigInt.parse(balItem.balance); BigInt pending = BigInt.parse(balItem.pending); if (balance + pending == BigInt.zero) { @@ -271,18 +270,17 @@ class AppTransferOverviewSheet { .fire(TransferConfirmEvent(balMap: privKeyBalanceMap)); Navigator.of(context).pop(); } catch (e) { - sl.get().e("error", e); + sl.get().e("error", error: e); if (_animationOpen) { Navigator.of(context).pop(); } - UIUtil.showSnackbar( - AppLocalization.of(context).sendError, - context); + UIUtil.showSnackbar(AppLocalization.of(context).sendError, context); } } /// Get NUM_SWEEP accounts from seed to request balances for - Future> getAccountsFromSeed(BuildContext context, String seed) async { + Future> getAccountsFromSeed( + BuildContext context, String seed) async { List accountsToRequest = List(); String privKey; String address; diff --git a/lib/ui/widgets/app_text_field.dart b/lib/ui/widgets/app_text_field.dart index bacfbee9..5ab5632a 100644 --- a/lib/ui/widgets/app_text_field.dart +++ b/lib/ui/widgets/app_text_field.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:natrium_wallet_flutter/appstate_container.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; /// TextField button class TextFieldButton extends StatelessWidget { @@ -12,23 +13,20 @@ class TextFieldButton extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - height: 48, - width: 48, - child: FlatButton( - padding: EdgeInsets.all(14.0), - highlightColor: - StateContainer.of(context).curTheme.primary15, - splashColor: StateContainer.of(context).curTheme.primary30, - onPressed: () { - onPressed != null ? onPressed() : null; - }, - child: Icon(icon, - size: 20, - color: StateContainer.of(context).curTheme.primary), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(200.0)), - ) - ); + height: 48, + width: 48, + child: FlatButton( + padding: EdgeInsets.all(14.0), + highlightColor: StateContainer.of(context).curTheme.primary15, + splashColor: StateContainer.of(context).curTheme.primary30, + onPressed: () { + onPressed != null ? onPressed() : null; + }, + child: Icon(icon, + size: 20, color: StateContainer.of(context).curTheme.primary), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(200.0)), + )); } } @@ -63,36 +61,35 @@ class AppTextField extends StatefulWidget { final bool obscureText; final bool autofocus; - AppTextField({ - this.focusNode, - this.controller, - this.cursorColor, - this.inputFormatters, - this.textInputAction, - this.hintText, - this.prefixButton, - this.suffixButton, - this.fadePrefixOnCondition, - this.prefixShowFirstCondition, - this.fadeSuffixOnCondition, - this.suffixShowFirstCondition, - this.overrideTextFieldWidget, - this.keyboardType, - this.onSubmitted, - this.onChanged, - this.style, - this.leftMargin, - this.rightMargin, - this.obscureText = false, - this.textAlign = TextAlign.center, - this.keyboardAppearance = Brightness.dark, - this.autocorrect = true, - this.maxLines = 1, - this.padding = EdgeInsets.zero, - this.buttonFadeDurationMs = 100, - this.topMargin = 0, - this.autofocus = false - }); + AppTextField( + {this.focusNode, + this.controller, + this.cursorColor, + this.inputFormatters, + this.textInputAction, + this.hintText, + this.prefixButton, + this.suffixButton, + this.fadePrefixOnCondition, + this.prefixShowFirstCondition, + this.fadeSuffixOnCondition, + this.suffixShowFirstCondition, + this.overrideTextFieldWidget, + this.keyboardType, + this.onSubmitted, + this.onChanged, + this.style, + this.leftMargin, + this.rightMargin, + this.obscureText = false, + this.textAlign = TextAlign.center, + this.keyboardAppearance = Brightness.dark, + this.autocorrect = true, + this.maxLines = 1, + this.padding = EdgeInsets.zero, + this.buttonFadeDurationMs = 100, + this.topMargin = 0, + this.autofocus = false}); _AppTextFieldState createState() => _AppTextFieldState(); } @@ -101,95 +98,109 @@ class _AppTextFieldState extends State { @override Widget build(BuildContext context) { return Container( - margin: EdgeInsets.only( - left: widget.leftMargin ?? MediaQuery.of(context).size.width * 0.105, - right: widget.rightMargin ?? MediaQuery.of(context).size.width * 0.105, - top: widget.topMargin, - ), - padding: widget.padding, - width: double.infinity, - decoration: BoxDecoration( - color: StateContainer.of(context).curTheme.backgroundDarkest, - borderRadius: BorderRadius.circular(25), - ), - child: widget.overrideTextFieldWidget == null ? - Stack( - alignment: AlignmentDirectional.center, - children: [ - TextField( - // User defined fields - textAlign: widget.textAlign, - keyboardAppearance: widget.keyboardAppearance, - autocorrect: widget.autocorrect, - maxLines: widget.maxLines, - focusNode: widget.focusNode, - controller: widget.controller, - cursorColor: widget.cursorColor ?? StateContainer.of(context).curTheme.primary, - inputFormatters: widget.inputFormatters, - textInputAction: widget.textInputAction, - keyboardType: widget.keyboardType, - obscureText: widget.obscureText, - autofocus: widget.autofocus, - onSubmitted: widget.onSubmitted != null ? widget.onSubmitted : (text) { - if (widget.textInputAction == TextInputAction.done) { - FocusScope.of(context).unfocus(); - } - }, - onChanged: widget.onChanged, - // Style - style: widget.style, - // Input decoration - decoration: InputDecoration( - border: InputBorder.none, - // Hint - hintText: widget.hintText == null ? "" : widget.hintText, - hintStyle: TextStyle( - fontSize: 16.0, - fontWeight: FontWeight.w100, - fontFamily: 'NunitoSans', - color: StateContainer.of(context).curTheme.text60, - ), - // First button - prefixIcon: widget.prefixButton == null ? - Container(width: 0, height: 0) - : Container(width: 48, height: 48), - suffixIcon: widget.suffixButton == null ? - Container(width: 0, height: 0) - : Container(width: 48, height: 48) - ) - ), - // Buttons - Column( - mainAxisSize: MainAxisSize.max, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - widget.fadePrefixOnCondition != null && widget.prefixButton != null ? - AnimatedCrossFade( - duration: Duration(milliseconds: widget.buttonFadeDurationMs), - firstChild: widget.prefixButton, - secondChild: SizedBox(height: 48, width: 48), - crossFadeState: widget.prefixShowFirstCondition ? CrossFadeState.showFirst : CrossFadeState.showSecond, - ) - : widget.prefixButton != null - ? widget.prefixButton : SizedBox(), - // Second (suffix) button - widget.fadeSuffixOnCondition != null && widget.suffixButton != null ? - AnimatedCrossFade( - duration: Duration(milliseconds: widget.buttonFadeDurationMs), - firstChild: widget.suffixButton, - secondChild: SizedBox(height: 48, width: 48), - crossFadeState: widget.suffixShowFirstCondition ? CrossFadeState.showFirst : CrossFadeState.showSecond, - ) - : widget.suffixButton != null - ? widget.suffixButton : SizedBox() - ] - ) - ], - ) - ] - ) : widget.overrideTextFieldWidget - ); + margin: EdgeInsets.only( + left: widget.leftMargin ?? MediaQuery.of(context).size.width * 0.105, + right: + widget.rightMargin ?? MediaQuery.of(context).size.width * 0.105, + top: widget.topMargin, + ), + padding: widget.padding, + width: double.infinity, + decoration: BoxDecoration( + color: StateContainer.of(context).curTheme.backgroundDarkest, + borderRadius: BorderRadius.circular(25), + ), + child: widget.overrideTextFieldWidget == null + ? Stack(alignment: AlignmentDirectional.center, children: [ + TextField( + // User defined fields + textAlign: widget.textAlign, + keyboardAppearance: widget.keyboardAppearance, + autocorrect: widget.autocorrect, + maxLines: widget.maxLines, + focusNode: widget.focusNode, + controller: widget.controller, + cursorColor: widget.cursorColor ?? + StateContainer.of(context).curTheme.primary, + inputFormatters: widget.inputFormatters, + textInputAction: widget.textInputAction, + keyboardType: widget.keyboardType, + obscureText: widget.obscureText, + autofocus: widget.autofocus, + onSubmitted: widget.onSubmitted != null + ? widget.onSubmitted + : (text) { + if (widget.textInputAction == + TextInputAction.done) { + FocusScope.of(context).unfocus(); + } + }, + onChanged: widget.onChanged, + // Style + style: widget.style, + // Input decoration + decoration: InputDecoration( + border: InputBorder.none, + // Hint + hintText: + widget.hintText == null ? "" : widget.hintText, + hintStyle: TextStyle( + fontSize: 16.0, + fontWeight: FontWeight.w100, + fontFamily: 'NunitoSans', + color: StateContainer.of(context).curTheme.text60, + ), + // First button + prefixIcon: widget.prefixButton == null + ? Container(width: 0, height: 0) + : Container(width: 48, height: 48), + suffixIcon: widget.suffixButton == null + ? Container(width: 0, height: 0) + : Container(width: 48, height: 48))), + // Buttons + Column( + mainAxisSize: MainAxisSize.max, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + widget.fadePrefixOnCondition != null && + widget.prefixButton != null + ? AnimatedCrossFade( + duration: Duration( + milliseconds: + widget.buttonFadeDurationMs), + firstChild: widget.prefixButton, + secondChild: SizedBox(height: 48, width: 48), + crossFadeState: + widget.prefixShowFirstCondition + ? CrossFadeState.showFirst + : CrossFadeState.showSecond, + ) + : widget.prefixButton != null + ? widget.prefixButton + : SizedBox(), + // Second (suffix) button + widget.fadeSuffixOnCondition != null && + widget.suffixButton != null + ? AnimatedCrossFade( + duration: Duration( + milliseconds: + widget.buttonFadeDurationMs), + firstChild: widget.suffixButton, + secondChild: SizedBox(height: 48, width: 48), + crossFadeState: + widget.suffixShowFirstCondition + ? CrossFadeState.showFirst + : CrossFadeState.showSecond, + ) + : widget.suffixButton != null + ? widget.suffixButton + : SizedBox() + ]) + ], + ) + ]) + : widget.overrideTextFieldWidget); } -} \ No newline at end of file +} diff --git a/lib/ui/widgets/buttons.dart b/lib/ui/widgets/buttons.dart index 939fb0c6..6b93cb4b 100644 --- a/lib/ui/widgets/buttons.dart +++ b/lib/ui/widgets/buttons.dart @@ -4,6 +4,7 @@ import 'package:natrium_wallet_flutter/appstate_container.dart'; import 'package:natrium_wallet_flutter/styles.dart'; import 'package:natrium_wallet_flutter/ui/util/exceptions.dart'; import 'package:natrium_wallet_flutter/ui/widgets/outline_button.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; enum AppButtonType { PRIMARY, diff --git a/lib/ui/widgets/dialog.dart b/lib/ui/widgets/dialog.dart index 29c694d1..e628e1f5 100644 --- a/lib/ui/widgets/dialog.dart +++ b/lib/ui/widgets/dialog.dart @@ -2,10 +2,10 @@ import 'package:flutter/material.dart'; import 'package:flare_flutter/flare_actor.dart'; import 'package:natrium_wallet_flutter/localization.dart'; import 'package:natrium_wallet_flutter/styles.dart'; -import 'package:natrium_wallet_flutter/themes.dart'; import 'package:natrium_wallet_flutter/appstate_container.dart'; import 'package:natrium_wallet_flutter/ui/widgets/app_simpledialog.dart'; import 'package:natrium_wallet_flutter/util/caseconverter.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; class AppDialogs { static void showConfirmDialog( diff --git a/lib/ui/widgets/flat_button.dart b/lib/ui/widgets/flat_button.dart new file mode 100644 index 00000000..c51e9871 --- /dev/null +++ b/lib/ui/widgets/flat_button.dart @@ -0,0 +1,105 @@ +import 'package:flutter/material.dart'; + +class FlatButton extends StatelessWidget { + final Widget child; + final VoidCallback onPressed; + final VoidCallback onLongPress; + final ValueChanged onHighlightChanged; + final MouseCursor mouseCursor; + final ButtonTextTheme textTheme; + final Color textColor; + final Color disabledTextColor; + final Color color; + final Color disabledColor; + final Color focusColor; + final Color hoverColor; + final Color highlightColor; + final Color splashColor; + final Brightness colorBrightness; + final EdgeInsetsGeometry padding; + final VisualDensity visualDensity; + final ShapeBorder shape; + final Clip clipBehavior; + final FocusNode focusNode; + final bool autofocus; + final MaterialTapTargetSize materialTapTargetSize; + final double height; + final double minWidth; + + FlatButton({ + Key key, + @required this.onPressed, + @required this.child, + this.onLongPress, + this.onHighlightChanged, + this.mouseCursor, + this.textTheme, + this.textColor, + this.disabledTextColor, + this.color, + this.disabledColor, + this.focusColor, + this.hoverColor, + this.highlightColor, + this.splashColor, + this.colorBrightness, + this.padding, + this.visualDensity, + this.shape, + this.clipBehavior = Clip.none, + this.focusNode, + this.autofocus = false, + this.materialTapTargetSize, + this.height, + this.minWidth, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + // Convert FlatButton properties to TextButton properties. + final ButtonStyle style = ButtonStyle( + backgroundColor: MaterialStateProperty.resolveWith( + (Set states) { + if (states.contains(MaterialState.disabled)) return disabledColor; + return color; + }, + ), + foregroundColor: MaterialStateProperty.resolveWith( + (Set states) { + if (states.contains(MaterialState.disabled)) return disabledTextColor; + return textColor; + }, + ), + overlayColor: MaterialStateProperty.resolveWith( + (Set states) { + if (states.contains(MaterialState.pressed)) return splashColor; + if (states.contains(MaterialState.hovered)) return hoverColor; + if (states.contains(MaterialState.focused)) return focusColor; + return null; + }, + ), + mouseCursor: + mouseCursor != null ? MaterialStateProperty.all(mouseCursor) : null, + shape: shape != null + ? MaterialStateProperty.all(shape) + : MaterialStateProperty.all( + RoundedRectangleBorder(borderRadius: BorderRadius.zero)), + padding: MaterialStateProperty.all(padding), + visualDensity: visualDensity, + tapTargetSize: materialTapTargetSize ?? MaterialTapTargetSize.padded, + minimumSize: (height != null || minWidth != null) + ? MaterialStateProperty.all(Size(minWidth ?? 0, height ?? 0)) + : null, + ); + + return TextButton( + onPressed: onPressed, + onLongPress: onLongPress, + style: style, + child: child, + clipBehavior: clipBehavior, + autofocus: autofocus, + focusNode: focusNode, + ); + } +} diff --git a/lib/ui/widgets/outline_button.dart b/lib/ui/widgets/outline_button.dart index 601c3f72..dcf89eb9 100644 --- a/lib/ui/widgets/outline_button.dart +++ b/lib/ui/widgets/outline_button.dart @@ -3,8 +3,9 @@ // found in the LICENSE file. import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart'; import 'package:flutter/material.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/raised_button.dart'; // The total time to make the button's fill color opaque and change // its elevation. Only applies when highlightElevation > 0.0. diff --git a/lib/ui/widgets/raised_button.dart b/lib/ui/widgets/raised_button.dart new file mode 100644 index 00000000..d0b0f5c3 --- /dev/null +++ b/lib/ui/widgets/raised_button.dart @@ -0,0 +1,328 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +/// A material design "raised button". +/// +/// A raised button is based on a [Material] widget whose [Material.elevation] +/// increases when the button is pressed. +/// +/// Use raised buttons to add dimension to otherwise mostly flat layouts, e.g. +/// in long busy lists of content, or in wide spaces. Avoid using raised buttons +/// on already-raised content such as dialogs or cards. +/// +/// If [onPressed] and [onLongPress] callbacks are null, then the button will be disabled and by +/// default will resemble a flat button in the [disabledColor]. If you are +/// trying to change the button's [color] and it is not having any effect, check +/// that you are passing a non-null [onPressed] or [onLongPress] callbacks. +/// +/// If you want an ink-splash effect for taps, but don't want to use a button, +/// consider using [InkWell] directly. +/// +/// Raised buttons have a minimum size of 88.0 by 36.0 which can be overridden +/// with [ButtonTheme]. +/// +/// {@tool sample --template=stateless_widget_scaffold} +/// +/// This sample shows how to render a disabled RaisedButton, an enabled RaisedButton +/// and lastly a RaisedButton with gradient background. +/// +/// ![Three raised buttons, one enabled, another disabled, and the last one +/// styled with a blue gradient background](https://flutter.github.io/assets-for-api-docs/assets/material/raised_button.png) +/// +/// ```dart +/// Widget build(BuildContext context) { +/// return Center( +/// child: Column( +/// mainAxisSize: MainAxisSize.min, +/// children: [ +/// const RaisedButton( +/// onPressed: null, +/// child: Text( +/// 'Disabled Button', +/// style: TextStyle(fontSize: 20) +/// ), +/// ), +/// const SizedBox(height: 30), +/// RaisedButton( +/// onPressed: () {}, +/// child: const Text( +/// 'Enabled Button', +/// style: TextStyle(fontSize: 20) +/// ), +/// ), +/// const SizedBox(height: 30), +/// RaisedButton( +/// onPressed: () {}, +/// textColor: Colors.white, +/// padding: const EdgeInsets.all(0.0), +/// child: Container( +/// decoration: const BoxDecoration( +/// gradient: LinearGradient( +/// colors: [ +/// Color(0xFF0D47A1), +/// Color(0xFF1976D2), +/// Color(0xFF42A5F5), +/// ], +/// ), +/// ), +/// padding: const EdgeInsets.all(10.0), +/// child: const Text( +/// 'Gradient Button', +/// style: TextStyle(fontSize: 20) +/// ), +/// ), +/// ), +/// ], +/// ), +/// ); +/// } +/// ``` +/// {@end-tool} +/// +/// See also: +/// +/// * [FlatButton], a material design button without a shadow. +/// * [DropdownButton], a button that shows options to select from. +/// * [FloatingActionButton], the round button in material applications. +/// * [IconButton], to create buttons that just contain icons. +/// * [InkWell], which implements the ink splash part of a flat button. +/// * [RawMaterialButton], the widget this widget is based on. +/// * +class RaisedButton extends MaterialButton { + /// Create a filled button. + /// + /// The [autofocus] and [clipBehavior] arguments must not be null. + /// Additionally, [elevation], [hoverElevation], [focusElevation], + /// [highlightElevation], and [disabledElevation] must be non-negative, if + /// specified. + const RaisedButton({ + Key key, + @required VoidCallback onPressed, + VoidCallback onLongPress, + ValueChanged onHighlightChanged, + ButtonTextTheme textTheme, + Color textColor, + Color disabledTextColor, + Color color, + Color disabledColor, + Color focusColor, + Color hoverColor, + Color highlightColor, + Color splashColor, + Brightness colorBrightness, + double elevation, + double focusElevation, + double hoverElevation, + double highlightElevation, + double disabledElevation, + EdgeInsetsGeometry padding, + VisualDensity visualDensity, + ShapeBorder shape, + Clip clipBehavior = Clip.none, + FocusNode focusNode, + bool autofocus = false, + MaterialTapTargetSize materialTapTargetSize, + Duration animationDuration, + Widget child, + }) : assert(autofocus != null), + assert(elevation == null || elevation >= 0.0), + assert(focusElevation == null || focusElevation >= 0.0), + assert(hoverElevation == null || hoverElevation >= 0.0), + assert(highlightElevation == null || highlightElevation >= 0.0), + assert(disabledElevation == null || disabledElevation >= 0.0), + assert(clipBehavior != null), + super( + key: key, + onPressed: onPressed, + onLongPress: onLongPress, + onHighlightChanged: onHighlightChanged, + textTheme: textTheme, + textColor: textColor, + disabledTextColor: disabledTextColor, + color: color, + disabledColor: disabledColor, + focusColor: focusColor, + hoverColor: hoverColor, + highlightColor: highlightColor, + splashColor: splashColor, + colorBrightness: colorBrightness, + elevation: elevation, + focusElevation: focusElevation, + hoverElevation: hoverElevation, + highlightElevation: highlightElevation, + disabledElevation: disabledElevation, + padding: padding, + visualDensity: visualDensity, + shape: shape, + clipBehavior: clipBehavior, + focusNode: focusNode, + autofocus: autofocus, + materialTapTargetSize: materialTapTargetSize, + animationDuration: animationDuration, + child: child, + ); + + /// Create a filled button from a pair of widgets that serve as the button's + /// [icon] and [label]. + /// + /// The icon and label are arranged in a row and padded by 12 logical pixels + /// at the start, and 16 at the end, with an 8 pixel gap in between. + /// + /// The [elevation], [highlightElevation], [disabledElevation], [icon], + /// [label], and [clipBehavior] arguments must not be null. + factory RaisedButton.icon({ + Key key, + @required VoidCallback onPressed, + VoidCallback onLongPress, + ValueChanged onHighlightChanged, + ButtonTextTheme textTheme, + Color textColor, + Color disabledTextColor, + Color color, + Color disabledColor, + Color focusColor, + Color hoverColor, + Color highlightColor, + Color splashColor, + Brightness colorBrightness, + double elevation, + double highlightElevation, + double disabledElevation, + ShapeBorder shape, + Clip clipBehavior, + FocusNode focusNode, + bool autofocus, + MaterialTapTargetSize materialTapTargetSize, + Duration animationDuration, + @required Widget icon, + @required Widget label, + }) = _RaisedButtonWithIcon; + + @override + Widget build(BuildContext context) { + final ThemeData theme = Theme.of(context); + final ButtonThemeData buttonTheme = ButtonTheme.of(context); + return RawMaterialButton( + onPressed: onPressed, + onLongPress: onLongPress, + onHighlightChanged: onHighlightChanged, + clipBehavior: clipBehavior, + fillColor: buttonTheme.getFillColor(this), + textStyle: theme.textTheme.button + .copyWith(color: buttonTheme.getTextColor(this)), + focusColor: buttonTheme.getFocusColor(this), + hoverColor: buttonTheme.getHoverColor(this), + highlightColor: buttonTheme.getHighlightColor(this), + splashColor: buttonTheme.getSplashColor(this), + elevation: buttonTheme.getElevation(this), + focusElevation: buttonTheme.getFocusElevation(this), + hoverElevation: buttonTheme.getHoverElevation(this), + highlightElevation: buttonTheme.getHighlightElevation(this), + disabledElevation: buttonTheme.getDisabledElevation(this), + padding: buttonTheme.getPadding(this), + visualDensity: visualDensity ?? theme.visualDensity, + constraints: buttonTheme.getConstraints(this), + shape: buttonTheme.getShape(this), + focusNode: focusNode, + autofocus: autofocus, + animationDuration: buttonTheme.getAnimationDuration(this), + materialTapTargetSize: buttonTheme.getMaterialTapTargetSize(this), + child: child, + ); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty('elevation', elevation, + defaultValue: null)); + properties.add(DiagnosticsProperty('focusElevation', focusElevation, + defaultValue: null)); + properties.add(DiagnosticsProperty('hoverElevation', hoverElevation, + defaultValue: null)); + properties.add(DiagnosticsProperty( + 'highlightElevation', highlightElevation, + defaultValue: null)); + properties.add(DiagnosticsProperty( + 'disabledElevation', disabledElevation, + defaultValue: null)); + } +} + +/// The type of RaisedButtons created with [RaisedButton.icon]. +/// +/// This class only exists to give RaisedButtons created with [RaisedButton.icon] +/// a distinct class for the sake of [ButtonTheme]. It can not be instantiated. +class _RaisedButtonWithIcon extends RaisedButton + with MaterialButtonWithIconMixin { + _RaisedButtonWithIcon({ + Key key, + @required VoidCallback onPressed, + VoidCallback onLongPress, + ValueChanged onHighlightChanged, + ButtonTextTheme textTheme, + Color textColor, + Color disabledTextColor, + Color color, + Color disabledColor, + Color focusColor, + Color hoverColor, + Color highlightColor, + Color splashColor, + Brightness colorBrightness, + double elevation, + double highlightElevation, + double disabledElevation, + ShapeBorder shape, + Clip clipBehavior = Clip.none, + FocusNode focusNode, + bool autofocus = false, + MaterialTapTargetSize materialTapTargetSize, + Duration animationDuration, + @required Widget icon, + @required Widget label, + }) : assert(elevation == null || elevation >= 0.0), + assert(highlightElevation == null || highlightElevation >= 0.0), + assert(disabledElevation == null || disabledElevation >= 0.0), + assert(clipBehavior != null), + assert(icon != null), + assert(label != null), + assert(autofocus != null), + super( + key: key, + onPressed: onPressed, + onLongPress: onLongPress, + onHighlightChanged: onHighlightChanged, + textTheme: textTheme, + textColor: textColor, + disabledTextColor: disabledTextColor, + color: color, + disabledColor: disabledColor, + focusColor: focusColor, + hoverColor: hoverColor, + highlightColor: highlightColor, + splashColor: splashColor, + colorBrightness: colorBrightness, + elevation: elevation, + highlightElevation: highlightElevation, + disabledElevation: disabledElevation, + shape: shape, + clipBehavior: clipBehavior, + focusNode: focusNode, + autofocus: autofocus, + materialTapTargetSize: materialTapTargetSize, + animationDuration: animationDuration, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + icon, + const SizedBox(width: 8.0), + label, + ], + ), + ); +} diff --git a/lib/ui/widgets/remote_message_card.dart b/lib/ui/widgets/remote_message_card.dart index 47ffb9e8..21b56b7f 100644 --- a/lib/ui/widgets/remote_message_card.dart +++ b/lib/ui/widgets/remote_message_card.dart @@ -3,6 +3,7 @@ import 'package:flutter/widgets.dart'; import 'package:natrium_wallet_flutter/appstate_container.dart'; import 'package:natrium_wallet_flutter/network/model/response/alerts_response_item.dart'; import 'package:natrium_wallet_flutter/styles.dart'; +import 'package:natrium_wallet_flutter/ui/widgets/flat_button.dart'; class RemoteMessageCard extends StatefulWidget { final AlertResponseItem alert; diff --git a/lib/util/biometrics.dart b/lib/util/biometrics.dart index bf6d0dd1..1c1a997c 100644 --- a/lib/util/biometrics.dart +++ b/lib/util/biometrics.dart @@ -6,21 +6,25 @@ import 'package:logger/logger.dart'; class BiometricUtil { /// /// hasBiometrics() - /// + /// /// @returns [true] if device has fingerprint/faceID available and registered, [false] otherwise Future hasBiometrics() async { LocalAuthentication localAuth = new LocalAuthentication(); bool canCheck = await localAuth.canCheckBiometrics; if (canCheck) { - List availableBiometrics = await localAuth.getAvailableBiometrics(); + List availableBiometrics = + await localAuth.getAvailableBiometrics(); availableBiometrics.forEach((type) { sl.get().i(type.toString()); - sl.get().i("${type == BiometricType.face ? 'face' : type == BiometricType.iris ? 'iris' : type == BiometricType.fingerprint ? 'fingerprint' : 'unknown'}"); + sl.get().i( + "${type == BiometricType.face ? 'face' : type == BiometricType.iris ? 'iris' : type == BiometricType.fingerprint ? 'fingerprint' : 'unknown'}"); }); if (availableBiometrics.contains(BiometricType.face)) { return true; } else if (availableBiometrics.contains(BiometricType.fingerprint)) { return true; + } else if (availableBiometrics.contains(BiometricType.strong)) { + return true; } } return false; @@ -28,18 +32,18 @@ class BiometricUtil { /// /// authenticateWithBiometrics() - /// + /// /// @param [message] Message shown to user in FaceID/TouchID popup /// @returns [true] if successfully authenticated, [false] otherwise - Future authenticateWithBiometrics(BuildContext context, String message) async { + Future authenticateWithBiometrics( + BuildContext context, String message) async { bool hasBiometricsEnrolled = await hasBiometrics(); if (hasBiometricsEnrolled) { LocalAuthentication localAuth = new LocalAuthentication(); - return await localAuth.authenticateWithBiometrics( - localizedReason: message, - useErrorDialogs: false - ); + return await localAuth.authenticate( + localizedReason: message, + options: const AuthenticationOptions(useErrorDialogs: false)); } return false; } -} \ No newline at end of file +} diff --git a/lib/util/sharedprefsutil.dart b/lib/util/sharedprefsutil.dart index 7b3793c3..e37d7da7 100644 --- a/lib/util/sharedprefsutil.dart +++ b/lib/util/sharedprefsutil.dart @@ -79,10 +79,7 @@ class SharedPrefsUtil { } else { expiryVal = expiry; } - Map msg = { - 'data':value, - 'expiry':expiryVal - }; + Map msg = {'data': value, 'expiry': expiryVal}; String serialized = json.encode(msg); await set(key, serialized); } @@ -226,8 +223,9 @@ class SharedPrefsUtil { } Future getBlockExplorer() async { - return AvailableBlockExplorer(AvailableBlockExplorerEnum.values[await get(cur_explorer, - defaultValue: AvailableBlockExplorerEnum.NANOCRAWLER.index)]); + return AvailableBlockExplorer(AvailableBlockExplorerEnum.values[await get( + cur_explorer, + defaultValue: AvailableBlockExplorerEnum.SPYNANO.index)]); } Future getTheme() async { @@ -380,7 +378,7 @@ class SharedPrefsUtil { Future shouldShowAlert(AlertResponseItem alert) async { int exists = await getWithExpiry("alert_${alert.id}"); - return exists == null ? true: false; + return exists == null ? true : false; } // For logging out diff --git a/lib/util/user_data_util.dart b/lib/util/user_data_util.dart index 724da630..37d17e0f 100644 --- a/lib/util/user_data_util.dart +++ b/lib/util/user_data_util.dart @@ -21,7 +21,11 @@ class QRScanErrs { static const String PERMISSION_DENIED = "qr_denied"; static const String UNKNOWN_ERROR = "qr_unknown"; static const String CANCEL_ERROR = "qr_cancel"; - static const List ERROR_LIST = [PERMISSION_DENIED, UNKNOWN_ERROR, CANCEL_ERROR]; + static const List ERROR_LIST = [ + PERMISSION_DENIED, + UNKNOWN_ERROR, + CANCEL_ERROR + ]; } class UserDataUtil { @@ -73,23 +77,26 @@ class UserDataUtil { static Future getQRData(DataType type, BuildContext context) async { UIUtil.cancelLockEvent(); try { - String data = await BarcodeScanner.scan(StateContainer.of(context).curTheme.qrScanTheme); + String data = await BarcodeScanner.scan( + StateContainer.of(context).curTheme.qrScanTheme); if (isEmpty(data)) { return null; } return _parseData(data, type); } on PlatformException catch (e) { if (e.code == BarcodeScanner.CameraAccessDenied) { - UIUtil.showSnackbar(AppLocalization.of(context).qrInvalidPermissions, context); + UIUtil.showSnackbar( + AppLocalization.of(context).qrInvalidPermissions, context); return QRScanErrs.PERMISSION_DENIED; } else { - UIUtil.showSnackbar(AppLocalization.of(context).qrUnknownError, context); + UIUtil.showSnackbar( + AppLocalization.of(context).qrUnknownError, context); return QRScanErrs.UNKNOWN_ERROR; } } on FormatException { return QRScanErrs.CANCEL_ERROR; } catch (e) { - log.e("Unknown QR Scan Error ${e.toString()}", e); + log.e("Unknown QR Scan Error ${e.toString()}", error: e); return QRScanErrs.UNKNOWN_ERROR; } } @@ -113,7 +120,9 @@ class UserDataUtil { }); setStream = delayed.asStream().listen((_) { Clipboard.getData("text/plain").then((data) { - if (data != null && data.text != null && NanoSeeds.isValidSeed(data.text)) { + if (data != null && + data.text != null && + NanoSeeds.isValidSeed(data.text)) { Clipboard.setData(ClipboardData(text: "")); } }); diff --git a/pubspec.yaml b/pubspec.yaml index cecde505..48472d1a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -6,7 +6,7 @@ description: Natrium - Fast, Robust & Secure NANO Wallet. # followed by an optional build number separated by a +. # Both the version and the builder number may be overridden in flutter # build by specifying --build-name and --build-number, respectively. -version: 2.4.5+83 +version: 2.5.2+86 environment: sdk: ">=2.11.99 <3.0.0" @@ -18,7 +18,7 @@ dependencies: sdk: flutter # Securley store data in a keystore - flutter_secure_storage: ^5.0.2 + flutter_secure_storage: ^8.1.0 # Nano core functions flutter_nano_ffi: @@ -29,7 +29,7 @@ dependencies: shared_preferences: ^2.0.8 # Flare for animations - flare_flutter: ^2.0.6 + flare_flutter: ^3.0.2 # Websockets web_socket_channel: ^2.0.0 @@ -50,7 +50,7 @@ dependencies: decimal: ^1.3.0 # Logger - logger: ^1.0.0 + logger: ^2.0.1 # Native webview plugin flutter_webview_plugin: ^0.4.0 @@ -62,15 +62,15 @@ dependencies: path_provider: ^2.0.1 # TouchID/FaceID - local_auth: ^1.0.0-nullsafety.3 + local_auth: ^2.1.6 # Eventbus event_taxi: ^1.0.0 # SVG - flutter_svg: ^0.22.0 + flutter_svg: ^1.0.3 # QR Codes - qr_flutter: ^2.0.1 # Generator + qr_flutter: ^4.0.0 # Generator barcode_scan: git: url: https://github.com/bbedward/flutter_barcode_reader.git @@ -84,7 +84,7 @@ dependencies: ref: master # File picker - file_picker: ^3.0.0-nullsafety.0 + file_picker: ^5.3.1 # Deep link support #uni_links: ^0.2.0 @@ -106,17 +106,17 @@ dependencies: oktoast: ^3.0.0 # Push notifications - firebase_messaging: ^11.1.0 - firebase_core: ^1.10.0 + firebase_messaging: ^14.6.7 + firebase_core: ^2.15.1 # Slidable list actions - flutter_slidable: ^0.5.7 + flutter_slidable: ^0.6.0 # Lock helper synchronized: ^3.0.0 # Service provider - get_it: ^6.0.0 + get_it: ^7.6.0 # Root/Jailbreak detection root_checker: @@ -125,10 +125,10 @@ dependencies: ref: master # Validation utilities - validators: 2.0.0 + validators: ^3.0.0 # Auto resize text widget - auto_size_text: ^2.1.0 + auto_size_text: ^3.0.0 # Avoid keyboard from overlapping text fields keyboard_avoider: ^0.1.2 @@ -144,7 +144,7 @@ dependencies: url: https://github.com/bbedward/manta-dart.git ref: master - devicelocale: ^0.4.1 + devicelocale: ^0.6.0 dependency_overrides: analyzer: ^2.7.0 @@ -153,7 +153,7 @@ dependency_overrides: dev_dependencies: flutter_test: sdk: flutter - build_runner: 2.1.5 + build_runner: ^2.3.3 json_serializable: ^6.0.1 intl_translation: git: