diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 00000000..a775014c --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,12 @@ +include: package:flutter_lints/flutter.yaml + +linter: + + rules: + prefer_single_quotes: true + public_member_api_docs: false + avoid_relative_lib_imports: true + always_use_package_imports: true + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/android/build.gradle b/android/build.gradle index 17a89c3d..5fc84d8a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -2,15 +2,14 @@ group 'co.paystack.flutterpaystack' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.7.20' repositories { - mavenCentral() google() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.4.0-rc02' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath 'com.android.tools.build:gradle:8.3.2' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.22" } } @@ -25,13 +24,24 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdkVersion 32 + namespace = "co.paystack.flutterpaystack" + compileSdk 34 sourceSets { main.java.srcDirs += 'src/main/kotlin' } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = "17" + } + defaultConfig { - minSdkVersion 16 + minSdkVersion 21 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" versionCode 21 versionName "3.0.10" @@ -42,5 +52,5 @@ android { } dependencies { - implementation 'com.google.android.material:material:1.7.0' + implementation 'com.google.android.material:material:1.12.0' } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 8212ba0d..09523c0e 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ -#Wed Oct 23 00:11:25 WAT 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 3d85f88b..73f6977a 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,5 +1,4 @@ - + - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - -android { - compileSdkVersion 32 - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - lintOptions { - disable 'InvalidPackage' - } - - defaultConfig { - applicationId "co.paystack.flutterpaystack" - minSdkVersion 16 - targetSdkVersion 32 - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} \ No newline at end of file diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index a0921006..00000000 --- a/example/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/example/android/app/src/main/kotlin/co/paystack/flutterpaystackexample/MainActivity.kt b/example/android/app/src/main/kotlin/co/paystack/flutterpaystackexample/MainActivity.kt deleted file mode 100644 index 2a81e189..00000000 --- a/example/android/app/src/main/kotlin/co/paystack/flutterpaystackexample/MainActivity.kt +++ /dev/null @@ -1,6 +0,0 @@ -package co.paystack.flutterpaystackexample - -import io.flutter.embedding.android.FlutterActivity - - -class MainActivity: FlutterActivity() \ No newline at end of file diff --git a/example/android/app/src/main/res/drawable/launch_background.xml b/example/android/app/src/main/res/drawable/launch_background.xml deleted file mode 100644 index 5782842b..00000000 --- a/example/android/app/src/main/res/drawable/launch_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index efc2479e..00000000 Binary files a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 50547751..00000000 Binary files a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 134eb027..00000000 Binary files a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index e7154ce0..00000000 Binary files a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b76cfd47..00000000 Binary files a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml deleted file mode 100644 index 41a2159f..00000000 --- a/example/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/example/android/build.gradle b/example/android/build.gradle deleted file mode 100644 index bef5f7b2..00000000 --- a/example/android/build.gradle +++ /dev/null @@ -1,31 +0,0 @@ -buildscript { - ext.kotlin_version = '1.7.10' - repositories { - google() - jcenter() - } - - dependencies { - classpath 'com.android.tools.build:gradle:7.2.2' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -allprojects { - repositories { - google() - jcenter() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/example/android/gradle.properties b/example/android/gradle.properties deleted file mode 100644 index 53ae0ae4..00000000 --- a/example/android/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -android.enableJetifier=true -android.useAndroidX=true -org.gradle.jvmargs=-Xmx1536M diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 97c775ed..00000000 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Sun Mar 14 03:06:25 WAT 2021 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle deleted file mode 100644 index 5a2f14fb..00000000 --- a/example/android/settings.gradle +++ /dev/null @@ -1,15 +0,0 @@ -include ':app' - -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() - -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } -} - -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory -} diff --git a/example/ios/.gitignore b/example/ios/.gitignore deleted file mode 100644 index 26f750ce..00000000 --- a/example/ios/.gitignore +++ /dev/null @@ -1,47 +0,0 @@ -.idea/ -.vagrant/ -.sconsign.dblite -.svn/ - -.DS_Store -*.swp -profile - -DerivedData/ -build/ -GeneratedPluginRegistrant.h -GeneratedPluginRegistrant.m - -.generated/ - -*.pbxuser -*.mode1v3 -*.mode2v3 -*.perspectivev3 - -!default.pbxuser -!default.mode1v3 -!default.mode2v3 -!default.perspectivev3 - -xcuserdata - -*.moved-aside - -*.pyc -*sync/ -Icon? -.tags* - -/Flutter/app.flx -/Flutter/app.zip -/Flutter/flutter_assets/ -/Flutter/App.framework -/Flutter/Flutter.framework -/Flutter/Generated.xcconfig -/ServiceDefinitions.json - -Pods/ -.symlinks/ -/Flutter/flutter_export_environment.sh -/Podfile.lock diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist deleted file mode 100644 index 9625e105..00000000 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - MinimumOSVersion - 11.0 - - diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig deleted file mode 100644 index e8efba11..00000000 --- a/example/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "Generated.xcconfig" diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig deleted file mode 100644 index 399e9340..00000000 --- a/example/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "Generated.xcconfig" diff --git a/example/ios/Podfile b/example/ios/Podfile deleted file mode 100644 index d207307f..00000000 --- a/example/ios/Podfile +++ /dev/null @@ -1,38 +0,0 @@ -# Uncomment this line to define a global platform for your project -# platform :ios, '11.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_ios_podfile_setup - -target 'Runner' do - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end -end diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index 92d03893..00000000 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,471 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 50; - objects = { - -/* Begin PBXBuildFile section */ - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; - 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; - 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 */; }; - B84D214F1187E089C89FBF4E /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2A0DA05EEF0BDC6F7D4D9B /* libPods-Runner.a */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 4ACB532BA65C0C3617E4D83C /* 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 = ""; }; - 6D2A0DA05EEF0BDC6F7D4D9B /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 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 = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 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 = ""; }; - A7D68B02E36C64CC1B2D93BF /* 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 = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - B84D214F1187E089C89FBF4E /* libPods-Runner.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 1E77DF603F56B34D2F082A32 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 6D2A0DA05EEF0BDC6F7D4D9B /* libPods-Runner.a */, - ); - name = Frameworks; - sourceTree = ""; - }; - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - A6A84EFD93D2D40A3EA1E347 /* Pods */, - 1E77DF603F56B34D2F082A32 /* Frameworks */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, - 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 97C146F11CF9000F007C117D /* Supporting Files */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - ); - path = Runner; - sourceTree = ""; - }; - 97C146F11CF9000F007C117D /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 97C146F21CF9000F007C117D /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - A6A84EFD93D2D40A3EA1E347 /* Pods */ = { - isa = PBXGroup; - children = ( - 4ACB532BA65C0C3617E4D83C /* Pods-Runner.debug.xcconfig */, - A7D68B02E36C64CC1B2D93BF /* Pods-Runner.release.xcconfig */, - ); - name = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 8637EE5623C81793E78E0C0B /* [CP] Check Pods Manifest.lock */, - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1300; - ORGANIZATIONNAME = "The Chromium Authors"; - TargetAttributes = { - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - DevelopmentTeam = A75A29V65V; - SystemCapabilities = { - com.apple.BackgroundModes = { - enabled = 1; - }; - }; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - English, - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 8637EE5623C81793E78E0C0B /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, - 97C146F31CF9000F007C117D /* main.m in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = A75A29V65V; - ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - PRODUCT_BUNDLE_IDENTIFIER = co.paystack.flutterPaystackExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = A75A29V65V; - ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - PRODUCT_BUNDLE_IDENTIFIER = co.paystack.flutterPaystackExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a6..00000000 --- a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index a69542ed..00000000 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc14..00000000 --- a/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/example/ios/Runner/AppDelegate.h b/example/ios/Runner/AppDelegate.h deleted file mode 100644 index 36e21bbf..00000000 --- a/example/ios/Runner/AppDelegate.h +++ /dev/null @@ -1,6 +0,0 @@ -#import -#import - -@interface AppDelegate : FlutterAppDelegate - -@end diff --git a/example/ios/Runner/AppDelegate.m b/example/ios/Runner/AppDelegate.m deleted file mode 100644 index 59a72e90..00000000 --- a/example/ios/Runner/AppDelegate.m +++ /dev/null @@ -1,13 +0,0 @@ -#include "AppDelegate.h" -#include "GeneratedPluginRegistrant.h" - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application - didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [GeneratedPluginRegistrant registerWithRegistry:self]; - // Override point for customization after application launch. - return [super application:application didFinishLaunchingWithOptions:launchOptions]; -} - -@end diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d36b1fab..00000000 --- a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index 9fa4284d..00000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png deleted file mode 100644 index 22ea0c1c..00000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png deleted file mode 100644 index 1aaaa674..00000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index f2bd974a..00000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png deleted file mode 100644 index 8947ef4b..00000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index 0cc03b56..00000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png deleted file mode 100644 index 8fe3c972..00000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png deleted file mode 100644 index 1aaaa674..00000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index 40556cc0..00000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index 4abd9aea..00000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index 4abd9aea..00000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index 7b3ef633..00000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png deleted file mode 100644 index 8f0e4bc2..00000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png deleted file mode 100644 index bf87ef09..00000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png deleted file mode 100644 index 26acb0c3..00000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json deleted file mode 100644 index 0bedcf2f..00000000 --- a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png deleted file mode 100644 index 9da19eac..00000000 Binary files a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png deleted file mode 100644 index 9da19eac..00000000 Binary files a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png deleted file mode 100644 index 9da19eac..00000000 Binary files a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725b..00000000 --- a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/example/ios/Runner/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f2e259c7..00000000 --- a/example/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/ios/Runner/Base.lproj/Main.storyboard b/example/ios/Runner/Base.lproj/Main.storyboard deleted file mode 100644 index f3c28516..00000000 --- a/example/ios/Runner/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist deleted file mode 100644 index 909e2657..00000000 --- a/example/ios/Runner/Info.plist +++ /dev/null @@ -1,52 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - Flutter Paystack - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UIBackgroundModes - - fetch - remote-notification - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - CADisableMinimumFrameDurationOnPhone - - - diff --git a/example/ios/Runner/main.m b/example/ios/Runner/main.m deleted file mode 100644 index dff6597e..00000000 --- a/example/ios/Runner/main.m +++ /dev/null @@ -1,9 +0,0 @@ -#import -#import -#import "AppDelegate.h" - -int main(int argc, char* argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/example/lib/main.dart b/example/lib/main.dart deleted file mode 100644 index 87a7123e..00000000 --- a/example/lib/main.dart +++ /dev/null @@ -1,495 +0,0 @@ -import 'dart:async'; -import 'dart:io'; - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_paystack/flutter_paystack.dart'; -import 'package:http/http.dart' as http; - -// To get started quickly, change this to your heroku deployment of -// https://github.com/PaystackHQ/sample-charge-card-backend -// Step 1. Visit https://github.com/PaystackHQ/sample-charge-card-backend -// Step 2. Click "Deploy to heroku" -// Step 3. Login with your heroku credentials or create a free heroku account -// Step 4. Provide your secret key and an email with which to start all test transactions -// Step 5. Replace {YOUR_BACKEND_URL} below with the url generated by heroku (format https://some-url.herokuapp.com) -String backendUrl = '{YOUR_BACKEND_URL}'; -// Set this to a public key that matches the secret key you supplied while creating the heroku instance -String paystackPublicKey = '{YOUR_PAYSTACK_PUBLIC_KEY}'; -const String appName = 'Paystack Example'; - -void main() => runApp(new MyApp()); - -class MyApp extends StatelessWidget { - @override - Widget build(BuildContext context) { - return new MaterialApp( - title: appName, - darkTheme: ThemeData.dark(), - home: new HomePage(), - ); - } -} - -class HomePage extends StatefulWidget { - @override - _HomePageState createState() => _HomePageState(); -} - -class _HomePageState extends State { - final _scaffoldKey = new GlobalKey(); - final _formKey = GlobalKey(); - final _verticalSizeBox = const SizedBox(height: 20.0); - final _horizontalSizeBox = const SizedBox(width: 10.0); - final plugin = PaystackPlugin(); - var _border = new Container( - width: double.infinity, - height: 1.0, - color: Colors.red, - ); - int _radioValue = 0; - CheckoutMethod _method = CheckoutMethod.selectable; - bool _inProgress = false; - String? _cardNumber; - String? _cvv; - int? _expiryMonth; - int? _expiryYear; - - @override - void initState() { - plugin.initialize(publicKey: paystackPublicKey); - super.initState(); - } - - @override - Widget build(BuildContext context) { - return new Scaffold( - key: _scaffoldKey, - appBar: new AppBar(title: const Text(appName)), - body: new Container( - padding: const EdgeInsets.all(20.0), - child: new Form( - key: _formKey, - child: new SingleChildScrollView( - child: new ListBody( - children: [ - new Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - new Expanded( - child: const Text('Initalize transaction from:'), - ), - new Expanded( - child: new Column( - mainAxisSize: MainAxisSize.min, - children: [ - new RadioListTile( - value: 0, - groupValue: _radioValue, - onChanged: _handleRadioValueChanged, - title: const Text('Local'), - ), - new RadioListTile( - value: 1, - groupValue: _radioValue, - onChanged: _handleRadioValueChanged, - title: const Text('Server'), - ), - ]), - ) - ], - ), - _border, - _verticalSizeBox, - new TextFormField( - decoration: const InputDecoration( - border: const UnderlineInputBorder(), - labelText: 'Card number', - ), - onSaved: (String? value) => _cardNumber = value, - ), - _verticalSizeBox, - new Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - new Expanded( - child: new TextFormField( - decoration: const InputDecoration( - border: const UnderlineInputBorder(), - labelText: 'CVV', - ), - onSaved: (String? value) => _cvv = value, - ), - ), - _horizontalSizeBox, - new Expanded( - child: new TextFormField( - decoration: const InputDecoration( - border: const UnderlineInputBorder(), - labelText: 'Expiry Month', - ), - onSaved: (String? value) => - _expiryMonth = int.tryParse(value ?? ""), - ), - ), - _horizontalSizeBox, - new Expanded( - child: new TextFormField( - decoration: const InputDecoration( - border: const UnderlineInputBorder(), - labelText: 'Expiry Year', - ), - onSaved: (String? value) => - _expiryYear = int.tryParse(value ?? ""), - ), - ) - ], - ), - _verticalSizeBox, - Theme( - data: Theme.of(context).copyWith( - colorScheme: Theme.of(context) - .colorScheme - .copyWith(secondary: green), - primaryColorLight: Colors.white, - primaryColorDark: navyBlue, - textTheme: Theme.of(context).textTheme.copyWith( - bodyText2: TextStyle( - color: lightBlue, - ), - ), - ), - child: Builder( - builder: (context) { - return _inProgress - ? new Container( - alignment: Alignment.center, - height: 50.0, - child: Platform.isIOS - ? new CupertinoActivityIndicator() - : new CircularProgressIndicator(), - ) - : new Column( - mainAxisSize: MainAxisSize.min, - children: [ - _getPlatformButton( - 'Charge Card', () => _startAfreshCharge()), - _verticalSizeBox, - _border, - new SizedBox( - height: 40.0, - ), - new Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - new Flexible( - flex: 3, - child: new DropdownButtonHideUnderline( - child: new InputDecorator( - decoration: const InputDecoration( - border: OutlineInputBorder(), - isDense: true, - hintText: 'Checkout method', - ), - child: new DropdownButton< - CheckoutMethod>( - value: _method, - isDense: true, - onChanged: (CheckoutMethod? value) { - if (value != null) { - setState(() => _method = value); - } - }, - items: banks.map((String value) { - return new DropdownMenuItem< - CheckoutMethod>( - value: - _parseStringToMethod(value), - child: new Text(value), - ); - }).toList(), - ), - ), - ), - ), - _horizontalSizeBox, - new Flexible( - flex: 2, - child: new Container( - width: double.infinity, - child: _getPlatformButton( - 'Checkout', - () => _handleCheckout(context), - ), - ), - ), - ], - ) - ], - ); - }, - ), - ) - ], - ), - ), - ), - ), - ); - } - - void _handleRadioValueChanged(int? value) { - if (value != null) setState(() => _radioValue = value); - } - - _handleCheckout(BuildContext context) async { - if (_method != CheckoutMethod.card && _isLocal) { - _showMessage('Select server initialization method at the top'); - return; - } - setState(() => _inProgress = true); - _formKey.currentState?.save(); - Charge charge = Charge() - ..amount = 10000 // In base currency - ..email = 'customer@email.com' - ..card = _getCardFromUI(); - - if (!_isLocal) { - var accessCode = await _fetchAccessCodeFrmServer(_getReference()); - charge.accessCode = accessCode; - } else { - charge.reference = _getReference(); - } - - try { - CheckoutResponse response = await plugin.checkout( - context, - method: _method, - charge: charge, - fullscreen: false, - logo: MyLogo(), - ); - print('Response = $response'); - setState(() => _inProgress = false); - _updateStatus(response.reference, '$response'); - } catch (e) { - setState(() => _inProgress = false); - _showMessage("Check console for error"); - rethrow; - } - } - - _startAfreshCharge() async { - _formKey.currentState?.save(); - - Charge charge = Charge(); - charge.card = _getCardFromUI(); - - setState(() => _inProgress = true); - - if (_isLocal) { - // Set transaction params directly in app (note that these params - // are only used if an access_code is not set. In debug mode, - // setting them after setting an access code would throw an exception - - charge - ..amount = 10000 // In base currency - ..email = 'customer@email.com' - ..reference = _getReference() - ..putCustomField('Charged From', 'Flutter SDK'); - _chargeCard(charge); - } else { - // Perform transaction/initialize on Paystack server to get an access code - // documentation: https://developers.paystack.co/reference#initialize-a-transaction - charge.accessCode = await _fetchAccessCodeFrmServer(_getReference()); - _chargeCard(charge); - } - } - - _chargeCard(Charge charge) async { - final response = await plugin.chargeCard(context, charge: charge); - - final reference = response.reference; - - // Checking if the transaction is successful - if (response.status) { - _verifyOnServer(reference); - return; - } - - // The transaction failed. Checking if we should verify the transaction - if (response.verify) { - _verifyOnServer(reference); - } else { - setState(() => _inProgress = false); - _updateStatus(reference, response.message); - } - } - - String _getReference() { - String platform; - if (Platform.isIOS) { - platform = 'iOS'; - } else { - platform = 'Android'; - } - - return 'ChargedFrom${platform}_${DateTime.now().millisecondsSinceEpoch}'; - } - - PaymentCard _getCardFromUI() { - // Using just the must-required parameters. - return PaymentCard( - number: _cardNumber, - cvc: _cvv, - expiryMonth: _expiryMonth, - expiryYear: _expiryYear, - ); - - // Using Cascade notation (similar to Java's builder pattern) -// return PaymentCard( -// number: cardNumber, -// cvc: cvv, -// expiryMonth: expiryMonth, -// expiryYear: expiryYear) -// ..name = 'Segun Chukwuma Adamu' -// ..country = 'Nigeria' -// ..addressLine1 = 'Ikeja, Lagos' -// ..addressPostalCode = '100001'; - - // Using optional parameters -// return PaymentCard( -// number: cardNumber, -// cvc: cvv, -// expiryMonth: expiryMonth, -// expiryYear: expiryYear, -// name: 'Ismail Adebola Emeka', -// addressCountry: 'Nigeria', -// addressLine1: '90, Nnebisi Road, Asaba, Deleta State'); - } - - Widget _getPlatformButton(String string, Function() function) { - // is still in progress - Widget widget; - if (Platform.isIOS) { - widget = new CupertinoButton( - onPressed: function, - padding: const EdgeInsets.symmetric(horizontal: 15.0), - color: CupertinoColors.activeBlue, - child: new Text( - string, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ); - } else { - widget = new ElevatedButton( - onPressed: function, - child: new Text( - string.toUpperCase(), - style: const TextStyle(fontSize: 17.0), - ), - ); - } - return widget; - } - - Future _fetchAccessCodeFrmServer(String reference) async { - String url = '$backendUrl/new-access-code'; - String? accessCode; - try { - print("Access code url = $url"); - http.Response response = await http.get(Uri.parse(url)); - accessCode = response.body; - print('Response for access code = $accessCode'); - } catch (e) { - setState(() => _inProgress = false); - _updateStatus( - reference, - 'There was a problem getting a new access code form' - ' the backend: $e'); - } - - return accessCode; - } - - void _verifyOnServer(String? reference) async { - _updateStatus(reference, 'Verifying...'); - String url = '$backendUrl/verify/$reference'; - try { - http.Response response = await http.get(Uri.parse(url)); - var body = response.body; - _updateStatus(reference, body); - } catch (e) { - _updateStatus( - reference, - 'There was a problem verifying %s on the backend: ' - '$reference $e'); - } - setState(() => _inProgress = false); - } - - _updateStatus(String? reference, String message) { - _showMessage('Reference: $reference \n\ Response: $message', - const Duration(seconds: 7)); - } - - _showMessage(String message, - [Duration duration = const Duration(seconds: 4)]) { - ScaffoldMessenger.of(context).showSnackBar(new SnackBar( - content: new Text(message), - duration: duration, - action: new SnackBarAction( - label: 'CLOSE', - onPressed: () => - ScaffoldMessenger.of(context).removeCurrentSnackBar()), - )); - } - - bool get _isLocal => _radioValue == 0; -} - -var banks = ['Selectable', 'Bank', 'Card']; - -CheckoutMethod _parseStringToMethod(String string) { - CheckoutMethod method = CheckoutMethod.selectable; - switch (string) { - case 'Bank': - method = CheckoutMethod.bank; - break; - case 'Card': - method = CheckoutMethod.card; - break; - } - return method; -} - -class MyLogo extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.black, - ), - alignment: Alignment.center, - padding: EdgeInsets.all(10), - child: Text( - "CO", - style: TextStyle( - color: Colors.white, - fontSize: 13, - fontWeight: FontWeight.bold, - ), - ), - ); - } -} - -const Color green = const Color(0xFF3db76d); -const Color lightBlue = const Color(0xFF34a5db); -const Color navyBlue = const Color(0xFF031b33); diff --git a/example/pubspec.yaml b/example/pubspec.yaml deleted file mode 100644 index 3d8962e5..00000000 --- a/example/pubspec.yaml +++ /dev/null @@ -1,20 +0,0 @@ -name: flutter_paystack_example -description: Demonstrates how to use the flutter_paystack plugin. -version: 1.0.0+1 - -dependencies: - flutter: - sdk: flutter - -dev_dependencies: - flutter_test: - sdk: flutter - - flutter_paystack: - path: ../ - -flutter: - uses-material-design: true - -environment: - sdk: ">=2.12.0 <3.0.0" \ No newline at end of file diff --git a/lib/src/api/model/transaction_api_response.dart b/lib/src/api/model/transaction_api_response.dart index 2904b96a..281889e5 100644 --- a/lib/src/api/model/transaction_api_response.dart +++ b/lib/src/api/model/transaction_api_response.dart @@ -13,7 +13,7 @@ class TransactionApiResponse extends ApiResponse { } TransactionApiResponse.fromMap(Map map) { - this.reference = map['reference']; + reference = map['reference']; if (map.containsKey('trans')) { trans = map['trans']; } else if (map.containsKey('id')) { @@ -47,7 +47,7 @@ class TransactionApiResponse extends ApiResponse { } bool hasValidUrl() { - if (otpMessage == null || otpMessage!.length == 0) { + if (otpMessage == null || otpMessage!.isEmpty) { return false; } diff --git a/lib/src/api/request/bank_charge_request_body.dart b/lib/src/api/request/bank_charge_request_body.dart index 2370cee1..3148a45f 100644 --- a/lib/src/api/request/bank_charge_request_body.dart +++ b/lib/src/api/request/bank_charge_request_body.dart @@ -3,15 +3,15 @@ import 'package:flutter_paystack/src/models/bank.dart'; import 'package:flutter_paystack/src/models/charge.dart'; class BankChargeRequestBody extends BaseRequestBody { - String _accessCode; - BankAccount _account; + final String _accessCode; + final BankAccount _account; String? _birthday; String? _token; String? transactionId; BankChargeRequestBody(Charge charge) - : this._accessCode = charge.accessCode!, - this._account = charge.account!; + : _accessCode = charge.accessCode!, + _account = charge.account!; Map tokenParams() => {fieldDevice: device, 'token': _token}; diff --git a/lib/src/api/request/base_request_body.dart b/lib/src/api/request/base_request_body.dart index 3e51b8fc..933bcbbb 100644 --- a/lib/src/api/request/base_request_body.dart +++ b/lib/src/api/request/base_request_body.dart @@ -14,6 +14,6 @@ abstract class BaseRequestBody { _setDeviceId() { String deviceId = PaystackPlugin.platformInfo.deviceId; - this._device = deviceId; + _device = deviceId; } } diff --git a/lib/src/api/request/card_request_body.dart b/lib/src/api/request/card_request_body.dart index 11ff18d6..67064532 100644 --- a/lib/src/api/request/card_request_body.dart +++ b/lib/src/api/request/card_request_body.dart @@ -7,54 +7,54 @@ import 'package:flutter_paystack/src/common/crypto.dart'; import 'package:flutter_paystack/src/models/charge.dart'; class CardRequestBody extends BaseRequestBody { - static const String fieldClientData = "clientdata"; - static const String fieldLast4 = "last4"; - static const String fieldAccessCode = "access_code"; - static const String fieldPublicKey = "public_key"; - static const String fieldEmail = "email"; - static const String fieldAmount = "amount"; - static const String fieldReference = "reference"; - static const String fieldSubAccount = "subaccount"; - static const String fieldTransactionCharge = "transaction_charge"; - static const String fieldBearer = "bearer"; - static const String fieldHandle = "handle"; - static const String fieldMetadata = "metadata"; - static const String fieldCurrency = "currency"; - static const String fieldPlan = "plan"; + static const String fieldClientData = 'clientdata'; + static const String fieldLast4 = 'last4'; + static const String fieldAccessCode = 'access_code'; + static const String fieldPublicKey = 'public_key'; + static const String fieldEmail = 'email'; + static const String fieldAmount = 'amount'; + static const String fieldReference = 'reference'; + static const String fieldSubAccount = 'subaccount'; + static const String fieldTransactionCharge = 'transaction_charge'; + static const String fieldBearer = 'bearer'; + static const String fieldHandle = 'handle'; + static const String fieldMetadata = 'metadata'; + static const String fieldCurrency = 'currency'; + static const String fieldPlan = 'plan'; - String _clientData; - String? _last4; + final String _clientData; + final String? _last4; final String? _publicKey; - String? _accessCode; - String? _email; - String _amount; - String? _reference; - String? _subAccount; - String? _transactionCharge; - String? _bearer; + final String? _accessCode; + final String? _email; + final String _amount; + final String? _reference; + final String? _subAccount; + final String? _transactionCharge; + final String? _bearer; String? _handle; - String? _metadata; - String? _currency; - String? _plan; - Map? _additionalParameters; + final String? _metadata; + final String? _currency; + final String? _plan; + final Map? _additionalParameters; CardRequestBody._(this._publicKey, Charge charge, String clientData) - : this._clientData = clientData, - this._last4 = charge.card!.last4Digits, - this._email = charge.email, - this._amount = charge.amount.toString(), - this._reference = charge.reference, - this._subAccount = charge.subAccount, - this._transactionCharge = + : _clientData = clientData, + _last4 = charge.card!.last4Digits, + _email = charge.email, + _amount = charge.amount.toString(), + _reference = charge.reference, + _subAccount = charge.subAccount, + _transactionCharge = charge.transactionCharge != null && charge.transactionCharge! > 0 ? charge.transactionCharge.toString() : null, - this._bearer = charge.bearer != null ? getBearer(charge.bearer) : null, - this._metadata = charge.metadata, - this._plan = charge.plan, - this._currency = charge.currency, - this._accessCode = charge.accessCode, - this._additionalParameters = charge.additionalParameters; + _bearer = charge.bearer != null ? getBearer(charge.bearer) : null, + _metadata = charge.metadata, + _plan = charge.plan, + _currency = charge.currency, + _accessCode = charge.accessCode, + _additionalParameters = charge.additionalParameters; static Future getChargeRequestBody( String publicKey, Charge charge) async { @@ -63,7 +63,7 @@ class CardRequestBody extends BaseRequestBody { } addPin(String pin) async { - this._handle = await Crypto.encrypt(pin); + _handle = await Crypto.encrypt(pin); } static String? getBearer(Bearer? bearer) { @@ -71,10 +71,10 @@ class CardRequestBody extends BaseRequestBody { String? bearerStr; switch (bearer) { case Bearer.SubAccount: - bearerStr = "subaccount"; + bearerStr = 'subaccount'; break; case Bearer.Account: - bearerStr = "account"; + bearerStr = 'account'; break; } return bearerStr; diff --git a/lib/src/api/request/validate_request_body.dart b/lib/src/api/request/validate_request_body.dart index b23fde39..b37988ab 100644 --- a/lib/src/api/request/validate_request_body.dart +++ b/lib/src/api/request/validate_request_body.dart @@ -1,8 +1,8 @@ import 'package:flutter_paystack/src/api/request/base_request_body.dart'; class ValidateRequestBody extends BaseRequestBody { - String _fieldTrans = 'trans'; - String _fieldToken = 'token'; + final String _fieldTrans = 'trans'; + final String _fieldToken = 'token'; String? trans; String? token; diff --git a/lib/src/api/service/bank_service.dart b/lib/src/api/service/bank_service.dart index 6fcc18ca..8246f503 100644 --- a/lib/src/api/service/bank_service.dart +++ b/lib/src/api/service/bank_service.dart @@ -1,16 +1,18 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:developer'; import 'dart:io'; import 'package:async/async.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter_paystack/src/api/model/transaction_api_response.dart'; import 'package:flutter_paystack/src/api/request/bank_charge_request_body.dart'; import 'package:flutter_paystack/src/api/service/base_service.dart'; import 'package:flutter_paystack/src/api/service/contracts/banks_service_contract.dart'; import 'package:flutter_paystack/src/common/exceptions.dart'; +import 'package:flutter_paystack/src/common/extensions.dart'; import 'package:flutter_paystack/src/common/my_strings.dart'; import 'package:flutter_paystack/src/models/bank.dart'; -import 'package:flutter_paystack/src/common/extensions.dart'; import 'package:http/http.dart' as http; class BankService with BaseApiService implements BankServiceContract { @@ -25,7 +27,11 @@ class BankService with BaseApiService implements BankServiceContract { if (response.statusCode == HttpStatus.ok && status!) { return responseBody['data']['id'].toString(); } - } catch (e) {} + } catch (e) { + if (kDebugMode) { + log(e.toString()); + } + } return null; } @@ -62,7 +68,7 @@ class BankService with BaseApiService implements BankServiceContract { if (statusCode == HttpStatus.ok) { return TransactionApiResponse.fromMap(responseBody!); } else { - throw new ChargeException(Strings.unKnownResponse); + throw ChargeException(Strings.unKnownResponse); } } @@ -81,12 +87,16 @@ class BankService with BaseApiService implements BankServiceContract { var data = body['data']; List banks = []; for (var bank in data) { - banks.add(new Bank(bank['name'], bank['id'])); + banks.add(Bank(bank['name'], bank['id'])); } return banks; - } catch (e) {} + } catch (e) { + if (kDebugMode) { + log(e.toString()); + } + } return null; } } -AsyncMemoizer?>? banksMemo = new AsyncMemoizer?>(); +AsyncMemoizer?>? banksMemo = AsyncMemoizer?>(); diff --git a/lib/src/api/service/card_service.dart b/lib/src/api/service/card_service.dart index f84f3b34..d8a4f037 100644 --- a/lib/src/api/service/card_service.dart +++ b/lib/src/api/service/card_service.dart @@ -2,24 +2,31 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:flutter/foundation.dart'; import 'package:flutter_paystack/src/api/model/transaction_api_response.dart'; import 'package:flutter_paystack/src/api/service/base_service.dart'; import 'package:flutter_paystack/src/api/service/contracts/cards_service_contract.dart'; import 'package:flutter_paystack/src/common/exceptions.dart'; -import 'package:flutter_paystack/src/common/my_strings.dart'; import 'package:flutter_paystack/src/common/extensions.dart'; +import 'package:flutter_paystack/src/common/my_strings.dart'; import 'package:http/http.dart' as http; class CardService with BaseApiService implements CardServiceContract { @override Future chargeCard(Map fields) async { - var url = '$baseUrl/charge/mobile_charge'; + final url = '$baseUrl/charge/mobile_charge'; + debugPrint(url); - http.Response response = - await http.post(url.toUri(), body: fields, headers: headers); - var body = response.body; + http.Response response = await http.post( + url.toUri(), + body: fields, + headers: headers, + ); + final body = response.body; + debugPrint('Body: $body'); - var statusCode = response.statusCode; + final statusCode = response.statusCode; + debugPrint('statusCode: $statusCode'); switch (statusCode) { case HttpStatus.ok: @@ -34,35 +41,50 @@ class CardService with BaseApiService implements CardServiceContract { @override Future validateCharge( - Map fields) async { - var url = '$baseUrl/charge/validate'; + Map fields, + ) async { + final url = '$baseUrl/charge/validate'; + debugPrint(url); - http.Response response = - await http.post(url.toUri(), body: fields, headers: headers); - var body = response.body; + http.Response response = await http.post( + url.toUri(), + body: fields, + headers: headers, + ); + final body = response.body; + debugPrint('Body: $body'); - var statusCode = response.statusCode; + final statusCode = response.statusCode; + debugPrint('statusCode: $statusCode'); if (statusCode == HttpStatus.ok) { Map responseBody = json.decode(body); return TransactionApiResponse.fromMap(responseBody); } else { - throw CardException('validate charge transaction failed with ' - 'status code: $statusCode and response: $body'); + throw CardException( + 'validate charge transaction failed with ' + 'status code: $statusCode and response: $body', + ); } } + @override Future reQueryTransaction(String? trans) async { - var url = '$baseUrl/requery/$trans'; + final url = '$baseUrl/requery/$trans'; + debugPrint(url); http.Response response = await http.get(url.toUri(), headers: headers); - var body = response.body; - var statusCode = response.statusCode; + final body = response.body; + debugPrint('Body: $body'); + final statusCode = response.statusCode; + debugPrint('statusCode: $statusCode'); if (statusCode == HttpStatus.ok) { Map responseBody = json.decode(body); return TransactionApiResponse.fromMap(responseBody); } else { - throw ChargeException('requery transaction failed with status code: ' - '$statusCode and response: $body'); + throw ChargeException( + 'requery transaction failed with status code: ' + '$statusCode and response: $body', + ); } } } diff --git a/lib/src/common/card_utils.dart b/lib/src/common/card_utils.dart index 41590c10..9b18b6a8 100644 --- a/lib/src/common/card_utils.dart +++ b/lib/src/common/card_utils.dart @@ -72,7 +72,7 @@ class CardUtils { static int? convertYearTo4Digits(int? year) { if (year == null) return 0; if (year < 100 && year >= 0) { - String prefix = "20"; + String prefix = '20'; year = int.parse('$prefix${year.toString().padLeft(2, '0')}'); } return year; @@ -83,7 +83,7 @@ class CardUtils { if (text == null) { return ''; } - RegExp regExp = new RegExp(r"[^0-9]"); + RegExp regExp = RegExp(r'[^0-9]'); return text.replaceAll(regExp, ''); } @@ -92,7 +92,7 @@ class CardUtils { /// Note: The card details are not validated. static String concatenateCardFields(PaymentCard? card) { if (card == null) { - throw new CardException("Card cannot be null"); + throw CardException('Card cannot be null'); } String? number = StringUtils.nullify(card.number); @@ -108,9 +108,9 @@ class CardUtils { ]; if (!StringUtils.isEmpty(number)) { - return cardFields.join("*"); + return cardFields.join('*'); } else { - throw new CardException( + throw CardException( 'Invalid card details: Card number is empty or null'); } } @@ -119,7 +119,7 @@ class CardUtils { /// the first number before the "/" and the last number after the "/ static List getExpiryDate(String? value) { if (value == null) return [-1, -1]; - var split = value.split(new RegExp(r'(\/)')); + var split = value.split(RegExp(r'(\/)')); var month = int.tryParse(split[0]) ?? -1; if (split.length == 1) { return [month, -1]; diff --git a/lib/src/common/crypto.dart b/lib/src/common/crypto.dart index 55369722..addd278b 100644 --- a/lib/src/common/crypto.dart +++ b/lib/src/common/crypto.dart @@ -8,7 +8,7 @@ class Crypto { try { String? result = await Utils.methodChannel - .invokeMethod('getEncryptedData', {"stringData": data}); + .invokeMethod('getEncryptedData', {'stringData': data}); completer.complete(result); } on PlatformException catch (e) { completer.completeError(e); diff --git a/lib/src/common/exceptions.dart b/lib/src/common/exceptions.dart index e7ae834a..7ac98eb3 100644 --- a/lib/src/common/exceptions.dart +++ b/lib/src/common/exceptions.dart @@ -13,15 +13,15 @@ class PaystackException implements Exception { } class AuthenticationException extends PaystackException { - AuthenticationException(String message) : super(message); + AuthenticationException(String super.message); } class CardException extends PaystackException { - CardException(String message) : super(message); + CardException(String super.message); } class ChargeException extends PaystackException { - ChargeException(String? message) : super(message); + ChargeException(super.message); } class InvalidAmountException extends PaystackException { @@ -39,7 +39,7 @@ class InvalidEmailException extends PaystackException { } class PaystackSdkNotInitializedException extends PaystackException { - PaystackSdkNotInitializedException(String message) : super(message); + PaystackSdkNotInitializedException(String super.message); } class ProcessingException extends ChargeException { diff --git a/lib/src/common/paystack.dart b/lib/src/common/paystack.dart index 1af8bb4c..63ee5d3b 100644 --- a/lib/src/common/paystack.dart +++ b/lib/src/common/paystack.dart @@ -17,7 +17,7 @@ import 'package:flutter_paystack/src/widgets/checkout/checkout_widget.dart'; class PaystackPlugin { bool _sdkInitialized = false; - String _publicKey = ""; + String _publicKey = ''; static late PlatformInfo platformInfo; /// Initialize the Paystack object. It should be called as early as possible @@ -31,14 +31,14 @@ class PaystackPlugin { initialize({required String publicKey}) async { assert(() { if (publicKey.isEmpty) { - throw new PaystackException('publicKey cannot be null or empty'); + throw PaystackException('publicKey cannot be null or empty'); } return true; }()); if (sdkInitialized) return; - this._publicKey = publicKey; + _publicKey = publicKey; // Using cascade notation to build the platform specific info try { @@ -50,7 +50,7 @@ class PaystackPlugin { } dispose() { - _publicKey = ""; + _publicKey = ''; _sdkInitialized = false; } @@ -66,8 +66,8 @@ class PaystackPlugin { //validate that sdk has been initialized _validateSdkInitialized(); //check for null value, and length and starts with pk_ - if (_publicKey.isEmpty || !_publicKey.startsWith("pk_")) { - throw new AuthenticationException(Utils.getKeyErrorMsg('public')); + if (_publicKey.isEmpty || !_publicKey.startsWith('pk_')) { + throw AuthenticationException(Utils.getKeyErrorMsg('public')); } } @@ -140,7 +140,7 @@ class PaystackPlugin { _validateSdkInitialized() { if (!sdkInitialized) { - throw new PaystackSdkNotInitializedException( + throw PaystackSdkNotInitializedException( 'Paystack SDK has not been initialized. The SDK has' ' to be initialized before use'); } @@ -154,7 +154,7 @@ class _Paystack { Future chargeCard( {required BuildContext context, required Charge charge}) { - return new CardTransactionManager( + return CardTransactionManager( service: CardService(), charge: charge, context: context, @@ -176,13 +176,13 @@ class _Paystack { switch (method) { case CheckoutMethod.card: if (charge.accessCode == null && charge.reference == null) { - throw new ChargeException(Strings.noAccessCodeReference); + throw ChargeException(Strings.noAccessCodeReference); } break; case CheckoutMethod.bank: case CheckoutMethod.selectable: if (charge.accessCode == null) { - throw new ChargeException('Pass an accesscode'); + throw ChargeException('Pass an accesscode'); } break; } @@ -192,7 +192,7 @@ class _Paystack { CheckoutResponse? response = await showDialog( barrierDismissible: false, context: context, - builder: (BuildContext context) => new CheckoutWidget( + builder: (BuildContext context) => CheckoutWidget( publicKey: publicKey, bankService: BankService(), cardsService: CardService(), @@ -204,21 +204,21 @@ class _Paystack { hideEmail: hideEmail, ), ); - return response == null ? CheckoutResponse.defaults() : response; + return response ?? CheckoutResponse.defaults(); } _validateChargeAndKey(Charge charge) { if (charge.amount.isNegative) { - throw new InvalidAmountException(charge.amount); + throw InvalidAmountException(charge.amount); } if (!StringUtils.isValidEmail(charge.email)) { - throw new InvalidEmailException(charge.email); + throw InvalidEmailException(charge.email); } } } -typedef void OnTransactionChange(Transaction transaction); -typedef void OnTransactionError( +typedef OnTransactionChange = void Function(Transaction transaction); +typedef OnTransactionError = void Function( Object e, Transaction transaction); enum CheckoutMethod { card, bank, selectable } diff --git a/lib/src/common/platform_info.dart b/lib/src/common/platform_info.dart index f260da2a..8bb753e0 100644 --- a/lib/src/common/platform_info.dart +++ b/lib/src/common/platform_info.dart @@ -11,11 +11,11 @@ class PlatformInfo { static Future fromMethodChannel(MethodChannel channel) async { // TODO: Update for every new versions. // And there should a better way to fucking do this - final pluginVersion = "1.0.5"; + const pluginVersion = '1.0.7'; final platform = Platform.operatingSystem; - String userAgent = "${platform}_Paystack_$pluginVersion"; - String deviceId = await channel.invokeMethod('getDeviceId') ?? ""; + String userAgent = '${platform}_Paystack_$pluginVersion'; + String deviceId = await channel.invokeMethod('getDeviceId') ?? ''; return PlatformInfo._( userAgent: userAgent, paystackBuild: pluginVersion, @@ -24,12 +24,10 @@ class PlatformInfo { } const PlatformInfo._({ - required String userAgent, - required String paystackBuild, - required String deviceId, - }) : userAgent = userAgent, - paystackBuild = paystackBuild, - deviceId = deviceId; + required this.userAgent, + required this.paystackBuild, + required this.deviceId, + }); @override String toString() { diff --git a/lib/src/common/string_utils.dart b/lib/src/common/string_utils.dart index c3bd2f24..c779100d 100644 --- a/lib/src/common/string_utils.dart +++ b/lib/src/common/string_utils.dart @@ -1,11 +1,11 @@ class StringUtils { static bool isEmpty(String? value) { - return value == null || value.length < 1 || value.toLowerCase() == "null"; + return value == null || value.isEmpty || value.toLowerCase() == 'null'; } static bool isValidEmail(String? email) { if (isEmpty(email)) return false; - RegExp regExp = new RegExp(_emailRegex); + RegExp regExp = RegExp(_emailRegex); return regExp.hasMatch(email!); } @@ -20,10 +20,8 @@ class StringUtils { } } -const _emailRegex = r"[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" + - "\\@" + - "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" + - "(" + - "\\." + - "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" + - ")+"; +const _emailRegex = r'[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}' + '\\@' + '[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}' + '(' + '\\.[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25})+'; diff --git a/lib/src/common/utils.dart b/lib/src/common/utils.dart index 7f4e915e..92bf51ad 100644 --- a/lib/src/common/utils.dart +++ b/lib/src/common/utils.dart @@ -3,7 +3,7 @@ import 'package:intl/intl.dart'; class Utils { static const MethodChannel methodChannel = - const MethodChannel('plugins.wilburt/flutter_paystack'); + MethodChannel('plugins.wilburt/flutter_paystack'); static String getKeyErrorMsg(String keyType) { return 'Invalid $keyType key. You must use a valid $keyType key. Ensure that you ' @@ -17,13 +17,13 @@ class Utils { NumberFormat.currency(locale: locale, name: '$currency\u{0020}'); static String formatAmount(num amountInBase) { - if (_currencyFormatter == null) throw "Currency formatter not initialized."; + if (_currencyFormatter == null) throw 'Currency formatter not initialized.'; return _currencyFormatter!.format((amountInBase / 100)); } /// Add double spaces after every 4th character static String addSpaces(String text) { - var buffer = new StringBuffer(); + var buffer = StringBuffer(); for (int i = 0; i < text.length; i++) { buffer.write(text[i]); var nonZeroIndex = i + 1; diff --git a/lib/src/models/card.dart b/lib/src/models/card.dart index 6c86764e..e48171a0 100644 --- a/lib/src/models/card.dart +++ b/lib/src/models/card.dart @@ -134,17 +134,17 @@ class PaymentCard { this.addressLine3 = StringUtils.nullify(addressLine3); this.addressLine4 = StringUtils.nullify(addressLine4); this.addressCountry = StringUtils.nullify(addressCountry); - this.addressPostalCode = StringUtils.nullify(addressPostalCode); + addressPostalCode = StringUtils.nullify(addressPostalCode); this.country = StringUtils.nullify(country); - this.type = type; + type = type; } PaymentCard.empty() { - this.expiryYear = 0; - this.expiryMonth = 0; - this._number = null; - this.cvc = null; + expiryYear = 0; + expiryMonth = 0; + _number = null; + cvc = null; } /// Validates the CVC or CVV of the card @@ -162,7 +162,7 @@ class PaymentCard { /// Validates the CVC or CVV of a card. /// Returns true if CVC is valid and false otherwise bool validCVC(String? cardCvc) { - cardCvc ??= this.cvc; + cardCvc ??= cvc; if (cardCvc == null || cardCvc.trim().isEmpty) return false; @@ -177,14 +177,12 @@ class PaymentCard { /// Validates the number of the card /// Returns true if the number is valid. Returns false otherwise bool validNumber(String? cardNumber) { - if (cardNumber == null) { - cardNumber = this.number; - } + cardNumber ??= number; if (StringUtils.isEmpty(cardNumber)) return false; // Remove all non digits var formattedNumber = - cardNumber!.trim().replaceAll(new RegExp(r'[^0-9]'), ''); + cardNumber!.trim().replaceAll(RegExp(r'[^0-9]'), ''); // Verve card needs no other validation except it matched pattern if (CardType.fullPatternVerve.hasMatch(formattedNumber)) { @@ -242,19 +240,19 @@ class PaymentCard { abstract class CardType { // Card types - static const String visa = "Visa"; - static const String masterCard = "MasterCard"; - static const String americanExpress = "American Express"; - static const String dinersClub = "Diners Club"; - static const String discover = "Discover"; - static const String jcb = "JCB"; - static const String verve = "VERVE"; - static const String unknown = "Unknown"; + static const String visa = 'Visa'; + static const String masterCard = 'MasterCard'; + static const String americanExpress = 'American Express'; + static const String dinersClub = 'Diners Club'; + static const String discover = 'Discover'; + static const String jcb = 'JCB'; + static const String verve = 'VERVE'; + static const String unknown = 'Unknown'; // Length for some cards - static final int maxLengthNormal = 16; - static final int maxLengthAmericanExpress = 15; - static final int maxLengthDinersClub = 14; + static const int maxLengthNormal = 16; + static const int maxLengthAmericanExpress = 15; + static const int maxLengthDinersClub = 14; // Regular expressions to match complete numbers of the card //source of these regex patterns http://stackoverflow.com/questions/72768/how-do-you-detect-credit-card-type-based-on-number diff --git a/lib/src/models/charge.dart b/lib/src/models/charge.dart index 4a4f52ce..eeab08d2 100644 --- a/lib/src/models/charge.dart +++ b/lib/src/models/charge.dart @@ -37,17 +37,17 @@ class Charge { String? subAccount; Charge() { - this._metadata = {}; - this.amount = -1; - this._additionalParameters = {}; - this._customFields = []; - this._metadata!['custom_fields'] = this._customFields; - this.locale = Strings.nigerianLocale; - this.currency = Strings.ngn; + _metadata = {}; + amount = -1; + _additionalParameters = {}; + _customFields = []; + _metadata!['custom_fields'] = _customFields; + locale = Strings.nigerianLocale; + currency = Strings.ngn; } addParameter(String key, String value) { - this._additionalParameters![key] = value; + _additionalParameters![key] = value; } Map? get additionalParameters => _additionalParameters; @@ -57,14 +57,14 @@ class Charge { set account(BankAccount? value) { if (value == null) { // Precaution to avoid setting of this field outside the library - throw new PaystackException('account cannot be null'); + throw PaystackException('account cannot be null'); } _account = value; } putMetaData(String name, dynamic value) { - this._metadata![name] = value; - this._hasMeta = true; + _metadata![name] = value; + _hasMeta = true; } putCustomField(String displayName, String value) { @@ -72,10 +72,10 @@ class Charge { 'value': value, 'display_name': displayName, 'variable_name': - displayName.toLowerCase().replaceAll(new RegExp(r'[^a-z0-9 ]'), "_") + displayName.toLowerCase().replaceAll(RegExp(r'[^a-z0-9 ]'), '_') }; - this._customFields!.add(customMap); - this._hasMeta = true; + _customFields!.add(customMap); + _hasMeta = true; } String? get metadata { diff --git a/lib/src/models/transaction.dart b/lib/src/models/transaction.dart index c6206d0d..f7276326 100644 --- a/lib/src/models/transaction.dart +++ b/lib/src/models/transaction.dart @@ -7,9 +7,9 @@ class Transaction { loadFromResponse(TransactionApiResponse t) { if (t.hasValidReferenceAndTrans()) { - this._reference = t.reference; - this._id = t.trans; - this._message = t.message; + _reference = t.reference; + _id = t.trans; + _message = t.message; } } @@ -17,7 +17,7 @@ class Transaction { String? get id => _id; - String get message => _message ?? ""; + String get message => _message ?? ''; bool hasStartedOnServer() { return (reference != null) && (id != null); diff --git a/lib/src/transaction/bank_transaction_manager.dart b/lib/src/transaction/bank_transaction_manager.dart index 3e3fc12b..454238da 100644 --- a/lib/src/transaction/bank_transaction_manager.dart +++ b/lib/src/transaction/bank_transaction_manager.dart @@ -1,13 +1,11 @@ import 'dart:async'; -import 'package:flutter/material.dart'; import 'package:flutter_paystack/src/api/model/transaction_api_response.dart'; import 'package:flutter_paystack/src/api/request/bank_charge_request_body.dart'; import 'package:flutter_paystack/src/api/service/contracts/banks_service_contract.dart'; import 'package:flutter_paystack/src/common/exceptions.dart'; import 'package:flutter_paystack/src/common/my_strings.dart'; import 'package:flutter_paystack/src/common/paystack.dart'; -import 'package:flutter_paystack/src/models/charge.dart'; import 'package:flutter_paystack/src/models/checkout_response.dart'; import 'package:flutter_paystack/src/transaction/base_transaction_manager.dart'; @@ -15,12 +13,12 @@ class BankTransactionManager extends BaseTransactionManager { BankChargeRequestBody? chargeRequestBody; final BankServiceContract service; - BankTransactionManager( - {required this.service, - required Charge charge, - required BuildContext context, - required String publicKey}) - : super(charge: charge, context: context, publicKey: publicKey); + BankTransactionManager({ + required this.service, + required super.charge, + required super.context, + required super.publicKey, + }); Future chargeBank() async { await initiate(); @@ -29,7 +27,7 @@ class BankTransactionManager extends BaseTransactionManager { @override postInitiate() { - chargeRequestBody = new BankChargeRequestBody(charge); + chargeRequestBody = BankChargeRequestBody(charge); } @override @@ -61,40 +59,45 @@ class BankTransactionManager extends BaseTransactionManager { @override Future handleApiResponse( - TransactionApiResponse response) async { - var auth = response.auth; + TransactionApiResponse apiResponse, + ) async { + var auth = apiResponse.auth; - if (response.status == 'success') { + if (apiResponse.status == 'success') { setProcessingOff(); return onSuccess(transaction); } if (auth == 'failed' || auth == 'timeout') { - return notifyProcessingError(new ChargeException(response.message)); + return notifyProcessingError(ChargeException(apiResponse.message)); } if (auth == 'birthday') { - return getBirthdayFrmUI(response); + return getBirthdayFrmUI(apiResponse); } if (auth == 'payment_token' || auth == 'registration_token') { - return getOtpFrmUI(response: response); + return getOtpFrmUI(response: apiResponse); } return notifyProcessingError( - PaystackException(response.message ?? Strings.unKnownResponse)); + PaystackException(apiResponse.message ?? Strings.unKnownResponse)); } @override Future handleOtpInput( - String token, TransactionApiResponse? response) { - chargeRequestBody!.token = token; + String otp, + TransactionApiResponse? response, + ) { + chargeRequestBody!.token = otp; return _sendTokenToServer(); } @override Future handleBirthdayInput( - String birthday, TransactionApiResponse response) { + String birthday, + TransactionApiResponse response, + ) { chargeRequestBody!.birthday = birthday; return _chargeAccount(); } diff --git a/lib/src/transaction/base_transaction_manager.dart b/lib/src/transaction/base_transaction_manager.dart index a9b930ef..81347f30 100644 --- a/lib/src/transaction/base_transaction_manager.dart +++ b/lib/src/transaction/base_transaction_manager.dart @@ -1,7 +1,9 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:developer'; import 'dart:io'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_paystack/src/api/model/transaction_api_response.dart'; import 'package:flutter_paystack/src/common/exceptions.dart'; @@ -49,9 +51,7 @@ abstract class BaseTransactionManager { Future _initApiResponse( TransactionApiResponse? apiResponse) { - if (apiResponse == null) { - apiResponse = TransactionApiResponse.unknownServerResponse(); - } + apiResponse ??= TransactionApiResponse.unknownServerResponse(); transaction.loadFromResponse(apiResponse); @@ -72,7 +72,7 @@ abstract class BaseTransactionManager { setProcessingOff(); if (e is TimeoutException || e is SocketException) { - e = 'Please check your internet connection or try again later'; + e = 'Please check your internet connection or try again later'; } return CheckoutResponse( message: e.toString(), @@ -81,7 +81,7 @@ abstract class BaseTransactionManager { card: charge.card?..nullifyNumber(), account: charge.account, method: checkoutMethod(), - verify: !(e is PaystackException)); + verify: e is! PaystackException); } setProcessingOff() => processing = false; @@ -108,18 +108,17 @@ abstract class BaseTransactionManager { String? otp = await showDialog( context: context, barrierDismissible: false, - builder: (BuildContext context) => new OtpWidget( - message: message != null - ? message - : response!.displayText == null || response.displayText!.isEmpty + builder: (BuildContext context) => OtpWidget( + message: message ?? + (response!.displayText == null || response.displayText!.isEmpty ? response.message - : response.displayText)); + : response.displayText))); if (otp != null && otp.isNotEmpty) { return handleOtpInput(otp, response); } else { return notifyProcessingError( - PaystackException("You did not provide an OTP")); + PaystackException('You did not provide an OTP')); } } @@ -127,14 +126,20 @@ abstract class BaseTransactionManager { TransactionApiResponse apiResponse = TransactionApiResponse.unknownServerResponse(); - String? result = await Utils.methodChannel - .invokeMethod('getAuthorization', {"authUrl": url}); + String? result = await Utils.methodChannel.invokeMethod( + 'getAuthorization', + {'authUrl': url}, + ); if (result != null) { try { Map responseMap = json.decode(result); apiResponse = TransactionApiResponse.fromMap(responseMap); - } catch (e) {} + } catch (e) { + if (kDebugMode) { + log(e.toString()); + } + } } return _initApiResponse(apiResponse); } @@ -143,58 +148,65 @@ abstract class BaseTransactionManager { String? pin = await showDialog( barrierDismissible: false, context: context, - builder: (BuildContext context) => new PinWidget()); + builder: (BuildContext context) => const PinWidget()); if (pin != null && pin.length == 4) { return handlePinInput(pin); } else { return notifyProcessingError( - PaystackException("PIN must be exactly 4 digits")); + PaystackException('PIN must be exactly 4 digits'), + ); } } Future getBirthdayFrmUI( - TransactionApiResponse response) async { + TransactionApiResponse response, + ) async { String? birthday = await showDialog( - barrierDismissible: false, - context: context, - builder: (BuildContext context) { - var messageText = - response.displayText == null || response.displayText!.isEmpty - ? response.message! - : response.displayText!; - return new BirthdayWidget(message: messageText); - }); + barrierDismissible: false, + context: context, + builder: (BuildContext context) { + var messageText = + response.displayText == null || response.displayText!.isEmpty + ? response.message! + : response.displayText!; + return BirthdayWidget(message: messageText); + }, + ); if (birthday != null && birthday.isNotEmpty) { return handleBirthdayInput(birthday, response); } else { return notifyProcessingError( - PaystackException("Date of birth not supplied")); + PaystackException('Date of birth not supplied'), + ); } } CheckoutResponse onSuccess(Transaction transaction) { return CheckoutResponse( - message: transaction.message, - reference: transaction.reference, - status: true, - card: charge.card?..nullifyNumber(), - account: charge.account, - method: checkoutMethod(), - verify: true); + message: transaction.message, + reference: transaction.reference, + status: true, + card: charge.card?..nullifyNumber(), + account: charge.account, + method: checkoutMethod(), + verify: true, + ); } Future handleCardInput() { throw UnsupportedError( - "Handling of card input not supported for Bank payment method"); + 'Handling of card input not supported for Bank payment method'); } Future handleOtpInput( - String otp, TransactionApiResponse? response); + String otp, + TransactionApiResponse? response, + ); Future handlePinInput(String pin) { - throw UnsupportedError("Pin Input not supported for ${checkoutMethod()}"); + throw UnsupportedError('Pin Input not supported for ${checkoutMethod()}'); } postInitiate(); @@ -202,7 +214,7 @@ abstract class BaseTransactionManager { Future handleBirthdayInput( String birthday, TransactionApiResponse response) { throw UnsupportedError( - "Birthday Input not supported for ${checkoutMethod()}"); + 'Birthday Input not supported for ${checkoutMethod()}'); } CheckoutMethod checkoutMethod(); diff --git a/lib/src/transaction/card_transaction_manager.dart b/lib/src/transaction/card_transaction_manager.dart index 9604d470..242820f6 100644 --- a/lib/src/transaction/card_transaction_manager.dart +++ b/lib/src/transaction/card_transaction_manager.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'package:flutter/material.dart'; import 'package:flutter_paystack/src/api/model/transaction_api_response.dart'; import 'package:flutter_paystack/src/api/request/card_request_body.dart'; import 'package:flutter_paystack/src/api/request/validate_request_body.dart'; @@ -8,7 +7,6 @@ import 'package:flutter_paystack/src/api/service/contracts/cards_service_contrac import 'package:flutter_paystack/src/common/exceptions.dart'; import 'package:flutter_paystack/src/common/my_strings.dart'; import 'package:flutter_paystack/src/common/paystack.dart'; -import 'package:flutter_paystack/src/models/charge.dart'; import 'package:flutter_paystack/src/models/checkout_response.dart'; import 'package:flutter_paystack/src/transaction/base_transaction_manager.dart'; @@ -18,14 +16,13 @@ class CardTransactionManager extends BaseTransactionManager { final CardServiceContract service; var _invalidDataSentRetries = 0; - CardTransactionManager( - {required Charge charge, - required this.service, - required BuildContext context, - required String publicKey}) - : assert(charge.card != null, - 'please add a card to the charge before ' 'calling chargeCard'), - super(charge: charge, context: context, publicKey: publicKey); + CardTransactionManager({ + required super.charge, + required this.service, + required super.context, + required super.publicKey, + }) : assert(charge.card != null, + 'please add a card to the charge before ' 'calling chargeCard'); @override postInitiate() async { @@ -43,7 +40,7 @@ class CardTransactionManager extends BaseTransactionManager { return sendCharge(); } } catch (e) { - if (!(e is ProcessingException)) { + if (e is! ProcessingException) { setProcessingOff(); } return CheckoutResponse( @@ -52,7 +49,7 @@ class CardTransactionManager extends BaseTransactionManager { status: false, card: charge.card?..nullifyNumber(), method: CheckoutMethod.card, - verify: !(e is PaystackException)); + verify: e is! PaystackException); } } diff --git a/lib/src/widgets/animated_widget.dart b/lib/src/widgets/animated_widget.dart index d03a7ae9..0e7b5df7 100644 --- a/lib/src/widgets/animated_widget.dart +++ b/lib/src/widgets/animated_widget.dart @@ -6,8 +6,8 @@ class CustomAnimatedWidget extends StatelessWidget { final Widget child; CustomAnimatedWidget( - {required this.child, required AnimationController controller}) - : _animation = new CurvedAnimation( + {super.key, required this.child, required AnimationController controller}) + : _animation = CurvedAnimation( parent: controller, curve: Curves.fastOutSlowIn, ); @@ -18,15 +18,15 @@ class CustomAnimatedWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return new FadeTransition( + return FadeTransition( opacity: _animation, - child: new SlideTransition( + child: SlideTransition( position: slideTween.animate(_animation), - child: new ScaleTransition( + child: ScaleTransition( scale: scaleTween.animate(_animation), - child: new Container( + child: Container( margin: const EdgeInsets.fromLTRB(10.0, 15.0, 10.0, 0.0), - child: new SafeArea(top: false, bottom: false, child: child), + child: SafeArea(top: false, bottom: false, child: child), ), ), ), @@ -42,7 +42,7 @@ abstract class BaseAnimatedState extends BaseState void initState() { super.initState(); alwaysPop = true; - controller = new AnimationController( + controller = AnimationController( duration: const Duration(milliseconds: 500), vsync: this, ); diff --git a/lib/src/widgets/base_widget.dart b/lib/src/widgets/base_widget.dart index 0cb1f836..d28d0aea 100644 --- a/lib/src/widgets/base_widget.dart +++ b/lib/src/widgets/base_widget.dart @@ -12,7 +12,7 @@ abstract class BaseState extends State { @override Widget build(BuildContext context) { - return new WillPopScope( + return WillPopScope( onWillPop: _onWillPop, child: buildChild(context), ); @@ -33,40 +33,40 @@ abstract class BaseState extends State { return false; } - var text = new Text(confirmationMessage); + var text = Text(confirmationMessage); var dialog = Platform.isIOS - ? new CupertinoAlertDialog( + ? CupertinoAlertDialog( content: text, actions: [ - new CupertinoDialogAction( - child: const Text('Yes'), + CupertinoDialogAction( isDestructiveAction: true, onPressed: () { Navigator.pop(context, true); // Returning true to // _onWillPop will pop again. }, + child: const Text('Yes'), ), - new CupertinoDialogAction( - child: const Text('No'), + CupertinoDialogAction( isDefaultAction: true, onPressed: () { Navigator.pop(context, false); // Pops the confirmation dialog but not the page. }, + child: const Text('No'), ), ], ) - : new AlertDialog( + : AlertDialog( content: text, actions: [ - new TextButton( + TextButton( child: const Text('NO'), onPressed: () { Navigator.of(context).pop( false); // Pops the confirmation dialog but not the page. }), - new TextButton( + TextButton( child: const Text('YES'), onPressed: () { Navigator.of(context).pop( diff --git a/lib/src/widgets/birthday_widget.dart b/lib/src/widgets/birthday_widget.dart index 20449a42..308b6daf 100644 --- a/lib/src/widgets/birthday_widget.dart +++ b/lib/src/widgets/birthday_widget.dart @@ -1,7 +1,7 @@ import 'dart:io'; -import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_paystack/src/widgets/base_widget.dart'; import 'package:flutter_paystack/src/widgets/buttons.dart'; import 'package:flutter_paystack/src/widgets/common/extensions.dart'; @@ -13,14 +13,14 @@ const double _kPickerSheetHeight = 216.0; class BirthdayWidget extends StatefulWidget { final String message; - BirthdayWidget({required this.message}); + const BirthdayWidget({super.key, required this.message}); @override - _BirthdayWidgetState createState() => _BirthdayWidgetState(); + BaseState createState() => _BirthdayWidgetState(); } class _BirthdayWidgetState extends BaseState { - var _heightBox = const SizedBox(height: 20.0); + final _heightBox = const SizedBox(height: 20.0); DateTime? _pickedDate; @override @@ -31,61 +31,67 @@ class _BirthdayWidgetState extends BaseState { @override Widget buildChild(BuildContext context) { - return new CustomAlertDialog( - content: new SingleChildScrollView( - child: Container( - padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), - child: new Column( - children: [ - new Image.asset('assets/images/dob.png', - width: 30.0, package: 'flutter_paystack'), - _heightBox, - new Text( - widget.message, - textAlign: TextAlign.center, - style: TextStyle( - fontWeight: FontWeight.w500, - color: context.textTheme().headline6?.color, - fontSize: 15.0, + return CustomAlertDialog( + content: SingleChildScrollView( + child: Container( + padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), + child: Column( + children: [ + Image.asset( + 'assets/images/dob.png', + width: 30.0, + package: 'flutter_paystack', ), - ), - _heightBox, - _pickedDate == null - ? new WhiteButton( - onPressed: _selectBirthday, text: 'Pick birthday') - : new WhiteButton( - onPressed: _selectBirthday, - flat: true, - child: new Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - new Flexible(flex: 4, child: dateItem(_getMonth())), - new Flexible(flex: 2, child: dateItem(_getDay())), - new Flexible(flex: 3, child: dateItem(_getYear())) - ], + _heightBox, + Text( + widget.message, + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.w500, + color: context.textTheme().titleLarge?.color, + fontSize: 15.0, + ), + ), + _heightBox, + _pickedDate == null + ? WhiteButton( + onPressed: _selectBirthday, + text: 'Pick birthday', + ) + : WhiteButton( + onPressed: _selectBirthday, + flat: true, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible(flex: 4, child: dateItem(_getMonth())), + Flexible(flex: 2, child: dateItem(_getDay())), + Flexible(flex: 3, child: dateItem(_getYear())) + ], + ), ), - ), - new SizedBox( - height: _pickedDate == null ? 5.0 : 20.0, - ), - _pickedDate == null - ? new Container() - : new AccentButton(onPressed: _onAuthorize, text: 'Authorize'), - new Container( - padding: - new EdgeInsets.only(top: _pickedDate == null ? 15.0 : 20.0), - child: new WhiteButton( - onPressed: onCancelPress, - text: 'Cancel', - flat: true, - bold: true, + SizedBox( + height: _pickedDate == null ? 5.0 : 20.0, ), - ), - ], + _pickedDate == null + ? Container() + : AccentButton(onPressed: _onAuthorize, text: 'Authorize'), + Container( + padding: + EdgeInsets.only(top: _pickedDate == null ? 15.0 : 20.0), + child: WhiteButton( + onPressed: onCancelPress, + text: 'Cancel', + flat: true, + bold: true, + ), + ), + ], + ), ), ), - )); + ); } void _selectBirthday() async { @@ -93,37 +99,40 @@ class _BirthdayWidgetState extends BaseState { setState(() => _pickedDate = date); } - var now = new DateTime.now(); + var now = DateTime.now(); var minimumYear = 1900; if (Platform.isIOS) { showCupertinoModalPopup( - context: context, - builder: (BuildContext context) => Container( - height: _kPickerSheetHeight, - padding: const EdgeInsets.only(top: 6.0), - color: CupertinoColors.white, - child: DefaultTextStyle( - style: const TextStyle( - color: CupertinoColors.black, - fontSize: 22.0, - ), - child: GestureDetector( - // Blocks taps from propagating to the modal sheet and popping. - onTap: () {}, - child: SafeArea( - top: false, - child: new CupertinoDatePicker( - mode: CupertinoDatePickerMode.date, - initialDateTime: now, - maximumDate: now, - minimumYear: minimumYear, - maximumYear: now.year, - onDateTimeChanged: updateDate, - ), - ), + context: context, + builder: (BuildContext context) { + return Container( + height: _kPickerSheetHeight, + padding: const EdgeInsets.only(top: 6.0), + color: CupertinoColors.white, + child: DefaultTextStyle( + style: const TextStyle( + color: CupertinoColors.black, + fontSize: 22.0, + ), + child: GestureDetector( + // Blocks taps from propagating to the modal sheet and popping. + onTap: () {}, + child: SafeArea( + top: false, + child: CupertinoDatePicker( + mode: CupertinoDatePickerMode.date, + initialDateTime: now, + maximumDate: now, + minimumYear: minimumYear, + maximumYear: now.year, + onDateTimeChanged: updateDate, ), ), - )); + ), + ), + ); + }, + ); } else { DateTime? result = await showDatePicker( context: context, @@ -132,7 +141,7 @@ class _BirthdayWidgetState extends BaseState { ? false : true, initialDate: now, - firstDate: new DateTime(minimumYear), + firstDate: DateTime(minimumYear), lastDate: now); updateDate(result); @@ -140,17 +149,17 @@ class _BirthdayWidgetState extends BaseState { } Widget dateItem(String text) { - const side = const BorderSide(color: Colors.grey, width: 0.5); - return new Container( + const side = BorderSide(color: Colors.grey, width: 0.5); + return Container( alignment: Alignment.center, margin: const EdgeInsets.symmetric(horizontal: 2.0), padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0), decoration: const BoxDecoration( - color: Colors.white, - borderRadius: const BorderRadius.all(const Radius.circular(3.0)), - border: - const Border(top: side, right: side, bottom: side, left: side)), - child: new Text( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(3.0)), + border: Border(top: side, right: side, bottom: side, left: side), + ), + child: Text( text, textAlign: TextAlign.center, maxLines: 1, @@ -164,19 +173,19 @@ class _BirthdayWidgetState extends BaseState { } String _getMonth() { - return new DateFormat('MMMM').format(_pickedDate!); + return DateFormat('MMMM').format(_pickedDate!); } String _getDay() { - return new DateFormat('dd').format(_pickedDate!); + return DateFormat('dd').format(_pickedDate!); } String _getYear() { - return new DateFormat('yyyy').format(_pickedDate!); + return DateFormat('yyyy').format(_pickedDate!); } void _onAuthorize() { - String date = new DateFormat('yyyy-MM-dd').format(_pickedDate!); + String date = DateFormat('yyyy-MM-dd').format(_pickedDate!); Navigator.of(context).pop(date); } } diff --git a/lib/src/widgets/buttons.dart b/lib/src/widgets/buttons.dart index b124908e..05a3d59a 100644 --- a/lib/src/widgets/buttons.dart +++ b/lib/src/widgets/buttons.dart @@ -3,26 +3,25 @@ import 'package:flutter_paystack/src/widgets/common/extensions.dart'; class WhiteButton extends _BaseButton { final bool flat; + @override final IconData? iconData; final bool bold; WhiteButton({ - required VoidCallback? onPressed, - String? text, - Widget? child, + required super.onPressed, + super.text, + super.child, this.flat = false, this.bold = true, this.iconData, }) : super( - onPressed: onPressed, showProgress: false, - text: text, - child: child, iconData: iconData, - textStyle: new TextStyle( - fontSize: 14.0, - color: Colors.black87.withOpacity(0.8), - fontWeight: bold ? FontWeight.bold : FontWeight.normal), + textStyle: TextStyle( + fontSize: 14.0, + color: Colors.black87.withOpacity(0.8), + fontWeight: bold ? FontWeight.bold : FontWeight.normal, + ), color: Colors.white, borderSide: flat ? BorderSide.none @@ -30,27 +29,48 @@ class WhiteButton extends _BaseButton { ); } +class CancelButton extends _BaseButton { + const CancelButton({ + required super.onPressed, + super.child, + }) : super( + showProgress: false, + text: 'Cancel', + iconData: null, + textStyle: const TextStyle( + fontSize: 14.0, + color: Color(0xFFB41010), + fontWeight: FontWeight.bold, + ), + color: Colors.white, + borderSide: BorderSide.none, + ); +} + class AccentButton extends StatelessWidget { final VoidCallback onPressed; final String text; final bool showProgress; - AccentButton({ - Key? key, + const AccentButton({ + super.key, required this.onPressed, required this.text, this.showProgress = false, - }) : super(key: key); + }); @override Widget build(BuildContext context) { return _BaseButton( onPressed: onPressed, showProgress: showProgress, - color: context.colorScheme().secondary, + color: context.colorScheme().primary, borderSide: BorderSide.none, textStyle: const TextStyle( - fontSize: 14.0, color: Colors.white, fontWeight: FontWeight.bold), + fontSize: 14.0, + color: Colors.white, + fontWeight: FontWeight.bold, + ), text: text, ); } @@ -66,7 +86,7 @@ class _BaseButton extends StatelessWidget { final IconData? iconData; final Widget? child; - _BaseButton({ + const _BaseButton({ required this.onPressed, required this.showProgress, required this.text, @@ -79,52 +99,55 @@ class _BaseButton extends StatelessWidget { @override Widget build(BuildContext context) { - const borderRadius = const BorderRadius.all(Radius.circular(5.0)); - var textWidget; - if (text != null) { - textWidget = new Text( - text!, - textAlign: TextAlign.center, - style: textStyle, - ); - } - return new Container( + const borderRadius = BorderRadius.all(Radius.circular(5.0)); + + return Container( + width: double.infinity, + height: 50.0, + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: borderRadius, + color: color, + ), + child: SizedBox( width: double.infinity, - height: 50.0, - alignment: Alignment.center, - decoration: new BoxDecoration( - borderRadius: borderRadius, - color: color, + height: double.infinity, + child: TextButton( + onPressed: showProgress ? null : onPressed, + child: showProgress + ? const SizedBox( + width: 20.0, + height: 20.0, + child: CircularProgressIndicator( + strokeWidth: 2.0, + color: Colors.white, + ), + ) + : iconData == null + ? child == null + ? Text( + text ?? '', + textAlign: TextAlign.center, + style: textStyle, + ) + : child! + : Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + iconData, + color: textStyle.color!.withOpacity(0.5), + ), + const SizedBox(width: 2.0), + Text( + text ?? '', + textAlign: TextAlign.center, + style: textStyle, + ), + ], + ), ), - child: new Container( - width: double.infinity, - height: double.infinity, - child: new TextButton( - onPressed: showProgress ? null : onPressed, - child: showProgress - ? new Container( - width: 20.0, - height: 20.0, - child: new CircularProgressIndicator( - strokeWidth: 2.0, - color: Colors.white, - ), - ) - : iconData == null - ? child == null - ? textWidget - : child! - : new Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - new Icon( - iconData, - color: textStyle.color!.withOpacity(0.5), - ), - const SizedBox(width: 2.0), - textWidget, - ], - )), - )); + ), + ); } } diff --git a/lib/src/widgets/card_widget.dart b/lib/src/widgets/card_widget.dart index 6d889e1c..9a266d9d 100644 --- a/lib/src/widgets/card_widget.dart +++ b/lib/src/widgets/card_widget.dart @@ -8,12 +8,10 @@ import 'package:flutter_paystack/src/widgets/input/card_input.dart'; class CardInputWidget extends StatefulWidget { final PaymentCard? card; - CardInputWidget(this.card); + const CardInputWidget(this.card, {super.key}); @override - _CardInputWidgetState createState() { - return new _CardInputWidgetState(); - } + BaseState createState() => _CardInputWidgetState(); } class _CardInputWidgetState extends BaseState { @@ -25,32 +23,32 @@ class _CardInputWidgetState extends BaseState { @override Widget buildChild(BuildContext context) { - return new CustomAlertDialog( - content: new SingleChildScrollView( - child: new Container( + return CustomAlertDialog( + content: SingleChildScrollView( + child: Container( padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), alignment: Alignment.center, - child: new Column( + child: Column( children: [ - new Text( + const Text( 'Please, provide valid card details.', textAlign: TextAlign.center, - style: const TextStyle(fontWeight: FontWeight.w500), + style: TextStyle(fontWeight: FontWeight.w500), ), - new SizedBox( + const SizedBox( height: 35.0, ), - new CardInput( + CardInput( buttonText: 'Continue', card: widget.card, onValidated: _onCardValidated, ), - new SizedBox( + const SizedBox( height: 10.0, ), - new Container( + Container( padding: const EdgeInsets.only(top: 10.0), - child: new WhiteButton( + child: WhiteButton( onPressed: onCancelPress, text: 'Cancel', flat: true, diff --git a/lib/src/widgets/checkout/bank_checkout.dart b/lib/src/widgets/checkout/bank_checkout.dart index cba9ad32..2e735943 100644 --- a/lib/src/widgets/checkout/bank_checkout.dart +++ b/lib/src/widgets/checkout/bank_checkout.dart @@ -22,7 +22,8 @@ class BankCheckout extends StatefulWidget { final BankServiceContract service; final String publicKey; - BankCheckout({ + const BankCheckout({ + super.key, required this.charge, required this.onResponse, required this.onProcessingChange, @@ -31,11 +32,12 @@ class BankCheckout extends StatefulWidget { }); @override - _BankCheckoutState createState() => _BankCheckoutState(onResponse); + BaseCheckoutMethodState createState() => + _BankCheckoutState(onResponse); } class _BankCheckoutState extends BaseCheckoutMethodState { - var _formKey = new GlobalKey(); + final _formKey = GlobalKey(); late AnimationController _controller; late Animation _animation; var _autoValidate = AutovalidateMode.disabled; @@ -50,10 +52,12 @@ class _BankCheckoutState extends BaseCheckoutMethodState { @override void initState() { _futureBanks = widget.service.fetchSupportedBanks(); - _controller = new AnimationController( - vsync: this, duration: const Duration(milliseconds: 300)); - _animation = new Tween(begin: 0.7, end: 1.0).animate( - new CurvedAnimation( + _controller = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 300), + ); + _animation = Tween(begin: 0.7, end: 1.0).animate( + CurvedAnimation( parent: _controller, curve: Curves.ease, ), @@ -72,18 +76,18 @@ class _BankCheckoutState extends BaseCheckoutMethodState { Widget buildAnimatedChild() { return Container( alignment: Alignment.center, - child: new FutureBuilder?>( + child: FutureBuilder?>( future: _futureBanks, builder: (BuildContext context, AsyncSnapshot snapshot) { Widget widget; switch (snapshot.connectionState) { case ConnectionState.waiting: - widget = new Center( - child: new Container( + widget = Center( + child: Container( width: 50.0, height: 50.0, margin: const EdgeInsets.symmetric(vertical: 30.0), - child: new CircularProgressIndicator( + child: const CircularProgressIndicator( strokeWidth: 3.0, ), ), @@ -105,54 +109,52 @@ class _BankCheckoutState extends BaseCheckoutMethodState { } Widget _getCompleteUI(List banks) { - var container = new Container(); - return new Container( - child: new Form( - autovalidateMode: _autoValidate, - key: _formKey, - child: new Column( - mainAxisSize: MainAxisSize.min, - children: [ - new SizedBox( - height: 10.0, - ), - _currentBank == null - ? new Icon( - Icons.account_balance, - size: 35.0, - ) - : container, + var container = Container(); + return Form( + autovalidateMode: _autoValidate, + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox( + height: 10.0, + ), + _currentBank == null + ? const Icon( + Icons.account_balance, + size: 35.0, + ) + : container, + _currentBank == null + ? const SizedBox( + height: 20.0, + ) + : container, + Text( _currentBank == null - ? new SizedBox( - height: 20.0, - ) - : container, - new Text( - _currentBank == null - ? 'Choose your bank to start the payment' - : 'Enter your acccount number', - style: const TextStyle( - fontWeight: FontWeight.w500, - fontSize: 14.0), - ), - new SizedBox( - height: 20.0, - ), - new DropdownButtonHideUnderline( - child: new InputDecorator( + ? 'Choose your bank to start the payment' + : 'Enter your account number', + style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 14.0), + ), + const SizedBox( + height: 20.0, + ), + DropdownButtonHideUnderline( + child: InputDecorator( decoration: InputDecoration( - border: OutlineInputBorder(), + border: const OutlineInputBorder(), isDense: true, enabledBorder: const OutlineInputBorder( - borderSide: - const BorderSide(color: Colors.grey, width: 0.5)), + borderSide: BorderSide(color: Colors.grey, width: 0.5), + ), focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: context.colorScheme().secondary, width: 1.0)), + borderSide: BorderSide( + color: context.colorScheme().secondary, width: 1.0), + ), hintText: 'Tap here to choose', ), isEmpty: _currentBank == null, - child: new DropdownButton( + child: DropdownButton( value: _currentBank, isDense: true, onChanged: (Bank? newValue) { @@ -162,44 +164,46 @@ class _BankCheckoutState extends BaseCheckoutMethodState { }); }, items: banks.map((Bank value) { - return new DropdownMenuItem( + return DropdownMenuItem( value: value, - child: new Text(value.name!), + child: Text(value.name!), ); }).toList(), ), - )), - new ScaleTransition( - scale: _animation, - child: _currentBank == null - ? container - : new Column( - mainAxisSize: MainAxisSize.min, - children: [ - new SizedBox( - height: 15.0, - ), - new AccountField( - onSaved: (String? value) => _account = - new BankAccount(_currentBank, value)), - new SizedBox( - height: 20.0, - ), - new AccentButton( - onPressed: _validateInputs, - showProgress: _loading, - text: 'Verify Account') - ], - ), ), - ], - ), + ), + ScaleTransition( + scale: _animation, + child: _currentBank == null + ? container + : Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox( + height: 15.0, + ), + AccountField( + onSaved: (String? value) => + _account = BankAccount(_currentBank, value), + ), + const SizedBox( + height: 20.0, + ), + AccentButton( + onPressed: _validateInputs, + showProgress: _loading, + text: 'Verify Account', + ), + ], + ), + ), + ], ), ); } void _validateInputs() { - FocusScope.of(context).requestFocus(new FocusNode()); + FocusScope.of(context).requestFocus(FocusNode()); final FormState form = _formKey.currentState!; if (form.validate()) { form.save(); @@ -214,11 +218,11 @@ class _BankCheckoutState extends BaseCheckoutMethodState { void _chargeAccount() async { final response = await BankTransactionManager( - charge: widget.charge, - service: widget.service, - context: context, - publicKey: widget.publicKey) - .chargeBank(); + charge: widget.charge, + service: widget.service, + context: context, + publicKey: widget.publicKey, + ).chargeBank(); if (!mounted) return; @@ -228,14 +232,15 @@ class _BankCheckoutState extends BaseCheckoutMethodState { Widget retryButton() { banksMemo = null; - banksMemo = new AsyncMemoizer(); + banksMemo = AsyncMemoizer(); _futureBanks = widget.service.fetchSupportedBanks(); return Container( margin: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 30.0), - child: new AccentButton( - onPressed: () => setState(() {}), - showProgress: false, - text: 'Display banks'), + child: AccentButton( + onPressed: () => setState(() {}), + showProgress: false, + text: 'Display banks', + ), ); } diff --git a/lib/src/widgets/checkout/card_checkout.dart b/lib/src/widgets/checkout/card_checkout.dart index 3ffb383f..0418d015 100644 --- a/lib/src/widgets/checkout/card_checkout.dart +++ b/lib/src/widgets/checkout/card_checkout.dart @@ -21,8 +21,8 @@ class CardCheckout extends StatefulWidget { final CardServiceContract service; final String publicKey; - CardCheckout({ - Key? key, + const CardCheckout({ + super.key, required this.charge, required this.onResponse, required this.onProcessingChange, @@ -30,10 +30,11 @@ class CardCheckout extends StatefulWidget { required this.service, required this.publicKey, this.hideAmount = false, - }) : super(key: key); + }); @override - _CardCheckoutState createState() => _CardCheckoutState(charge, onResponse); + BaseCheckoutMethodState createState() => + _CardCheckoutState(charge, onResponse); } class _CardCheckoutState extends BaseCheckoutMethodState { @@ -47,21 +48,21 @@ class _CardCheckoutState extends BaseCheckoutMethodState { var amountText = _charge.amount.isNegative ? '' : Utils.formatAmount(_charge.amount); - return new Container( + return Container( alignment: Alignment.center, - child: new Column( + child: Column( children: [ - new Text( + const Text( Strings.cardInputInstruction, - key: Key("InstructionKey"), - style: const TextStyle(fontWeight: FontWeight.w500), + key: Key('InstructionKey'), + style: TextStyle(fontWeight: FontWeight.w500), ), - new SizedBox( + const SizedBox( height: 20.0, ), - new CardInput( - key: Key("CardInput"), - buttonText: widget.hideAmount ? "Continue" : 'Pay $amountText', + CardInput( + key: const Key('CardInput'), + buttonText: widget.hideAmount ? 'Continue' : 'Pay $amountText', card: _charge.card, onValidated: _onCardValidated, ), @@ -81,7 +82,7 @@ class _CardCheckoutState extends BaseCheckoutMethodState { _chargeCard(_charge); } else { // This should never happen. Validation has already been done in [PaystackPlugin .checkout] - throw new ChargeException(Strings.noAccessCodeReference); + throw ChargeException(Strings.noAccessCodeReference); } } diff --git a/lib/src/widgets/checkout/checkout_widget.dart b/lib/src/widgets/checkout/checkout_widget.dart index 6e467620..49ba2cad 100644 --- a/lib/src/widgets/checkout/checkout_widget.dart +++ b/lib/src/widgets/checkout/checkout_widget.dart @@ -28,7 +28,8 @@ class CheckoutWidget extends StatefulWidget { final CardServiceContract cardsService; final String publicKey; - CheckoutWidget({ + const CheckoutWidget({ + super.key, required this.method, required this.charge, required this.bankService, @@ -41,13 +42,13 @@ class CheckoutWidget extends StatefulWidget { }); @override - _CheckoutWidgetState createState() => _CheckoutWidgetState(charge); + BaseState createState() => _CheckoutWidgetState(); } class _CheckoutWidgetState extends BaseState with TickerProviderStateMixin { static const tabBorderRadius = BorderRadius.all(Radius.circular(4.0)); - final Charge _charge; + late final Charge _charge; int? _currentIndex = 0; var _showTabs = true; String? _paymentError; @@ -58,27 +59,24 @@ class _CheckoutWidgetState extends BaseState late AnimationController _animationController; CheckoutResponse? _response; - _CheckoutWidgetState(this._charge); - @override void initState() { super.initState(); + _charge = widget.charge; _init(); _initPaymentMethods(); _currentIndex = _getCurrentTab(); _showTabs = widget.method == CheckoutMethod.selectable ? true : false; - _tabController = new TabController( + _tabController = TabController( vsync: this, length: _methodWidgets.length, initialIndex: _currentIndex!); _tabController!.addListener(_indexChange); - _animationController = new AnimationController( + _animationController = AnimationController( duration: const Duration(milliseconds: 500), vsync: this, ); - if (_charge.card == null) { - _charge.card = PaymentCard.empty(); - } + _charge.card ??= PaymentCard.empty(); } @override @@ -94,7 +92,7 @@ class _CheckoutWidgetState extends BaseState crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - Row( + const Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -102,31 +100,31 @@ class _CheckoutWidgetState extends BaseState Padding( padding: EdgeInsetsDirectional.only(start: 3), child: Text( - "Secured by", - key: Key("SecuredBy"), + 'Secured by', + key: Key('SecuredBy'), style: TextStyle(fontSize: 10), ), ) ], ), - SizedBox(height: 5), + const SizedBox(height: 5), Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ if (widget.logo != null) Padding( - padding: EdgeInsetsDirectional.only(end: 3), + padding: const EdgeInsetsDirectional.only(end: 3), child: Image.asset( 'assets/images/paystack_icon.png', - key: Key("PaystackBottomIcon"), + key: const Key('PaystackBottomIcon'), package: 'flutter_paystack', height: 16, ), ), Image.asset( 'assets/images/paystack.png', - key: Key("PaystackLogo"), + key: const Key('PaystackLogo'), package: 'flutter_paystack', height: 15, ) @@ -134,31 +132,32 @@ class _CheckoutWidgetState extends BaseState ) ], ); - return new CustomAlertDialog( + return CustomAlertDialog( expanded: true, fullscreen: widget.fullscreen, - titlePadding: EdgeInsets.all(0.0), + titlePadding: const EdgeInsets.all(0.0), onCancelPress: onCancelPress, title: _buildTitle(), - content: new Container( - child: new SingleChildScrollView( - child: GestureDetector( - onTap: () => FocusScope.of(context).unfocus(), - behavior: HitTestBehavior.translucent, - child: new Container( - padding: const EdgeInsets.symmetric( - vertical: 10.0, horizontal: 10.0), - child: Column( - children: [ - _showProcessingError() - ? _buildErrorWidget() - : _paymentSuccessful - ? _buildSuccessfulWidget() - : _methodWidgets[_currentIndex!].child, - SizedBox(height: 20), - securedWidget - ], - )), + content: SingleChildScrollView( + child: GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + behavior: HitTestBehavior.translucent, + child: Container( + padding: const EdgeInsets.symmetric( + vertical: 10.0, + horizontal: 10.0, + ), + child: Column( + children: [ + _showProcessingError() + ? _buildErrorWidget() + : _paymentSuccessful + ? _buildSuccessfulWidget() + : _methodWidgets[_currentIndex!].child, + const SizedBox(height: 20), + securedWidget + ], + ), ), ), ), @@ -173,62 +172,69 @@ class _CheckoutWidgetState extends BaseState if (!widget.hideEmail && _charge.email != null) Text( _charge.email!, - key: Key("ChargeEmail"), + key: const Key('ChargeEmail'), maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( - color: context.textTheme().bodySmall?.color, fontSize: 12.0), + color: context.textTheme().bodySmall?.color, + fontSize: 12.0, + ), ), if (!widget.hideAmount && !_charge.amount.isNegative) Row( - key: Key("DisplayAmount"), + key: const Key('DisplayAmount'), mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Pay', style: TextStyle( - fontSize: 14.0, color: context.textTheme().headline1?.color), + fontSize: 14.0, + color: context.textTheme().displayLarge?.color, + ), ), - SizedBox( + const SizedBox( width: 5.0, ), Flexible( - child: Text(Utils.formatAmount(_charge.amount), - style: TextStyle( - fontSize: 15.0, - color: context.textTheme().headline6?.color, - fontWeight: FontWeight.bold))) + child: Text( + Utils.formatAmount(_charge.amount), + style: TextStyle( + fontSize: 15.0, + color: context.textTheme().titleLarge?.color, + fontWeight: FontWeight.bold), + ), + ), ], - ) + ), ], ); return Column( mainAxisSize: MainAxisSize.min, children: [ - new Container( + Container( padding: const EdgeInsets.all(10.0), - child: new Row( + child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ if (widget.logo == null) Image.asset( 'assets/images/paystack_icon.png', - key: Key("PaystackIcon"), + key: const Key('PaystackIcon'), package: 'flutter_paystack', width: 25, ) else SizedBox( - key: Key("Logo"), + key: const Key('Logo'), child: widget.logo, ), - new SizedBox( + const SizedBox( width: 50, ), - new Expanded(child: emailAndAmount), + Expanded(child: emailAndAmount), ], ), ), @@ -241,18 +247,18 @@ class _CheckoutWidgetState extends BaseState return AnimatedSize( duration: const Duration(milliseconds: 300), curve: Curves.fastOutSlowIn, - child: new Container( - color: context.colorScheme().background.withOpacity(0.5), + child: Container( + color: context.colorScheme().surface.withOpacity(0.5), height: _tabHeight, alignment: Alignment.center, - child: new TabBar( + child: TabBar( controller: _tabController, isScrollable: true, - unselectedLabelColor: context.colorScheme().onBackground, + unselectedLabelColor: context.colorScheme().onSurface, labelColor: accentColor, labelStyle: - new TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500), - indicator: new ShapeDecoration( + const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500), + indicator: ShapeDecoration( shape: RoundedRectangleBorder( borderRadius: tabBorderRadius, side: BorderSide( @@ -269,9 +275,9 @@ class _CheckoutWidgetState extends BaseState ), ), tabs: _methodWidgets.map((MethodItem m) { - return new Tab( + return Tab( text: m.text, - icon: new Icon( + icon: Icon( m.icon, size: 24.0, ), @@ -292,11 +298,11 @@ class _CheckoutWidgetState extends BaseState void _initPaymentMethods() { _methodWidgets = [ - new MethodItem( + MethodItem( text: 'Card', icon: Icons.credit_card, - child: new CardCheckout( - key: Key("CardCheckout"), + child: CardCheckout( + key: const Key('CardCheckout'), publicKey: widget.publicKey, service: widget.cardsService, charge: _charge, @@ -311,10 +317,10 @@ class _CheckoutWidgetState extends BaseState _charge.card!.expiryYear = card.expiryYear; }, )), - new MethodItem( + MethodItem( text: 'Bank', icon: Icons.account_balance, - child: new BankCheckout( + child: BankCheckout( publicKey: widget.publicKey, charge: _charge, service: widget.bankService, @@ -380,48 +386,48 @@ class _CheckoutWidgetState extends BaseState Widget _buildErrorWidget() { _initPaymentMethods(); - void _resetShowTabs() { + void resetShowTabs() { _response = null; // Reset the response _showTabs = widget.method == CheckoutMethod.selectable ? true : false; } - return new ErrorWidget( + return ErrorWidget( text: _paymentError, method: widget.method, isCardPayment: _charge.card!.isValid(), vSync: this, payWithBank: () { setState(() { - _resetShowTabs(); + resetShowTabs(); _onPaymentError(null); - _charge.card = new PaymentCard.empty(); + _charge.card = PaymentCard.empty(); _tabController!.index = 1; _paymentError = null; }); }, tryAnotherCard: () { setState(() { - _resetShowTabs(); + resetShowTabs(); _onPaymentError(null); - _charge.card = new PaymentCard.empty(); + _charge.card = PaymentCard.empty(); _tabController!.index = 0; }); }, startOverWithCard: () { - _resetShowTabs(); + resetShowTabs(); _onPaymentError(null); _tabController!.index = 0; }, ); } - Widget _buildSuccessfulWidget() => new SuccessfulWidget( + Widget _buildSuccessfulWidget() => SuccessfulWidget( amount: _charge.amount, onCountdownComplete: () { if (_response!.card != null) { _response!.card!.nullifyNumber(); } - Navigator.of(context).pop(_response); + Navigator.of(context).pop(_response); }, ); @@ -449,4 +455,4 @@ class _CheckoutWidgetState extends BaseState } } -typedef void OnResponse(CheckoutResponse response); +typedef OnResponse = void Function(CheckoutResponse response); diff --git a/lib/src/widgets/common/input_formatters.dart b/lib/src/widgets/common/input_formatters.dart index a40cb177..090a6ccd 100644 --- a/lib/src/widgets/common/input_formatters.dart +++ b/lib/src/widgets/common/input_formatters.dart @@ -12,7 +12,7 @@ class CardMonthInputFormatter extends TextInputFormatter { return newValue; } - var buffer = new StringBuffer(); + var buffer = StringBuffer(); for (int i = 0; i < text.length; i++) { buffer.write(text[i]); var nonZeroIndex = i + 1; @@ -28,7 +28,7 @@ class CardMonthInputFormatter extends TextInputFormatter { var string = buffer.toString(); return newValue.copyWith( text: string, - selection: new TextSelection.collapsed(offset: string.length)); + selection: TextSelection.collapsed(offset: string.length)); } } @@ -45,7 +45,7 @@ class CardNumberInputFormatter extends TextInputFormatter { var string = Utils.addSpaces(text); return newValue.copyWith( text: string, - selection: new TextSelection.collapsed(offset: string.length)); + selection: TextSelection.collapsed(offset: string.length)); } } diff --git a/lib/src/widgets/custom_dialog.dart b/lib/src/widgets/custom_dialog.dart index 4faa5333..168fd895 100644 --- a/lib/src/widgets/custom_dialog.dart +++ b/lib/src/widgets/custom_dialog.dart @@ -7,7 +7,7 @@ import 'package:flutter_paystack/src/widgets/common/extensions.dart'; /// to retain the dialog feel and look while adding the close IconButton class CustomAlertDialog extends StatelessWidget { const CustomAlertDialog({ - Key? key, + super.key, this.title, this.titlePadding, this.onCancelPress, @@ -15,7 +15,7 @@ class CustomAlertDialog extends StatelessWidget { this.expanded = false, this.fullscreen = false, required this.content, - }) : super(key: key); + }); final Widget? title; final EdgeInsetsGeometry? titlePadding; @@ -30,24 +30,26 @@ class CustomAlertDialog extends StatelessWidget { final List children = []; if (title != null && titlePadding != null) { - children.add(new Padding( + children.add(Padding( padding: titlePadding!, - child: new DefaultTextStyle( - style: context.textTheme().headline6!, - child: new Semantics(child: title, namesRoute: true), + child: DefaultTextStyle( + style: context.textTheme().titleLarge!, + child: Semantics(namesRoute: true, child: title), ), )); } - children.add(new Flexible( - child: new Padding( - padding: contentPadding, - child: new DefaultTextStyle( - style: context.textTheme().subtitle1!, - child: content, + children.add( + Flexible( + child: Padding( + padding: contentPadding, + child: DefaultTextStyle( + style: context.textTheme().titleMedium!, + child: content, + ), ), ), - )); + ); return buildContent(context, children); } @@ -55,35 +57,35 @@ class CustomAlertDialog extends StatelessWidget { Widget buildContent(context, List children) { Widget widget; if (fullscreen) { - widget = new Material( - child: new Container( + widget = Material( + child: Container( child: onCancelPress == null - ? new Padding( + ? Padding( padding: const EdgeInsets.symmetric( horizontal: 10.0, vertical: 20.0, ), - child: new Column( + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: children), ) - : new Column( + : Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - new Align( + Align( alignment: Alignment.topRight, - child: new IconButton( - icon: new Icon(Icons.close), + child: IconButton( + icon: const Icon(Icons.close), onPressed: onCancelPress, color: Colors.black54, padding: const EdgeInsets.all(15.0), iconSize: 30.0, ), ), - new Expanded( - child: new Padding( + Expanded( + child: Padding( padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: new Column( + child: Column( children: children, ), )) @@ -91,26 +93,26 @@ class CustomAlertDialog extends StatelessWidget { )), ); } else { - var body = new Material( + var body = Material( type: MaterialType.card, - borderRadius: new BorderRadius.circular(10.0), - child: new Column( + borderRadius: BorderRadius.circular(10.0), + child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: children, ), ); - var child = new IntrinsicWidth( + var child = IntrinsicWidth( child: onCancelPress == null ? body - : new Column( + : Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, children: [ - new Container( + Container( margin: const EdgeInsets.all(10.0), - child: new IconButton( + child: IconButton( highlightColor: Colors.white54, splashColor: Colors.white54, color: Colors.white, @@ -121,11 +123,11 @@ class CustomAlertDialog extends StatelessWidget { ), onPressed: onCancelPress), ), - new Flexible(child: body), + Flexible(child: body), ], ), ); - widget = new CustomDialog(child: child, expanded: expanded); + widget = CustomDialog(expanded: expanded, child: child); } return widget; } @@ -135,12 +137,12 @@ class CustomAlertDialog extends StatelessWidget { /// elevation and changing the Material type. class CustomDialog extends StatelessWidget { const CustomDialog({ - Key? key, + super.key, required this.child, required this.expanded, this.insetAnimationDuration = const Duration(milliseconds: 100), this.insetAnimationCurve = Curves.decelerate, - }) : super(key: key); + }); final Widget child; final Duration insetAnimationDuration; @@ -149,25 +151,25 @@ class CustomDialog extends StatelessWidget { @override Widget build(BuildContext context) { - return new AnimatedPadding( + return AnimatedPadding( padding: MediaQuery.of(context).viewInsets + const EdgeInsets.symmetric(horizontal: 20.0, vertical: 24.0), duration: insetAnimationDuration, curve: insetAnimationCurve, - child: new MediaQuery.removeViewInsets( + child: MediaQuery.removeViewInsets( removeLeft: true, removeTop: true, removeRight: true, removeBottom: true, context: context, - child: new Center( - child: new ConstrainedBox( - constraints: new BoxConstraints( + child: Center( + child: ConstrainedBox( + constraints: BoxConstraints( minWidth: expanded ? math.min( (MediaQuery.of(context).size.width - 40.0), 332.0) : 280.0), - child: new Material( + child: Material( elevation: 50.0, type: MaterialType.transparency, child: child, diff --git a/lib/src/widgets/error_widget.dart b/lib/src/widgets/error_widget.dart index ccf3a60e..c1e95b08 100644 --- a/lib/src/widgets/error_widget.dart +++ b/lib/src/widgets/error_widget.dart @@ -14,6 +14,7 @@ class ErrorWidget extends StatelessWidget { final bool isCardPayment; ErrorWidget({ + super.key, required this.text, required this.vSync, required this.method, @@ -21,66 +22,66 @@ class ErrorWidget extends StatelessWidget { this.payWithBank, this.tryAnotherCard, this.startOverWithCard, - }) : controller = new AnimationController( + }) : controller = AnimationController( duration: const Duration(milliseconds: 500), vsync: vSync, ) { controller.forward(); } - final emptyContainer = new Container(); + final emptyContainer = Container(); @override Widget build(BuildContext context) { // Remove 'Retry buttons for bank payment because when you retry a transaction it ret var buttonMargin = - isCardPayment ? new SizedBox(height: 5.0) : emptyContainer; - return new Container( - child: new CustomAnimatedWidget( - controller: controller, - child: new Column( - mainAxisSize: MainAxisSize.min, - children: [ - new Icon( - Icons.warning, - size: 50.0, - color: const Color(0xFFf9a831), + isCardPayment ? const SizedBox(height: 5.0) : emptyContainer; + return CustomAnimatedWidget( + controller: controller, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon( + Icons.warning, + size: 50.0, + color: Color(0xFFf9a831), + ), + const SizedBox(height: 10.0), + Text( + text!, + textAlign: TextAlign.center, + style: const TextStyle( + fontWeight: FontWeight.w500, + fontSize: 14.0, ), - new SizedBox(height: 10.0), - new Text( - text!, - textAlign: TextAlign.center, - style: const TextStyle( - fontWeight: FontWeight.w500, - fontSize: 14.0, - ), - ), - new SizedBox(height: 25.0), - isCardPayment - ? new WhiteButton( - onPressed: tryAnotherCard, text: 'Try another card') - : emptyContainer, - buttonMargin, - method == CheckoutMethod.selectable || method == CheckoutMethod.bank - ? new WhiteButton( - onPressed: payWithBank, - text: method == CheckoutMethod.bank || !isCardPayment - ? 'Retry' - : 'Try paying with your bank account', - ) - : emptyContainer, - buttonMargin, - isCardPayment - ? new WhiteButton( - onPressed: startOverWithCard, - text: 'Start over with same card', - iconData: Icons.refresh, - bold: false, - flat: true, - ) - : emptyContainer - ], - ), + ), + const SizedBox(height: 25.0), + isCardPayment + ? WhiteButton( + onPressed: tryAnotherCard, + text: 'Try another card', + ) + : emptyContainer, + buttonMargin, + method == CheckoutMethod.selectable || method == CheckoutMethod.bank + ? WhiteButton( + onPressed: payWithBank, + text: method == CheckoutMethod.bank || !isCardPayment + ? 'Retry' + : 'Try paying with your bank account', + ) + : emptyContainer, + buttonMargin, + isCardPayment + ? WhiteButton( + onPressed: startOverWithCard, + text: 'Start over with same card', + iconData: Icons.refresh, + bold: false, + flat: true, + ) + : emptyContainer + ], ), ); } diff --git a/lib/src/widgets/input/account_field.dart b/lib/src/widgets/input/account_field.dart index a20ef838..5e20eab8 100644 --- a/lib/src/widgets/input/account_field.dart +++ b/lib/src/widgets/input/account_field.dart @@ -4,14 +4,14 @@ import 'package:flutter_paystack/src/common/my_strings.dart'; import 'package:flutter_paystack/src/widgets/input/base_field.dart'; class AccountField extends BaseTextField { - AccountField({required FormFieldSetter onSaved}) + AccountField({super.key, required FormFieldSetter onSaved}) : super( labelText: 'Bank Account Number(10 digits)', validator: _validate, onSaved: onSaved, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, - new LengthLimitingTextInputFormatter(10), + LengthLimitingTextInputFormatter(10), ], ); diff --git a/lib/src/widgets/input/base_field.dart b/lib/src/widgets/input/base_field.dart index 2db7ad9a..4deab8d5 100644 --- a/lib/src/widgets/input/base_field.dart +++ b/lib/src/widgets/input/base_field.dart @@ -12,8 +12,8 @@ class BaseTextField extends StatelessWidget { final TextEditingController? controller; final String? initialValue; - BaseTextField({ - Key? key, + const BaseTextField({ + super.key, this.suffix, this.labelText, this.hintText, @@ -22,7 +22,7 @@ class BaseTextField extends StatelessWidget { this.validator, this.controller, this.initialValue, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -34,21 +34,21 @@ class BaseTextField extends StatelessWidget { maxLines: 1, initialValue: initialValue, keyboardType: TextInputType.number, - decoration: new InputDecoration( - border: OutlineInputBorder(), + decoration: InputDecoration( + border: const OutlineInputBorder(), labelText: labelText, labelStyle: const TextStyle(color: Colors.grey, fontSize: 14.0), suffixIcon: suffix == null ? null - : new Padding( + : Padding( padding: const EdgeInsetsDirectional.only(end: 12.0), child: suffix, ), errorStyle: const TextStyle(fontSize: 12.0), errorMaxLines: 3, isDense: true, - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide(color: Colors.grey, width: 0.5)), + enabledBorder: const OutlineInputBorder( + borderSide: BorderSide(color: Colors.grey, width: 0.5)), focusedBorder: OutlineInputBorder( borderSide: BorderSide(color: context.colorScheme().secondary, width: 1.0)), diff --git a/lib/src/widgets/input/card_input.dart b/lib/src/widgets/input/card_input.dart index aa69f936..b2be2f25 100644 --- a/lib/src/widgets/input/card_input.dart +++ b/lib/src/widgets/input/card_input.dart @@ -12,30 +12,29 @@ class CardInput extends StatefulWidget { final PaymentCard? card; final ValueChanged onValidated; - CardInput({ - Key? key, + const CardInput({ + super.key, required this.buttonText, required this.card, required this.onValidated, - }) : super(key: key); + }); @override - _CardInputState createState() => _CardInputState(card); + State createState() => _CardInputState(); } class _CardInputState extends State { - var _formKey = new GlobalKey(); - final PaymentCard? _card; + final _formKey = GlobalKey(); + late final PaymentCard? _card; var _autoValidate = AutovalidateMode.disabled; late TextEditingController numberController; bool _validated = false; - _CardInputState(this._card); - @override void initState() { super.initState(); - numberController = new TextEditingController(); + _card = widget.card; + numberController = TextEditingController(); numberController.addListener(_getCardTypeFrmNumber); if (_card?.number != null) { numberController.text = Utils.addSpaces(_card!.number!); @@ -51,29 +50,29 @@ class _CardInputState extends State { @override Widget build(BuildContext context) { - return new Form( + return Form( autovalidateMode: _autoValidate, key: _formKey, - child: new Column( + child: Column( children: [ - new NumberField( - key: Key("CardNumberKey"), + NumberField( + key: const Key('CardNumberKey'), controller: numberController, card: _card, onSaved: (String? value) => _card!.number = CardUtils.getCleanedNumber(value), suffix: getCardIcon(), ), - new SizedBox( + const SizedBox( height: 15.0, ), - new Row( + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ - new Flexible( - child: new DateField( - key: ValueKey("ExpiryKey"), + Flexible( + child: DateField( + key: const ValueKey('ExpiryKey'), card: _card, onSaved: (value) { List expiryDate = CardUtils.getExpiryDate(value); @@ -82,10 +81,10 @@ class _CardInputState extends State { }, ), ), - new SizedBox(width: 15.0), - new Flexible( - child: new CVCField( - key: Key("CVVKey"), + const SizedBox(width: 15.0), + Flexible( + child: CVCField( + key: const Key('CVVKey'), card: _card, onSaved: (value) { _card!.cvc = CardUtils.getCleanedNumber(value); @@ -93,14 +92,15 @@ class _CardInputState extends State { )), ], ), - new SizedBox( + const SizedBox( height: 20.0, ), - new AccentButton( - key: Key("PayButton"), - onPressed: _validateInputs, - text: widget.buttonText, - showProgress: _validated), + AccentButton( + key: const Key('PayButton'), + onPressed: _validateInputs, + text: widget.buttonText, + showProgress: _validated, + ), ], ), ); @@ -110,12 +110,12 @@ class _CardInputState extends State { String input = CardUtils.getCleanedNumber(numberController.text); String cardType = _card!.getTypeForIIN(input); setState(() { - this._card!.type = cardType; + _card!.type = cardType; }); } void _validateInputs() { - FocusScope.of(context).requestFocus(new FocusNode()); + FocusScope.of(context).requestFocus(FocusNode()); final FormState form = _formKey.currentState!; if (form.validate()) { form.save(); @@ -129,10 +129,10 @@ class _CardInputState extends State { } Widget getCardIcon() { - String img = ""; + String img = ''; var defaultIcon = Icon( Icons.credit_card, - key: Key("DefaultIssuerIcon"), + key: const Key('DefaultIssuerIcon'), size: 15.0, color: Colors.grey[600], ); @@ -165,7 +165,7 @@ class _CardInputState extends State { if (img.isNotEmpty) { widget = Image.asset( 'assets/images/$img', - key: Key("IssuerIcon"), + key: const Key('IssuerIcon'), height: 15, width: 30, package: 'flutter_paystack', diff --git a/lib/src/widgets/input/cvc_field.dart b/lib/src/widgets/input/cvc_field.dart index 32203e89..4cf6c8dd 100644 --- a/lib/src/widgets/input/cvc_field.dart +++ b/lib/src/widgets/input/cvc_field.dart @@ -6,20 +6,18 @@ import 'package:flutter_paystack/src/widgets/input/base_field.dart'; class CVCField extends BaseTextField { CVCField({ - Key? key, + super.key, required PaymentCard? card, - required FormFieldSetter onSaved, + required FormFieldSetter super.onSaved, }) : super( - key: key, labelText: 'CVV', hintText: '123', - onSaved: onSaved, validator: (String? value) => validateCVC(value, card), initialValue: card != null && card.cvc != null ? card.cvc.toString() : null, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, - new LengthLimitingTextInputFormatter(4), + LengthLimitingTextInputFormatter(4), ], ); diff --git a/lib/src/widgets/input/date_field.dart b/lib/src/widgets/input/date_field.dart index d9bc11ae..51cb97e6 100644 --- a/lib/src/widgets/input/date_field.dart +++ b/lib/src/widgets/input/date_field.dart @@ -8,20 +8,18 @@ import 'package:flutter_paystack/src/widgets/input/base_field.dart'; class DateField extends BaseTextField { DateField({ - Key? key, + super.key, required PaymentCard? card, - required FormFieldSetter onSaved, + required FormFieldSetter super.onSaved, }) : super( - key: key, labelText: 'CARD EXPIRY', hintText: 'MM/YY', validator: validateDate, initialValue: _getInitialExpiryMonth(card), - onSaved: onSaved, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, - new LengthLimitingTextInputFormatter(4), - new CardMonthInputFormatter() + LengthLimitingTextInputFormatter(4), + CardMonthInputFormatter() ], ); @@ -48,7 +46,7 @@ class DateField extends BaseTextField { int month; // The value contains a forward slash if the month and year has been // entered. - if (value.contains(new RegExp(r'(/)'))) { + if (value.contains(RegExp(r'(/)'))) { final date = CardUtils.getExpiryDate(value); month = date[0]; year = date[1]; diff --git a/lib/src/widgets/input/number_field.dart b/lib/src/widgets/input/number_field.dart index fdf10a39..874a6304 100644 --- a/lib/src/widgets/input/number_field.dart +++ b/lib/src/widgets/input/number_field.dart @@ -7,24 +7,20 @@ import 'package:flutter_paystack/src/widgets/common/input_formatters.dart'; import 'package:flutter_paystack/src/widgets/input/base_field.dart'; class NumberField extends BaseTextField { - NumberField( - {Key? key, - required PaymentCard? card, - required TextEditingController? controller, - required FormFieldSetter onSaved, - required Widget suffix}) - : super( - key: key, + NumberField({ + super.key, + required PaymentCard? card, + required super.controller, + required FormFieldSetter super.onSaved, + required Widget super.suffix, + }) : super( labelText: 'CARD NUMBER', hintText: '0000 0000 0000 0000', - controller: controller, - onSaved: onSaved, - suffix: suffix, validator: (String? value) => validateCardNum(value, card), inputFormatters: [ FilteringTextInputFormatter.digitsOnly, - new LengthLimitingTextInputFormatter(19), - new CardNumberInputFormatter() + LengthLimitingTextInputFormatter(19), + CardNumberInputFormatter() ], ); diff --git a/lib/src/widgets/input/otp_field.dart b/lib/src/widgets/input/otp_field.dart index 695ba36f..b5df55cd 100644 --- a/lib/src/widgets/input/otp_field.dart +++ b/lib/src/widgets/input/otp_field.dart @@ -1,30 +1,34 @@ import 'package:flutter/material.dart'; class OtpField extends TextFormField { - OtpField({FormFieldSetter? onSaved, required Color borderColor}) - : super( + OtpField({ + super.key, + super.onSaved, + required Color borderColor, + }) : super( keyboardType: TextInputType.text, textCapitalization: TextCapitalization.none, textAlign: TextAlign.center, - style: TextStyle( + style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 25.0, ), autofocus: true, maxLines: 1, - onSaved: onSaved, validator: (String? value) => value!.isEmpty ? 'Enter OTP' : null, obscureText: false, - decoration: new InputDecoration( - border: OutlineInputBorder(), + decoration: InputDecoration( + border: const OutlineInputBorder(), isDense: true, hintText: 'ENTER', hintStyle: const TextStyle(color: Colors.grey, fontSize: 14.0), contentPadding: const EdgeInsets.all(10.0), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide(color: Colors.grey, width: 0.5)), + enabledBorder: const OutlineInputBorder( + borderSide: BorderSide(color: Colors.grey, width: 0.5), + ), focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: borderColor, width: 1.0)), + borderSide: BorderSide(color: borderColor, width: 1.0), + ), ), ); } diff --git a/lib/src/widgets/input/pin_field.dart b/lib/src/widgets/input/pin_field.dart index e6c657c3..c4e56bb5 100644 --- a/lib/src/widgets/input/pin_field.dart +++ b/lib/src/widgets/input/pin_field.dart @@ -6,7 +6,7 @@ class PinField extends StatefulWidget { final ValueChanged? onSaved; final int pinLength; - PinField({this.onSaved, this.pinLength = 4}); + const PinField({super.key, this.onSaved, this.pinLength = 4}); @override State createState() => _PinFieldState(); @@ -16,11 +16,11 @@ class _PinFieldState extends State { @override Widget build(BuildContext context) { return Container( - margin: EdgeInsets.symmetric(horizontal: 10), - child: new TextField( + margin: const EdgeInsets.symmetric(horizontal: 10), + child: TextField( keyboardType: TextInputType.number, textAlign: TextAlign.center, - style: TextStyle( + style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 25.0, letterSpacing: 15.0, @@ -28,11 +28,11 @@ class _PinFieldState extends State { autofocus: true, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, - new LengthLimitingTextInputFormatter(widget.pinLength), + LengthLimitingTextInputFormatter(widget.pinLength), ], obscureText: true, - decoration: new InputDecoration( - border: OutlineInputBorder(), + decoration: InputDecoration( + border: const OutlineInputBorder(), isDense: true, hintText: 'ENTER PIN', hintStyle: const TextStyle( @@ -42,10 +42,14 @@ class _PinFieldState extends State { ), contentPadding: const EdgeInsets.all(10.0), enabledBorder: const OutlineInputBorder( - borderSide: const BorderSide(color: Colors.grey, width: 0.5)), + borderSide: BorderSide(color: Colors.grey, width: 0.5), + ), focusedBorder: OutlineInputBorder( - borderSide: - BorderSide(color: context.colorScheme().secondary, width: 1.0)), + borderSide: BorderSide( + color: context.colorScheme().secondary, + width: 1.0, + ), + ), ), onChanged: (String value) { if (value.length == widget.pinLength) { diff --git a/lib/src/widgets/otp_widget.dart b/lib/src/widgets/otp_widget.dart index f0f74a70..55c8a363 100644 --- a/lib/src/widgets/otp_widget.dart +++ b/lib/src/widgets/otp_widget.dart @@ -1,66 +1,68 @@ import 'package:flutter/material.dart'; import 'package:flutter_paystack/src/widgets/base_widget.dart'; +import 'package:flutter_paystack/src/widgets/buttons.dart'; import 'package:flutter_paystack/src/widgets/common/extensions.dart'; import 'package:flutter_paystack/src/widgets/custom_dialog.dart'; import 'package:flutter_paystack/src/widgets/input/otp_field.dart'; -import 'buttons.dart'; - class OtpWidget extends StatefulWidget { final String? message; - OtpWidget({required this.message}); + const OtpWidget({super.key, required this.message}); @override - _OtpWidgetState createState() => _OtpWidgetState(); + BaseState createState() => _OtpWidgetState(); } class _OtpWidgetState extends BaseState { - var _formKey = new GlobalKey(); + final _formKey = GlobalKey(); var _autoValidate = AutovalidateMode.disabled; String? _otp; var heightBox = const SizedBox(height: 20.0); @override Widget buildChild(BuildContext context) { - return new CustomAlertDialog( - content: new SingleChildScrollView( - child: new Container( + return CustomAlertDialog( + content: SingleChildScrollView( + child: Container( padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0), - child: new Form( + child: Form( key: _formKey, autovalidateMode: _autoValidate, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ - new Image.asset('assets/images/otp.png', - width: 30.0, package: 'flutter_paystack'), + Image.asset( + 'assets/images/otp.png', + width: 30.0, + package: 'flutter_paystack', + ), heightBox, - new Text( + Text( widget.message!, textAlign: TextAlign.center, - style: TextStyle( + style: TextStyle( fontWeight: FontWeight.w500, - color: context.textTheme().headline6?.color, + color: context.textTheme().titleLarge?.color, fontSize: 15.0, ), ), heightBox, Padding( - padding: EdgeInsets.symmetric(horizontal: 10), - child: new OtpField( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: OtpField( onSaved: (String? value) => _otp = value, borderColor: context.colorScheme().secondary, ), ), heightBox, - new AccentButton( + AccentButton( onPressed: _validateInputs, text: 'Authorize', ), heightBox, - new WhiteButton( + WhiteButton( onPressed: onCancelPress, text: 'Cancel', flat: true, @@ -75,7 +77,7 @@ class _OtpWidgetState extends BaseState { } void _validateInputs() { - FocusScope.of(context).requestFocus(new FocusNode()); + FocusScope.of(context).requestFocus(FocusNode()); final FormState form = _formKey.currentState!; if (form.validate()) { form.save(); diff --git a/lib/src/widgets/pin_widget.dart b/lib/src/widgets/pin_widget.dart index 124dabd8..ef76dfac 100644 --- a/lib/src/widgets/pin_widget.dart +++ b/lib/src/widgets/pin_widget.dart @@ -1,14 +1,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_paystack/src/widgets/base_widget.dart'; +import 'package:flutter_paystack/src/widgets/buttons.dart'; import 'package:flutter_paystack/src/widgets/common/extensions.dart'; import 'package:flutter_paystack/src/widgets/custom_dialog.dart'; import 'package:flutter_paystack/src/widgets/input/pin_field.dart'; -import 'buttons.dart'; - class PinWidget extends StatefulWidget { + const PinWidget({super.key}); + @override - _PinWidgetState createState() => _PinWidgetState(); + BaseState createState() => _PinWidgetState(); } class _PinWidgetState extends BaseState { @@ -22,9 +23,9 @@ class _PinWidgetState extends BaseState { @override Widget buildChild(BuildContext context) { - return new CustomAlertDialog( - content: new SingleChildScrollView( - child: new Container( + return CustomAlertDialog( + content: SingleChildScrollView( + child: Container( padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0), child: Column( mainAxisSize: MainAxisSize.min, @@ -38,19 +39,19 @@ class _PinWidgetState extends BaseState { textAlign: TextAlign.center, style: TextStyle( fontWeight: FontWeight.w500, - color: context.textTheme().headline6?.color, + color: context.textTheme().titleLarge?.color, fontSize: 15.0, ), ), heightBox, - new PinField( - onSaved: (String pin) => Navigator.of(context).pop(pin)), + PinField( + onSaved: (String pin) { + Navigator.of(context).pop(pin); + }, + ), heightBox, - new WhiteButton( + CancelButton( onPressed: onCancelPress, - text: 'Cancel', - flat: true, - bold: true, ), ], ), @@ -60,25 +61,27 @@ class _PinWidgetState extends BaseState { } Widget buildStar() { - Icon star(Color color) => new Icon( + Icon star(Color color) => Icon( Icons.star, color: color, size: 12.0, ); - return new Container( + return Container( padding: const EdgeInsets.fromLTRB(6.0, 15.0, 6.0, 6.0), decoration: BoxDecoration( - color: Theme.of(context).primaryColorDark, - borderRadius: const BorderRadius.all(Radius.circular(5.0))), - child: new Row( + color: Theme.of(context).primaryColorDark, + borderRadius: const BorderRadius.all(Radius.circular(5.0)), + ), + child: Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: List.generate( - _startCount, - (i) => star(i == (_startCount - 1) - ? context.colorScheme().secondary - : Theme.of(context).primaryColorLight)), + _startCount, + (i) => star(i == (_startCount - 1) + ? context.colorScheme().secondary + : Theme.of(context).primaryColorLight), + ), ), ); } diff --git a/lib/src/widgets/sucessful_widget.dart b/lib/src/widgets/sucessful_widget.dart index dc669431..31e60dc1 100644 --- a/lib/src/widgets/sucessful_widget.dart +++ b/lib/src/widgets/sucessful_widget.dart @@ -7,12 +7,14 @@ class SuccessfulWidget extends StatefulWidget { final int amount; final VoidCallback onCountdownComplete; - SuccessfulWidget({required this.amount, required this.onCountdownComplete}); + const SuccessfulWidget({ + super.key, + required this.amount, + required this.onCountdownComplete, + }); @override - _SuccessfulWidgetState createState() { - return new _SuccessfulWidgetState(); - } + State createState() => _SuccessfulWidgetState(); } class _SuccessfulWidgetState extends State @@ -29,31 +31,30 @@ class _SuccessfulWidgetState extends State @override void initState() { super.initState(); - _mainController = new AnimationController( + _mainController = AnimationController( duration: const Duration(milliseconds: 500), vsync: this, ); _mainController.forward(); - _countdownController = new AnimationController( + _countdownController = AnimationController( vsync: this, - duration: new Duration(seconds: kStartValue), + duration: const Duration(seconds: kStartValue), ); _countdownController.addListener(() => setState(() {})); _countdownAnim = - new StepTween(begin: kStartValue, end: 0).animate(_countdownController); + StepTween(begin: kStartValue, end: 0).animate(_countdownController); - _opacityController = new AnimationController( + _opacityController = AnimationController( vsync: this, duration: const Duration(milliseconds: 500)); - _opacity = - new CurvedAnimation(parent: _opacityController, curve: Curves.linear) - ..addStatusListener((status) { - if (status == AnimationStatus.completed) { - _opacityController.reverse(); - } else if (status == AnimationStatus.dismissed) { - _opacityController.forward(); - } - }); + _opacity = CurvedAnimation(parent: _opacityController, curve: Curves.linear) + ..addStatusListener((status) { + if (status == AnimationStatus.completed) { + _opacityController.reverse(); + } else if (status == AnimationStatus.dismissed) { + _opacityController.forward(); + } + }); WidgetsBinding.instance.addPostFrameCallback((_) => _startCountdown()); } @@ -69,55 +70,53 @@ class _SuccessfulWidgetState extends State @override Widget build(BuildContext context) { final sceondaryColor = context.colorScheme().secondary; - return new Container( - child: new CustomAnimatedWidget( - controller: _mainController, - child: new Column( - mainAxisSize: MainAxisSize.min, - children: [ - sizedBox, - new Image.asset( - 'assets/images/successful.png', - color: sceondaryColor, - width: 50.0, - package: 'flutter_paystack', + return CustomAnimatedWidget( + controller: _mainController, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + sizedBox, + Image.asset( + 'assets/images/successful.png', + color: sceondaryColor, + width: 50.0, + package: 'flutter_paystack', + ), + sizedBox, + Text( + 'Payment Successful', + style: TextStyle( + color: context.textTheme().titleLarge?.color, + fontWeight: FontWeight.w500, + fontSize: 16.0, ), - sizedBox, - Text( - 'Payment Successful', + ), + const SizedBox( + height: 5.0, + ), + widget.amount.isNegative + ? Container() + : Text('You paid ${Utils.formatAmount(widget.amount)}', + style: TextStyle( + color: context.textTheme().titleLarge?.color, + fontWeight: FontWeight.normal, + fontSize: 14.0, + )), + sizedBox, + FadeTransition( + opacity: _opacity, + child: Text( + _countdownAnim.value.toString(), style: TextStyle( - color: context.textTheme().headline6?.color, - fontWeight: FontWeight.w500, - fontSize: 16.0, - ), - ), - new SizedBox( - height: 5.0, - ), - widget.amount.isNegative - ? new Container() - : new Text('You paid ${Utils.formatAmount(widget.amount)}', - style: TextStyle( - color: context.textTheme().headline6?.color, - fontWeight: FontWeight.normal, - fontSize: 14.0, - )), - sizedBox, - new FadeTransition( - opacity: _opacity, - child: new Text( - _countdownAnim.value.toString(), - style: TextStyle( - color: sceondaryColor, - fontWeight: FontWeight.bold, - fontSize: 25.0), - ), + color: sceondaryColor, + fontWeight: FontWeight.bold, + fontSize: 25.0), ), - new SizedBox( - height: 30.0, - ) - ], - ), + ), + const SizedBox( + height: 30.0, + ) + ], ), ); } diff --git a/pubspec.yaml b/pubspec.yaml index f76392a8..d7f4d22d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,37 +1,35 @@ name: flutter_paystack description: A Flutter plugin for making payments via Paystack Payment Gateway. Completely supports Android and iOS. -version: 1.0.7 -homepage: https://github.com/wilburt/flutter_paystack +version: 1.0.9 +homepage: https://github.com/codeAvid/flutter_paystack dependencies: flutter: sdk: flutter - http: ^0.13.5 - intl: ^0.17.0 - meta: ^1.8.0 - async: ^2.9.0 + http: ^1.2.0 + intl: ^0.19.0 + meta: ^1.9.1 + async: ^2.11.0 dev_dependencies: + flutter_lints: ^5.0.0 flutter_test: sdk: flutter - matcher: ^0.12.12 - mockito: ^5.3.1 - + matcher: ^0.12.15 + mockito: ^5.4.2 flutter: plugin: platforms: android: package: co.paystack.flutterpaystack - pluginClass: FlutterPaystackPlugin + pluginClass: FlutterPaystackPlugin ios: - pluginClass: FlutterPaystackPlugin + pluginClass: FlutterPaystackPlugin assets: - - assets/images/ - - + - assets/images/ environment: - sdk: '>=2.12.0 <3.0.0' - flutter: ">=2.0.0" \ No newline at end of file + sdk: ">=3.0.0 <4.0.0" + flutter: ">=3.3.0" diff --git a/test/src/common/card_utils_test.dart b/test/src/common/card_utils_test.dart index 7635ac61..9d539f7b 100644 --- a/test/src/common/card_utils_test.dart +++ b/test/src/common/card_utils_test.dart @@ -5,29 +5,29 @@ import 'package:flutter_test/flutter_test.dart'; import 'case.dart'; void main() { - group("$CardUtils", () { - group("#isWholeNumberPositive", () { + group('$CardUtils', () { + group('#isWholeNumberPositive', () { final cases = [ - Case(inp: "12", out: true), - Case(inp: "+9876567", out: false), - Case(inp: "hgfdfghjk", out: false), - Case(inp: "KDHJIWUHE", out: false), - Case(inp: "-1-2-84ufpo", out: false), - Case(inp: "一些角色", out: false), - Case(inp: "九十", out: false), - Case(inp: "девяносто", out: false), - Case(inp: "09765678987656789876545678987656789876545678", out: true), + Case(inp: '12', out: true), + Case(inp: '+9876567', out: false), + Case(inp: 'hgfdfghjk', out: false), + Case(inp: 'KDHJIWUHE', out: false), + Case(inp: '-1-2-84ufpo', out: false), + Case(inp: '一些角色', out: false), + Case(inp: '九十', out: false), + Case(inp: 'девяносто', out: false), + Case(inp: '09765678987656789876545678987656789876545678', out: true), Case(inp: null, out: false), ]; - cases.forEach((c) { - test("${c.inp} returns ${c.out}", () { + for (var c in cases) { + test('${c.inp} returns ${c.out}', () { final value = CardUtils.isWholeNumberPositive(c.inp); expect(c.out, value); }); - }); + } }); - group("#convertYearTo4Digits", () { + group('#convertYearTo4Digits', () { final cases = [ Case(inp: 10, out: 2010), Case(inp: 100, out: 100), @@ -44,15 +44,15 @@ void main() { Case(inp: -88, out: -88), Case(inp: null, out: 0), ]; - cases.forEach((c) { - test("${c.inp} returns ${c.out}", () { + for (var c in cases) { + test('${c.inp} returns ${c.out}', () { final value = CardUtils.convertYearTo4Digits(c.inp); expect(c.out, value); }); - }); + } }); - group("#hasYearPassed", () { + group('#hasYearPassed', () { final cases = [ Case(inp: 10, out: true), Case(inp: 100, out: true), @@ -69,15 +69,15 @@ void main() { Case(inp: -88, out: true), Case(inp: null, out: true), ]; - cases.forEach((c) { - test("${c.inp} returns ${c.out}", () { + for (var c in cases) { + test('${c.inp} returns ${c.out}', () { final value = CardUtils.hasYearPassed(c.inp); expect(c.out, value); }); - }); + } }); - group("#hasMonthPassed", () { + group('#hasMonthPassed', () { final cases = [ Case(inp: [2027, 10], out: false), Case(inp: [10, 0], out: true), @@ -91,15 +91,15 @@ void main() { Case(inp: [24, null], out: true), Case(inp: [null, null], out: true), ]; - cases.forEach((c) { - test("${c.inp} returns ${c.out}", () { + for (var c in cases) { + test('${c.inp} returns ${c.out}', () { final value = CardUtils.hasMonthPassed(c.inp[0], c.inp[1]); expect(c.out, value); }); - }); + } }); - group("#isValidMonth", () { + group('#isValidMonth', () { final cases = [ Case(inp: 10, out: true), Case(inp: 0, out: false), @@ -110,15 +110,15 @@ void main() { Case(inp: 012, out: true), Case(inp: null, out: false), ]; - cases.forEach((c) { - test("${c.inp} returns ${c.out}", () { + for (var c in cases) { + test('${c.inp} returns ${c.out}', () { final value = CardUtils.isValidMonth(c.inp); expect(c.out, value); }); - }); + } }); - group("#isNotExpired", () { + group('#isNotExpired', () { final cases = [ Case(inp: [2027, 10], out: true), Case(inp: [10, 0], out: false), @@ -132,80 +132,80 @@ void main() { Case(inp: [null, null], out: false), Case(inp: [45, 67], out: false), ]; - cases.forEach((c) { - test("${c.inp} returns ${c.out}", () { + for (var c in cases) { + test('${c.inp} returns ${c.out}', () { final value = CardUtils.isNotExpired(c.inp[0], c.inp[1]); expect(c.out, value); }); - }); + } }); - group("#getCleanedNumber", () { + group('#getCleanedNumber', () { final cases = [ - Case(inp: "poiuytdfghjkkjhb", out: ""), - Case(inp: "098765tgb098eyr", out: "098765098"), - Case(inp: "6d8ge8gf7tfhd=-82qgjs9fh7w6ehf8", out: "6887829768"), - Case(inp: "0", out: "0"), - Case(inp: "девяносто", out: ""), - Case(inp: "一些角色", out: ""), - Case(inp: null, out: ""), + Case(inp: 'poiuytdfghjkkjhb', out: ''), + Case(inp: '098765tgb098eyr', out: '098765098'), + Case(inp: '6d8ge8gf7tfhd=-82qgjs9fh7w6ehf8', out: '6887829768'), + Case(inp: '0', out: '0'), + Case(inp: 'девяносто', out: ''), + Case(inp: '一些角色', out: ''), + Case(inp: null, out: ''), ]; - cases.forEach((c) { - test("${c.inp} returns ${c.out}", () { + for (var c in cases) { + test('${c.inp} returns ${c.out}', () { final value = CardUtils.getCleanedNumber(c.inp); expect(c.out, value); }); - }); + } }); - group("#concatenateCardFields", () { + group('#concatenateCardFields', () { final cases = [ Case( inp: PaymentCard( number: null, cvc: null, expiryMonth: null, expiryYear: null), - out: throwsA(TypeMatcher())), - Case(inp: null, out: throwsA(TypeMatcher())), + out: throwsA(const TypeMatcher())), + Case(inp: null, out: throwsA(const TypeMatcher())), Case( inp: PaymentCard( - number: "4111111111111111", - cvc: "123", + number: '4111111111111111', + cvc: '123', expiryMonth: 12, expiryYear: 12), - out: "4111111111111111*123*12*12"), + out: '4111111111111111*123*12*12'), Case( inp: PaymentCard( - number: "5500000000000004", + number: '5500000000000004', cvc: null, expiryMonth: 12, expiryYear: 12), - out: "5500000000000004*null*12*12"), + out: '5500000000000004*null*12*12'), Case( inp: PaymentCard( - number: "340000000000009", - cvc: "433", + number: '340000000000009', + cvc: '433', expiryMonth: 199, expiryYear: null), - out: "340000000000009*433*199*0"), + out: '340000000000009*433*199*0'), Case( inp: PaymentCard( - number: "340000000000009", - cvc: "433", + number: '340000000000009', + cvc: '433', expiryMonth: null, expiryYear: 30), - out: "340000000000009*433*0*30"), + out: '340000000000009*433*0*30'), Case( inp: PaymentCard( - number: "340000000000009", - cvc: "433", + number: '340000000000009', + cvc: '433', expiryMonth: null, expiryYear: null), - out: "340000000000009*433*0*0"), + out: '340000000000009*433*0*0'), ]; - cases.forEach((c) { - test("${c.inp} returns ${c.out}", () { - final value = CardUtils.concatenateCardFields; + for (var c in cases) { + test('${c.inp} returns ${c.out}', () { + const value = CardUtils.concatenateCardFields; if (c.out is String) { var v = value(c.inp); expect(v, c.out); @@ -213,32 +213,32 @@ void main() { expect(() => value(c.inp), c.out); } }); - }); + } }); - group("#getExpiryDate", () { + group('#getExpiryDate', () { final cases = [ - Case(inp: "poiuytdfghjkkjhb", out: [-1, -1]), - Case(inp: "0/12", out: [0, 12]), - Case(inp: "13/0", out: [13, 0]), - Case(inp: "девяносто/носто", out: [-1, -1]), - Case(inp: "一些角色/12", out: [-1, 12]), + Case(inp: 'poiuytdfghjkkjhb', out: [-1, -1]), + Case(inp: '0/12', out: [0, 12]), + Case(inp: '13/0', out: [13, 0]), + Case(inp: 'девяносто/носто', out: [-1, -1]), + Case(inp: '一些角色/12', out: [-1, 12]), Case(inp: null, out: [-1, -1]), - Case(inp: "12/23", out: [12, 23]), - Case(inp: "-12/-23", out: [-12, -23]), - Case(inp: "13/", out: [13, -1]), - Case(inp: "/", out: [-1, -1]), - Case(inp: "", out: [-1, -1]), - Case(inp: "12/23/14", out: [12, 14]), - Case(inp: "1223", out: [1223, -1]), + Case(inp: '12/23', out: [12, 23]), + Case(inp: '-12/-23', out: [-12, -23]), + Case(inp: '13/', out: [13, -1]), + Case(inp: '/', out: [-1, -1]), + Case(inp: '', out: [-1, -1]), + Case(inp: '12/23/14', out: [12, 14]), + Case(inp: '1223', out: [1223, -1]), ]; - cases.forEach((c) { - test("${c.inp} returns ${c.out}", () { + for (var c in cases) { + test('${c.inp} returns ${c.out}', () { final value = CardUtils.getExpiryDate(c.inp); expect(c.out, value); }); - }); + } }); }); } diff --git a/test/src/common/paystack_test.dart b/test/src/common/paystack_test.dart index 9a5bc629..74ed31b4 100644 --- a/test/src/common/paystack_test.dart +++ b/test/src/common/paystack_test.dart @@ -20,9 +20,9 @@ void main() { channel.setMockMethodCallHandler(null); }); - group("$PaystackPlugin", () { + group('$PaystackPlugin', () { test('is properly initialized with passed key', () async { - var publicKey = Platform.environment["PAYSTACK_TEST_PUBLIC_KEY"] ?? ""; + var publicKey = Platform.environment['PAYSTACK_TEST_PUBLIC_KEY'] ?? ''; final plugin = PaystackPlugin(); await plugin.initialize(publicKey: publicKey); expect(publicKey, plugin.publicKey); diff --git a/test/src/common/string_utils_test.dart b/test/src/common/string_utils_test.dart index 4c70bbfe..5dd3c994 100644 --- a/test/src/common/string_utils_test.dart +++ b/test/src/common/string_utils_test.dart @@ -4,63 +4,63 @@ import 'package:flutter_test/flutter_test.dart'; import 'case.dart'; void main() { - group("$StringUtils", () { - group("#isEmpty", () { + group('$StringUtils', () { + group('#isEmpty', () { final cases = [ - Case(inp: "876jje", out: false), - Case(inp: "@", out: false), - Case(inp: "12344323", out: false), - Case(inp: "null", out: true), + Case(inp: '876jje', out: false), + Case(inp: '@', out: false), + Case(inp: '12344323', out: false), + Case(inp: 'null', out: true), Case(inp: null, out: true), - Case(inp: "娱乐", out: false), - Case(inp: "развлекательная", out: false), + Case(inp: '娱乐', out: false), + Case(inp: 'развлекательная', out: false), ]; - cases.forEach((c) { - test("${c.inp} returns ${c.out}", () { + for (var c in cases) { + test('${c.inp} returns ${c.out}', () { final value = StringUtils.isEmpty(c.inp); expect(c.out, value); }); - }); + } }); - group("#isValidEmail", () { + group('#isValidEmail', () { final cases = [ - Case(inp: "email", out: false), - Case(inp: "@", out: false), - Case(inp: ".com", out: false), - Case(inp: "email@.com", out: false), - Case(inp: "email@host.com", out: true), - Case(inp: "ema-il@host-h.com", out: true), - Case(inp: "e_mail@host-j.gov", out: true), - Case(inp: "asdf@adsf.adsf", out: true), - Case(inp: "развлекательная@adsf.adsf", out: false), - Case(inp: "1234444", out: false), - Case(inp: "null", out: false), + Case(inp: 'email', out: false), + Case(inp: '@', out: false), + Case(inp: '.com', out: false), + Case(inp: 'email@.com', out: false), + Case(inp: 'email@host.com', out: true), + Case(inp: 'ema-il@host-h.com', out: true), + Case(inp: 'e_mail@host-j.gov', out: true), + Case(inp: 'asdf@adsf.adsf', out: true), + Case(inp: 'развлекательная@adsf.adsf', out: false), + Case(inp: '1234444', out: false), + Case(inp: 'null', out: false), Case(inp: null, out: false), ]; - cases.forEach((c) { - test("${c.inp} returns ${c.out}", () { + for (var c in cases) { + test('${c.inp} returns ${c.out}', () { final value = StringUtils.isValidEmail(c.inp); expect(c.out, value); }); - }); + } }); - group("#nullify", () { + group('#nullify', () { final cases = [ - Case(inp: "you", out: "you"), - Case(inp: "развлекательная", out: "развлекательная"), - Case(inp: "娱乐", out: "娱乐"), - Case(inp: "", out: null), + Case(inp: 'you', out: 'you'), + Case(inp: 'развлекательная', out: 'развлекательная'), + Case(inp: '娱乐', out: '娱乐'), Case(inp: '', out: null), - Case(inp: null, out: isNot(equals("q"))), + Case(inp: '', out: null), + Case(inp: null, out: isNot(equals('q'))), ]; - cases.forEach((c) { - test("${c.inp} returns ${c.out}", () { + for (var c in cases) { + test('${c.inp} returns ${c.out}', () { final value = StringUtils.nullify(c.inp); expect(value, c.out); }); - }); + } }); }); } diff --git a/test/src/common/utils_test.dart b/test/src/common/utils_test.dart index f0595e92..5333f101 100644 --- a/test/src/common/utils_test.dart +++ b/test/src/common/utils_test.dart @@ -19,20 +19,20 @@ void main() { channel.setMockMethodCallHandler(null); }); - group("$Utils", () { - group("#getKeyErrorMsg", () { - test("returns a string with keyType", () { - final keyType = "public"; + group('$Utils', () { + group('#getKeyErrorMsg', () { + test('returns a string with keyType', () { + const keyType = 'public'; expect(Utils.getKeyErrorMsg(keyType), contains(keyType)); }); }); - group("#formatAmount", () { - test("throws Error when currency formatter is not set", () { - expect(() => Utils.formatAmount(100), throwsA(TypeMatcher())); + group('#formatAmount', () { + test('throws Error when currency formatter is not set', () { + expect(() => Utils.formatAmount(100), throwsA(const TypeMatcher())); }); - test("returns normally when currency formatter has been set", () { + test('returns normally when currency formatter has been set', () { Utils.setCurrencyFormatter(Strings.ngn, Strings.nigerianLocale); expect(() => Utils.formatAmount(100), returnsNormally); }); diff --git a/test/src/models/card_test.dart b/test/src/models/card_test.dart index 4e8b8927..509468da 100644 --- a/test/src/models/card_test.dart +++ b/test/src/models/card_test.dart @@ -4,255 +4,255 @@ import 'package:flutter_test/flutter_test.dart'; import '../common/case.dart'; void main() { - group("$PaymentCard", () { - group("#type", () { + group('$PaymentCard', () { + group('#type', () { final cases = [ Case(inp: null, out: CardType.unknown), - Case(inp: "9765478765567656765", out: CardType.unknown), - Case(inp: "4111111111111111", out: CardType.visa), - Case(inp: "4222 22222 2222", out: CardType.visa), - Case(inp: "5500000000000004", out: CardType.masterCard), - Case(inp: "3400 0000 0000 009", out: CardType.americanExpress), - Case(inp: "30000000000004", out: CardType.dinersClub), - Case(inp: "6011000000000004", out: CardType.discover), - Case(inp: "3530111333300000", out: CardType.jcb), - Case(inp: "5060666666666666666", out: CardType.verve), + Case(inp: '9765478765567656765', out: CardType.unknown), + Case(inp: '4111111111111111', out: CardType.visa), + Case(inp: '4222 22222 2222', out: CardType.visa), + Case(inp: '5500000000000004', out: CardType.masterCard), + Case(inp: '3400 0000 0000 009', out: CardType.americanExpress), + Case(inp: '30000000000004', out: CardType.dinersClub), + Case(inp: '6011000000000004', out: CardType.discover), + Case(inp: '3530111333300000', out: CardType.jcb), + Case(inp: '5060666666666666666', out: CardType.verve), Case( desc: "doesn't return verve type for Ameerican Express number", - inp: "378282246310005", + inp: '378282246310005', out: isNot(equals(CardType.verve)), ), Case( - desc: "returns Unknown for empty number", - inp: "", + desc: 'returns Unknown for empty number', + inp: '', out: CardType.unknown, ), ]; - cases.forEach((c) { - test(c.desc ?? "returns ${c.out} for ${c.inp}", () { + for (var c in cases) { + test(c.desc ?? 'returns ${c.out} for ${c.inp}', () { final value = PaymentCard.empty()..number = c.inp; expect(value.type, c.out); }); - }); + } }); - group("#getTypeForIIN", () { + group('#getTypeForIIN', () { final cases = [ Case(inp: null, out: CardType.unknown), - Case(inp: "", out: CardType.unknown), - Case(inp: "000", out: CardType.unknown), - Case(inp: "4", out: CardType.visa), - Case(inp: "4", out: CardType.visa), - Case(inp: "55", out: CardType.masterCard), - Case(inp: "51", out: CardType.masterCard), - Case(inp: "3782", out: CardType.americanExpress), - Case(inp: "305", out: CardType.dinersClub), - Case(inp: "6011", out: CardType.discover), - Case(inp: "3561", out: CardType.jcb), - Case(inp: "5060", out: CardType.verve), - Case(inp: "506 0", out: CardType.verve), + Case(inp: '', out: CardType.unknown), + Case(inp: '000', out: CardType.unknown), + Case(inp: '4', out: CardType.visa), + Case(inp: '4', out: CardType.visa), + Case(inp: '55', out: CardType.masterCard), + Case(inp: '51', out: CardType.masterCard), + Case(inp: '3782', out: CardType.americanExpress), + Case(inp: '305', out: CardType.dinersClub), + Case(inp: '6011', out: CardType.discover), + Case(inp: '3561', out: CardType.jcb), + Case(inp: '5060', out: CardType.verve), + Case(inp: '506 0', out: CardType.verve), Case( desc: "doesn't return Ameerican Express type for VISA number", - inp: "4", + inp: '4', out: isNot(equals(CardType.americanExpress))), ]; - cases.forEach((c) { - test(c.desc ?? "returns ${c.out} for ${c.inp}", () { + for (var c in cases) { + test(c.desc ?? 'returns ${c.out} for ${c.inp}', () { final value = PaymentCard.empty()..number = c.inp; expect(value.getTypeForIIN(value.number), c.out); }); - }); + } }); - group("#number", () { + group('#number', () { final cases = [ - Case(inp: "4 22 22222 2222 2", out: "2222"), + Case(inp: '4 22 22222 2222 2', out: '2222'), Case( desc: "setting empty space as card number doesn't generate empty last4Digits", - inp: " ", - out: ""), - Case(inp: "12", out: "12"), - Case(inp: "1298", out: "1298"), - Case(inp: "976 5478 765567656 765", out: "6765"), - Case(inp: "5060666666666666666", out: "6666"), - Case(inp: "随机你,等等", out: ""), + inp: ' ', + out: ''), + Case(inp: '12', out: '12'), + Case(inp: '1298', out: '1298'), + Case(inp: '976 5478 765567656 765', out: '6765'), + Case(inp: '5060666666666666666', out: '6666'), + Case(inp: '随机你,等等', out: ''), Case( desc: "setting 340000000000009 as card number doesn't generate 7688 as last4Digits", - inp: "340000000000009", - out: isNot(equals("7688"))), + inp: '340000000000009', + out: isNot(equals('7688'))), ]; - cases.forEach((c) { + for (var c in cases) { test( c.desc ?? - "setting ${c.inp} as card number generates ${c.out} as last4Digits", + 'setting ${c.inp} as card number generates ${c.out} as last4Digits', () { final value = PaymentCard.empty()..number = c.inp; expect(value.last4Digits, c.out); }); - }); + } }); - group("#number", () { + group('#number', () { final cases = [ - Case(inp: "4222 22 22 2222 2", out: "4222222222222"), - Case(inp: "5060666666666666666", out: "5060666666666666666"), - Case(inp: "3YSHHjj40000B000000A009", out: "340000000000009"), - Case(inp: "随机你,等等", out: ""), - Case(inp: "随机你,等等124", out: "124"), + Case(inp: '4222 22 22 2222 2', out: '4222222222222'), + Case(inp: '5060666666666666666', out: '5060666666666666666'), + Case(inp: '3YSHHjj40000B000000A009', out: '340000000000009'), + Case(inp: '随机你,等等', out: ''), + Case(inp: '随机你,等等124', out: '124'), ]; - cases.forEach((c) { - test("${c.inp} is cleaned and assigned as ${c.out}", () { + for (var c in cases) { + test('${c.inp} is cleaned and assigned as ${c.out}', () { final value = PaymentCard.empty()..number = c.inp; expect(value.number, c.out); }); - }); + } }); - group("#cvv", () { + group('#cvv', () { final cases = [ - Case(inp: "123", out: "123"), - Case(inp: "așa", out: ""), - Case(inp: "8777等等", out: "8777"), - Case(inp: "9 11 1", out: "9111"), - Case(inp: "随机你,等等124", out: "124"), + Case(inp: '123', out: '123'), + Case(inp: 'așa', out: ''), + Case(inp: '8777等等', out: '8777'), + Case(inp: '9 11 1', out: '9111'), + Case(inp: '随机你,等等124', out: '124'), Case( - desc: "какая is not assigned as какая", - inp: "какая", - out: isNot(equals("какая"))), + desc: 'какая is not assigned as какая', + inp: 'какая', + out: isNot(equals('какая'))), ]; - cases.forEach((c) { - test(c.desc ?? "${c.inp} is cleaned and assigned as ${c.out}", () { + for (var c in cases) { + test(c.desc ?? '${c.inp} is cleaned and assigned as ${c.out}', () { final value = PaymentCard.empty()..cvc = c.inp; expect(value.cvc, c.out); }); - }); + } }); - group("#isValid", () { + group('#isValid', () { final cases = [ - Case(desc: "empty details", inp: PaymentCard.empty(), out: false), + Case(desc: 'empty details', inp: PaymentCard.empty(), out: false), Case( - desc: "null details", + desc: 'null details', inp: PaymentCard( number: null, cvc: null, expiryMonth: null, expiryYear: null), out: false), Case( - desc: "empty details", + desc: 'empty details', inp: - PaymentCard(number: "", cvc: "", expiryMonth: 0, expiryYear: 0), + PaymentCard(number: '', cvc: '', expiryMonth: 0, expiryYear: 0), out: false), Case( - desc: "invalid number and other valid details", + desc: 'invalid number and other valid details', inp: PaymentCard( - number: "9876567876567", - cvc: "123", + number: '9876567876567', + cvc: '123', expiryMonth: 12, expiryYear: 12), out: false), Case( - desc: "invalid cvv and other valid details", + desc: 'invalid cvv and other valid details', inp: PaymentCard( - number: "4111111111111111", - cvc: "12333", + number: '4111111111111111', + cvc: '12333', expiryMonth: 12, expiryYear: 12), out: false), Case( - desc: "invalid month and other valid details", + desc: 'invalid month and other valid details', inp: PaymentCard( - number: "4111111111111111", - cvc: "123", + number: '4111111111111111', + cvc: '123', expiryMonth: 90, expiryYear: 12), out: false), Case( - desc: "negative month and other valid details", + desc: 'negative month and other valid details', inp: PaymentCard( - number: "6011000000000004", - cvc: "123", + number: '6011000000000004', + cvc: '123', expiryMonth: -9, expiryYear: 12), out: false), Case( - desc: "negative year and other valid details", + desc: 'negative year and other valid details', inp: PaymentCard( - number: "4111111111111111", - cvc: "123", + number: '4111111111111111', + cvc: '123', expiryMonth: -9, expiryYear: -2020), out: false), Case( - desc: "four digit year and other valid details", + desc: 'four digit year and other valid details', inp: PaymentCard( - number: "4111111111111111", - cvc: "123", + number: '4111111111111111', + cvc: '123', expiryMonth: 09, expiryYear: 2027), out: true), Case( - desc: "expired card", + desc: 'expired card', inp: PaymentCard( - number: "4111111111111111", - cvc: "123", + number: '4111111111111111', + cvc: '123', expiryMonth: 09, expiryYear: 2002), out: false), Case( - desc: "valid card", + desc: 'valid card', inp: PaymentCard( - number: "6011000000000004", - cvc: "123", + number: '6011000000000004', + cvc: '123', expiryMonth: 09, expiryYear: 27), out: true), ]; - cases.forEach((c) { - test("returns ${c.out} for ${c.desc}", () { + for (var c in cases) { + test('returns ${c.out} for ${c.desc}', () { var valid = c.inp.isValid(); expect(valid, c.out); }); - }); + } }); - group("#validCVC", () { + group('#validCVC', () { final cases = [ Case( - desc: "returns false for empty cvv", - inp: PaymentCard.empty()..cvc = "", + desc: 'returns false for empty cvv', + inp: PaymentCard.empty()..cvc = '', out: false), Case( - desc: "returns false for empty cvv", + desc: 'returns false for empty cvv', inp: PaymentCard.empty()..cvc = null, out: false), Case( - desc: "returns false for two character length cvv", - inp: PaymentCard.empty()..cvc = "12", + desc: 'returns false for two character length cvv', + inp: PaymentCard.empty()..cvc = '12', out: false), Case( - desc: "returns false for alphanumeric characters", - inp: PaymentCard.empty()..cvc = "A9ri12499", + desc: 'returns false for alphanumeric characters', + inp: PaymentCard.empty()..cvc = 'A9ri12499', out: false), Case( - desc: "returns true for 3 character length cvv", - inp: PaymentCard.empty()..cvc = "123", + desc: 'returns true for 3 character length cvv', + inp: PaymentCard.empty()..cvc = '123', out: true), Case( desc: - "returns false for 3 character length cvv American Express cards", + 'returns false for 3 character length cvv American Express cards', inp: PaymentCard.empty() ..type = CardType.americanExpress - ..cvc = "123", + ..cvc = '123', out: false), ]; - cases.forEach((c) { - test("returns ${c.out} for ${c.inp}", () { + for (var c in cases) { + test('returns ${c.out} for ${c.inp}', () { var valid = c.inp.validCVC(null); expect(valid, c.out); }); - }); + } }); }); } diff --git a/test/src/widgets/checkout/card_checkout_test.dart b/test/src/widgets/checkout/card_checkout_test.dart index cd36b47c..87ea2419 100644 --- a/test/src/widgets/checkout/card_checkout_test.dart +++ b/test/src/widgets/checkout/card_checkout_test.dart @@ -14,15 +14,15 @@ import '../../common/widget_builder.dart'; class MockedCardService extends Mock implements CardServiceContract {} void main() { - group("$CardCheckout", () { - String publicKey = Platform.environment["PAYSTACK_TEST_PUBLIC_KEY"] ?? ""; + group('$CardCheckout', () { + String publicKey = Platform.environment['PAYSTACK_TEST_PUBLIC_KEY'] ?? ''; final charge = Charge() ..amount = 20000 - ..currency = "USD" + ..currency = 'USD' ..email = 'customer@email.com'; - Utils.setCurrencyFormatter(charge.currency, "en_US"); + Utils.setCurrencyFormatter(charge.currency, 'en_US'); final checkoutWidget = buildTestWidget( CardCheckout( @@ -35,36 +35,36 @@ void main() { ), ); - group("input instruction", () { - testWidgets("displayed", (tester) async { + group('input instruction', () { + testWidgets('displayed', (tester) async { await tester.pumpWidget(checkoutWidget); await tester.pumpAndSettle(); - expect(find.byKey(Key("InstructionKey")), findsOneWidget); + expect(find.byKey(const Key('InstructionKey')), findsOneWidget); }); }); - group("card input", () { - testWidgets("displayed", (tester) async { + group('card input', () { + testWidgets('displayed', (tester) async { await tester.pumpWidget(checkoutWidget); await tester.pumpAndSettle(); - expect(find.byKey(Key("CardInput")), findsOneWidget); + expect(find.byKey(const Key('CardInput')), findsOneWidget); }); - testWidgets("displays the correct amount when `hideAmount` is false", + testWidgets('displays the correct amount when `hideAmount` is false', (tester) async { await tester.pumpWidget(checkoutWidget); await tester.pumpAndSettle(); - CardInput input = tester.widget(find.byKey(Key("CardInput"))); - expect(input.buttonText, "Pay ${charge.currency} 200.00"); + CardInput input = tester.widget(find.byKey(const Key('CardInput'))); + expect(input.buttonText, 'Pay ${charge.currency} 200.00'); }); - testWidgets("displays the \"Continue\" when `hideAmount` is true", + testWidgets('displays the "Continue" when `hideAmount` is true', (tester) async { await tester.pumpWidget(buildTestWidget(CardCheckout( publicKey: publicKey, @@ -78,8 +78,8 @@ void main() { await tester.pumpAndSettle(); - CardInput input = tester.widget(find.byKey(Key("CardInput"))); - expect(input.buttonText, "Continue"); + CardInput input = tester.widget(find.byKey(const Key('CardInput'))); + expect(input.buttonText, 'Continue'); }); }); }); diff --git a/test/src/widgets/checkout/checkout_widget_test.dart b/test/src/widgets/checkout/checkout_widget_test.dart index b5c069ac..5cee0782 100644 --- a/test/src/widgets/checkout/checkout_widget_test.dart +++ b/test/src/widgets/checkout/checkout_widget_test.dart @@ -18,16 +18,16 @@ void main() { late String publicKey; setUp(() { - publicKey = Platform.environment["PAYSTACK_TEST_PUBLIC_KEY"] ?? ""; + publicKey = Platform.environment['PAYSTACK_TEST_PUBLIC_KEY'] ?? ''; }); - group("$CheckoutWidget", () { + group('$CheckoutWidget', () { var charge = Charge() ..amount = 20000 - ..currency = "USD" + ..currency = 'USD' ..email = 'customer@email.com'; - group("custom logo", () { - testWidgets("is supplied", (tester) async { + group('custom logo', () { + testWidgets('is supplied', (tester) async { final checkoutWidget = buildTestWidget( CheckoutWidget( publicKey: publicKey, @@ -44,15 +44,15 @@ void main() { await tester.pumpAndSettle(); - expect(find.byKey(Key("Logo")), findsOneWidget); - expect(find.byKey(Key("PaystackBottomIcon")), findsOneWidget); - expect(find.byKey(Key("PaystackLogo")), findsOneWidget); - expect(find.byKey(Key("PaystackIcon")), findsNothing); + expect(find.byKey(const Key('Logo')), findsOneWidget); + expect(find.byKey(const Key('PaystackBottomIcon')), findsOneWidget); + expect(find.byKey(const Key('PaystackLogo')), findsOneWidget); + expect(find.byKey(const Key('PaystackIcon')), findsNothing); expect(find.byIcon(Icons.lock), findsOneWidget); - expect(find.byKey(Key("SecuredBy")), findsOneWidget); + expect(find.byKey(const Key('SecuredBy')), findsOneWidget); }); - testWidgets("is not passed", (tester) async { + testWidgets('is not passed', (tester) async { final checkoutWidget = buildTestWidget( CheckoutWidget( publicKey: publicKey, @@ -69,17 +69,17 @@ void main() { await tester.pumpAndSettle(); - expect(find.byKey(Key("Logo")), findsNothing); - expect(find.byKey(Key("PaystackBottomIcon")), findsNothing); - expect(find.byKey(Key("PaystackIcon")), findsOneWidget); - expect(find.byKey(Key("PaystackLogo")), findsOneWidget); + expect(find.byKey(const Key('Logo')), findsNothing); + expect(find.byKey(const Key('PaystackBottomIcon')), findsNothing); + expect(find.byKey(const Key('PaystackIcon')), findsOneWidget); + expect(find.byKey(const Key('PaystackLogo')), findsOneWidget); expect(find.byIcon(Icons.lock), findsOneWidget); - expect(find.byKey(Key("SecuredBy")), findsOneWidget); + expect(find.byKey(const Key('SecuredBy')), findsOneWidget); }); }); - group("card", () { - testWidgets("card checkout is displayed for selectable method", + group('card', () { + testWidgets('card checkout is displayed for selectable method', (tester) async { final checkoutWidget = buildTestWidget( CheckoutWidget( @@ -95,10 +95,10 @@ void main() { await tester.pumpWidget(checkoutWidget); await tester.pumpAndSettle(); - expect(find.byKey(Key("CardCheckout")), findsOneWidget); + expect(find.byKey(const Key('CardCheckout')), findsOneWidget); }); - testWidgets("card checkout is displayed for card method", (tester) async { + testWidgets('card checkout is displayed for card method', (tester) async { final checkoutWidget = buildTestWidget( CheckoutWidget( publicKey: publicKey, @@ -113,10 +113,10 @@ void main() { await tester.pumpWidget(checkoutWidget); await tester.pumpAndSettle(); - expect(find.byKey(Key("CardCheckout")), findsOneWidget); + expect(find.byKey(const Key('CardCheckout')), findsOneWidget); }); - testWidgets("card checkout is not displayed for bank method", + testWidgets('card checkout is not displayed for bank method', (tester) async { var bankService = MockedBankService(); @@ -137,12 +137,12 @@ void main() { await tester.pumpWidget(checkoutWidget); await tester.pumpAndSettle(); - expect(find.byKey(Key("CardCheckout")), findsNothing); + expect(find.byKey(const Key('CardCheckout')), findsNothing); }); }); - group("email", () { - testWidgets("is displayed when `hideEmail` is false", (tester) async { + group('email', () { + testWidgets('is displayed when `hideEmail` is false', (tester) async { final checkoutWidget = buildTestWidget( CheckoutWidget( publicKey: publicKey, @@ -158,10 +158,10 @@ void main() { await tester.pumpWidget(checkoutWidget); await tester.pumpAndSettle(); - expect(find.byKey(Key("ChargeEmail")), findsOneWidget); + expect(find.byKey(const Key('ChargeEmail')), findsOneWidget); }); - testWidgets("is not displayed when `hideEmail` is true", (tester) async { + testWidgets('is not displayed when `hideEmail` is true', (tester) async { final checkoutWidget = buildTestWidget( CheckoutWidget( publicKey: publicKey, @@ -177,10 +177,10 @@ void main() { await tester.pumpWidget(checkoutWidget); await tester.pumpAndSettle(); - expect(find.byKey(Key("ChargeEmail")), findsNothing); + expect(find.byKey(const Key('ChargeEmail')), findsNothing); }); - testWidgets("is not displayed when no email is passed", (tester) async { + testWidgets('is not displayed when no email is passed', (tester) async { final checkoutWidget = buildTestWidget( CheckoutWidget( publicKey: publicKey, @@ -196,12 +196,12 @@ void main() { await tester.pumpWidget(checkoutWidget); await tester.pumpAndSettle(); - expect(find.byKey(Key("ChargeEmail")), findsNothing); + expect(find.byKey(const Key('ChargeEmail')), findsNothing); }); }); - group("amount", () { - testWidgets("is displayed when `hideAmount` is false", (tester) async { + group('amount', () { + testWidgets('is displayed when `hideAmount` is false', (tester) async { final checkoutWidget = buildTestWidget( CheckoutWidget( publicKey: publicKey, @@ -217,10 +217,10 @@ void main() { await tester.pumpWidget(checkoutWidget); await tester.pumpAndSettle(); - expect(find.byKey(Key("DisplayAmount")), findsOneWidget); + expect(find.byKey(const Key('DisplayAmount')), findsOneWidget); }); - testWidgets("is not displayed when `hideAmount` is true", (tester) async { + testWidgets('is not displayed when `hideAmount` is true', (tester) async { final checkoutWidget = buildTestWidget( CheckoutWidget( publicKey: publicKey, @@ -236,7 +236,7 @@ void main() { await tester.pumpWidget(checkoutWidget); await tester.pumpAndSettle(); - expect(find.byKey(Key("DisplayAmount")), findsNothing); + expect(find.byKey(const Key('DisplayAmount')), findsNothing); }); }); }); diff --git a/test/src/widgets/input/card_input_test.dart b/test/src/widgets/input/card_input_test.dart index 6a2f6d0f..8c16c404 100644 --- a/test/src/widgets/input/card_input_test.dart +++ b/test/src/widgets/input/card_input_test.dart @@ -7,8 +7,8 @@ import 'package:flutter_test/flutter_test.dart'; import '../../common/widget_builder.dart'; void main() { - group("$CardInput", () { - final buttonText = "Pay NGN 300"; + group('$CardInput', () { + const buttonText = 'Pay NGN 300'; final paymentCard = PaymentCard.empty(); final cardInputWidget = buildTestWidget(CardInput( @@ -17,239 +17,239 @@ void main() { onValidated: (v) {}, )); - group("pay button", () { - testWidgets("isDisplayed", (tester) async { + group('pay button', () { + testWidgets('isDisplayed', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - final cardNumberFinder = find.byKey(Key("PayButton")); + final cardNumberFinder = find.byKey(const Key('PayButton')); expect(cardNumberFinder, findsOneWidget); }); - testWidgets("callsValidateInputs", (tester) async { + testWidgets('callsValidateInputs', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - final cardNumberFinder = find.byKey(Key("PayButton")); + final cardNumberFinder = find.byKey(const Key('PayButton')); await tester.tap(cardNumberFinder); await tester.pump(); - expect(find.text("Invalid card number"), findsOneWidget); - expect(find.text("Invalid card expiry"), findsOneWidget); - expect(find.text("Invalid cvv"), findsOneWidget); + expect(find.text('Invalid card number'), findsOneWidget); + expect(find.text('Invalid card expiry'), findsOneWidget); + expect(find.text('Invalid cvv'), findsOneWidget); }); }); - group("card number", () { - testWidgets("isDisplayed", (tester) async { + group('card number', () { + testWidgets('isDisplayed', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - final cardNumberFinder = find.byKey(Key("CardNumberKey")); + final cardNumberFinder = find.byKey(const Key('CardNumberKey')); expect(cardNumberFinder, findsOneWidget); }); - testWidgets("defaultIssuerIconIsDisplayed", (tester) async { + testWidgets('defaultIssuerIconIsDisplayed', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - final cardNumberFinder = find.byKey(Key("DefaultIssuerIcon")); + final cardNumberFinder = find.byKey(const Key('DefaultIssuerIcon')); expect(cardNumberFinder, findsOneWidget); - expect(find.byKey(Key("IssuerIcon")), findsNothing); + expect(find.byKey(const Key('IssuerIcon')), findsNothing); }); - testWidgets("displayErrorWithNoInput", (tester) async { + testWidgets('displayErrorWithNoInput', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - await tester.tap(find.byKey(Key("PayButton"))); + await tester.tap(find.byKey(const Key('PayButton'))); await tester.pump(); - expect(find.text("Invalid card number"), findsOneWidget); + expect(find.text('Invalid card number'), findsOneWidget); }); - testWidgets("displayErrorWithInvalidInput", (tester) async { + testWidgets('displayErrorWithInvalidInput', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - final cardNumberFinder = find.byKey(Key("CardNumberKey")); - await tester.enterText(cardNumberFinder, "411111111111111111"); + final cardNumberFinder = find.byKey(const Key('CardNumberKey')); + await tester.enterText(cardNumberFinder, '411111111111111111'); - await tester.tap(find.byKey(Key("PayButton"))); + await tester.tap(find.byKey(const Key('PayButton'))); await tester.pump(); - expect(find.text("Invalid card number"), findsOneWidget); + expect(find.text('Invalid card number'), findsOneWidget); }); - testWidgets("displaysIssuerIconWhenIncompleteNumberIsInputted", + testWidgets('displaysIssuerIconWhenIncompleteNumberIsInputted', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - final cardNumberFinder = find.byKey(Key("CardNumberKey")); - await tester.enterText(cardNumberFinder, "533"); + final cardNumberFinder = find.byKey(const Key('CardNumberKey')); + await tester.enterText(cardNumberFinder, '533'); await tester.pump(); - expect(find.byKey(Key("IssuerIcon")), findsOneWidget); - expect(find.byKey(Key("DefaultIssuerIcon")), findsNothing); + expect(find.byKey(const Key('IssuerIcon')), findsOneWidget); + expect(find.byKey(const Key('DefaultIssuerIcon')), findsNothing); }); - testWidgets("displaysNoErrorWithValidInput", (tester) async { + testWidgets('displaysNoErrorWithValidInput', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - final cardNumberFinder = find.byKey(Key("CardNumberKey")); - await tester.enterText(cardNumberFinder, "3000 0000 0000 04"); + final cardNumberFinder = find.byKey(const Key('CardNumberKey')); + await tester.enterText(cardNumberFinder, '3000 0000 0000 04'); - await tester.tap(find.byKey(Key("PayButton"))); + await tester.tap(find.byKey(const Key('PayButton'))); await tester.pump(); - expect(find.text("Invalid card number"), findsNothing); + expect(find.text('Invalid card number'), findsNothing); }); }); - group("card expiry", () { - testWidgets("isDisplayed", (tester) async { + group('card expiry', () { + testWidgets('isDisplayed', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - final expiryFinder = find.byKey(Key("ExpiryKey")); + final expiryFinder = find.byKey(const Key('ExpiryKey')); expect(expiryFinder, findsOneWidget); }); - testWidgets("displaysErrorWithEmptyInput", (tester) async { + testWidgets('displaysErrorWithEmptyInput', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - await tester.tap(find.byKey(Key("PayButton"))); + await tester.tap(find.byKey(const Key('PayButton'))); await tester.pump(); - expect(find.text("Invalid card expiry"), findsOneWidget); + expect(find.text('Invalid card expiry'), findsOneWidget); }); - testWidgets("displaysErrorWithInvalidInput", (tester) async { + testWidgets('displaysErrorWithInvalidInput', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - final expiryFinder = find.byKey(Key("ExpiryKey")); - await tester.enterText(expiryFinder, "1365"); + final expiryFinder = find.byKey(const Key('ExpiryKey')); + await tester.enterText(expiryFinder, '1365'); - await tester.tap(find.byKey(Key("PayButton"))); + await tester.tap(find.byKey(const Key('PayButton'))); await tester.pump(); - expect(find.text("Invalid card expiry"), findsOneWidget); + expect(find.text('Invalid card expiry'), findsOneWidget); }); - testWidgets("displaysNoErrorWithValidInput", (tester) async { + testWidgets('displaysNoErrorWithValidInput', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - final expiryFinder = find.byKey(Key("ExpiryKey")); - await tester.enterText(expiryFinder, "12/18"); + final expiryFinder = find.byKey(const Key('ExpiryKey')); + await tester.enterText(expiryFinder, '12/18'); - await tester.tap(find.byKey(Key("PayButton"))); + await tester.tap(find.byKey(const Key('PayButton'))); await tester.pump(); - expect(find.text("Invalid card expiry"), findsOneWidget); + expect(find.text('Invalid card expiry'), findsOneWidget); }); - testWidgets("moreThanFourCharactersIsNotAccepted", (tester) async { + testWidgets('moreThanFourCharactersIsNotAccepted', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - final expiryFinder = find.byKey(Key("ExpiryKey")); - await tester.enterText(expiryFinder, "12218"); + final expiryFinder = find.byKey(const Key('ExpiryKey')); + await tester.enterText(expiryFinder, '12218'); - expect(find.text("12/21"), findsOneWidget); - expect(find.text("12/218"), findsNothing); - expect(find.text("12/18"), findsNothing); - expect(find.text("122/18"), findsNothing); + expect(find.text('12/21'), findsOneWidget); + expect(find.text('12/218'), findsNothing); + expect(find.text('12/18'), findsNothing); + expect(find.text('122/18'), findsNothing); }); }); - group("cvv", () { - testWidgets("isDisplayed", (tester) async { + group('cvv', () { + testWidgets('isDisplayed', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - final cvvFinder = find.byKey(Key("CVVKey")); + final cvvFinder = find.byKey(const Key('CVVKey')); expect(cvvFinder, findsOneWidget); }); - testWidgets("displaysErrorWithEmptyInput", (tester) async { + testWidgets('displaysErrorWithEmptyInput', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - await tester.tap(find.byKey(Key("PayButton"))); + await tester.tap(find.byKey(const Key('PayButton'))); await tester.pump(); - expect(find.text("Invalid cvv"), findsOneWidget); + expect(find.text('Invalid cvv'), findsOneWidget); }); - testWidgets("displaysErrorWithInvalidInput", (tester) async { + testWidgets('displaysErrorWithInvalidInput', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - final cvvFinder = find.byKey(Key("CVVKey")); - await tester.enterText(cvvFinder, "12"); + final cvvFinder = find.byKey(const Key('CVVKey')); + await tester.enterText(cvvFinder, '12'); - await tester.tap(find.byKey(Key("PayButton"))); + await tester.tap(find.byKey(const Key('PayButton'))); await tester.pump(); - expect(find.text("Invalid cvv"), findsOneWidget); + expect(find.text('Invalid cvv'), findsOneWidget); }); - testWidgets("displaysNoErrorWithValidInput", (tester) async { + testWidgets('displaysNoErrorWithValidInput', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - final cvvFinder = find.byKey(Key("CVVKey")); - await tester.enterText(cvvFinder, "123"); + final cvvFinder = find.byKey(const Key('CVVKey')); + await tester.enterText(cvvFinder, '123'); - await tester.tap(find.byKey(Key("PayButton"))); + await tester.tap(find.byKey(const Key('PayButton'))); await tester.pump(); - expect(find.text("Invalid cvv"), findsNothing); + expect(find.text('Invalid cvv'), findsNothing); }); - testWidgets("moreThanFourCharactersIsNotAccepted", (tester) async { + testWidgets('moreThanFourCharactersIsNotAccepted', (tester) async { await tester.pumpWidget(cardInputWidget); await tester.pumpAndSettle(); - final cvvFinder = find.byKey(Key("CVVKey")); - await tester.enterText(cvvFinder, "123456"); + final cvvFinder = find.byKey(const Key('CVVKey')); + await tester.enterText(cvvFinder, '123456'); - expect(find.text("1234"), findsOneWidget); - expect(find.text("12345"), findsNothing); - expect(find.text("123456"), findsNothing); + expect(find.text('1234'), findsOneWidget); + expect(find.text('12345'), findsNothing); + expect(find.text('123456'), findsNothing); }); }); });