diff --git a/packages/wyatt_authentication_bloc/example_router/.metadata b/packages/wyatt_authentication_bloc/example_router/.metadata index 2544bab1..8c2e2e3d 100644 --- a/packages/wyatt_authentication_bloc/example_router/.metadata +++ b/packages/wyatt_authentication_bloc/example_router/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled. version: - revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4 channel: stable project_type: app @@ -13,11 +13,11 @@ project_type: app migration: platforms: - platform: root - create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 - base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 - - platform: android - create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 - base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4 + base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4 + - platform: ios + create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4 + base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4 # User provided section diff --git a/packages/wyatt_authentication_bloc/example_router/ios/.gitignore b/packages/wyatt_authentication_bloc/example_router/ios/.gitignore new file mode 100644 index 00000000..7a7f9873 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Flutter/AppFrameworkInfo.plist b/packages/wyatt_authentication_bloc/example_router/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 00000000..9625e105 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + 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/packages/wyatt_authentication_bloc/example_router/ios/Flutter/Debug.xcconfig b/packages/wyatt_authentication_bloc/example_router/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..ec97fc6f --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Flutter/Release.xcconfig b/packages/wyatt_authentication_bloc/example_router/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..c4855bfe --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Podfile b/packages/wyatt_authentication_bloc/example_router/ios/Podfile new file mode 100644 index 00000000..88359b22 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '11.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Podfile.lock b/packages/wyatt_authentication_bloc/example_router/ios/Podfile.lock new file mode 100644 index 00000000..1a4d1789 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Podfile.lock @@ -0,0 +1,142 @@ +PODS: + - AppAuth (1.6.0): + - AppAuth/Core (= 1.6.0) + - AppAuth/ExternalUserAgent (= 1.6.0) + - AppAuth/Core (1.6.0) + - AppAuth/ExternalUserAgent (1.6.0): + - AppAuth/Core + - FBAEMKit (14.1.0): + - FBSDKCoreKit_Basics (= 14.1.0) + - FBSDKCoreKit (14.1.0): + - FBAEMKit (= 14.1.0) + - FBSDKCoreKit_Basics (= 14.1.0) + - FBSDKCoreKit_Basics (14.1.0) + - FBSDKLoginKit (14.1.0): + - FBSDKCoreKit (= 14.1.0) + - Firebase/Auth (10.0.0): + - Firebase/CoreOnly + - FirebaseAuth (~> 10.0.0) + - Firebase/CoreOnly (10.0.0): + - FirebaseCore (= 10.0.0) + - firebase_auth (4.1.1): + - Firebase/Auth (= 10.0.0) + - firebase_core + - Flutter + - firebase_core (2.1.1): + - Firebase/CoreOnly (= 10.0.0) + - Flutter + - FirebaseAuth (10.0.0): + - FirebaseCore (~> 10.0) + - GoogleUtilities/AppDelegateSwizzler (~> 7.8) + - GoogleUtilities/Environment (~> 7.8) + - GTMSessionFetcher/Core (~> 2.1) + - FirebaseCore (10.0.0): + - FirebaseCoreInternal (~> 10.0) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/Logger (~> 7.8) + - FirebaseCoreInternal (10.1.0): + - "GoogleUtilities/NSData+zlib (~> 7.8)" + - Flutter (1.0.0) + - flutter_facebook_auth (4.4.1): + - FBSDKLoginKit (= 14.1.0) + - Flutter + - google_sign_in_ios (0.0.1): + - Flutter + - GoogleSignIn (~> 6.2) + - GoogleSignIn (6.2.4): + - AppAuth (~> 1.5) + - GTMAppAuth (~> 1.3) + - GTMSessionFetcher/Core (< 3.0, >= 1.1) + - GoogleUtilities/AppDelegateSwizzler (7.8.0): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (7.8.0): + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/Logger (7.8.0): + - GoogleUtilities/Environment + - GoogleUtilities/Network (7.8.0): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (7.8.0)" + - GoogleUtilities/Reachability (7.8.0): + - GoogleUtilities/Logger + - GTMAppAuth (1.3.1): + - AppAuth/Core (~> 1.6) + - GTMSessionFetcher/Core (< 3.0, >= 1.5) + - GTMSessionFetcher/Core (2.1.0) + - PromisesObjC (2.1.1) + - sign_in_with_apple (0.0.1): + - Flutter + - twitter_login (0.0.1): + - Flutter + +DEPENDENCIES: + - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) + - firebase_core (from `.symlinks/plugins/firebase_core/ios`) + - Flutter (from `Flutter`) + - flutter_facebook_auth (from `.symlinks/plugins/flutter_facebook_auth/ios`) + - google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/ios`) + - sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`) + - twitter_login (from `.symlinks/plugins/twitter_login/ios`) + +SPEC REPOS: + trunk: + - AppAuth + - FBAEMKit + - FBSDKCoreKit + - FBSDKCoreKit_Basics + - FBSDKLoginKit + - Firebase + - FirebaseAuth + - FirebaseCore + - FirebaseCoreInternal + - GoogleSignIn + - GoogleUtilities + - GTMAppAuth + - GTMSessionFetcher + - PromisesObjC + +EXTERNAL SOURCES: + firebase_auth: + :path: ".symlinks/plugins/firebase_auth/ios" + firebase_core: + :path: ".symlinks/plugins/firebase_core/ios" + Flutter: + :path: Flutter + flutter_facebook_auth: + :path: ".symlinks/plugins/flutter_facebook_auth/ios" + google_sign_in_ios: + :path: ".symlinks/plugins/google_sign_in_ios/ios" + sign_in_with_apple: + :path: ".symlinks/plugins/sign_in_with_apple/ios" + twitter_login: + :path: ".symlinks/plugins/twitter_login/ios" + +SPEC CHECKSUMS: + AppAuth: 8fca6b5563a5baef2c04bee27538025e4ceb2add + FBAEMKit: a899515e45476027f73aef377b5cffadcd56ca3a + FBSDKCoreKit: 24f8bc8d3b5b2a8c5c656a1329492a12e8efa792 + FBSDKCoreKit_Basics: 6e578c9bdc7aa1365dbbbde633c9ebb536bcaa98 + FBSDKLoginKit: 787de205d524c3a4b17d527916f1d066e4361660 + Firebase: 1b810f3d0c0532e27a48f1961f8c0400a668a2cf + firebase_auth: dd33e93fce72a1c72040f7380dacf06e89db5705 + firebase_core: 5c0bb0ca7d0e70480a68a6e9ad9bf55d1edd5305 + FirebaseAuth: 493382cf533cc45e2862b00e9aa4cfe4c98daf71 + FirebaseCore: 97f48a3a567a72b8d4daa0f03c3aadb78df4e995 + FirebaseCoreInternal: 96d75228e10fd369564da51bd898414eb0f54df5 + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + flutter_facebook_auth: 361ac7a57263ebf327f26089507ead0d66558ee8 + google_sign_in_ios: 4f85eb9f937450765c8573bb85fd8cd6a5af675c + GoogleSignIn: 5651ce3a61e56ca864160e79b484cd9ed3f49b7a + GoogleUtilities: 1d20a6ad97ef46f67bbdec158ce00563a671ebb7 + GTMAppAuth: 0ff230db599948a9ad7470ca667337803b3fc4dd + GTMSessionFetcher: ffbb25ec00ebcb5201adab0a56d808f6f1902d9f + PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb + sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440 + twitter_login: 2794db69b7640681171b17b3c2c84ad9dfb4a57f + +PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 + +COCOAPODS: 1.11.3 diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.pbxproj b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..11d0d0ad --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,552 @@ +// !$*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 */; }; + 69F3BBCD5DEB05A456F6B74F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B0A061B2E527F311149C3581 /* Pods_Runner.framework */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 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 */; }; +/* 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 */ + 07E343497E760D6A90A105C5 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 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 = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; 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; }; + 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 = ""; }; + B0A061B2E527F311149C3581 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F0D7945BAE0BEA457137ED73 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + F9340E3A859C31E59380BD0F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 69F3BBCD5DEB05A456F6B74F /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 66B357379C2757D2844F12BB /* Pods */ = { + isa = PBXGroup; + children = ( + F0D7945BAE0BEA457137ED73 /* Pods-Runner.debug.xcconfig */, + F9340E3A859C31E59380BD0F /* Pods-Runner.release.xcconfig */, + 07E343497E760D6A90A105C5 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + 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 */, + 66B357379C2757D2844F12BB /* Pods */, + BC1E25CE0DADDF7B7201CCF8 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + BC1E25CE0DADDF7B7201CCF8 /* Frameworks */ = { + isa = PBXGroup; + children = ( + B0A061B2E527F311149C3581 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 92D20EC4971D81AAB7475BDB /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + DEBBE8DDE939288865FFA279 /* [CP] Embed Pods Frameworks */, + ); + 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 = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + 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"; + }; + 92D20EC4971D81AAB7475BDB /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 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"; + }; + DEBBE8DDE939288865FFA279 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift 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 */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + 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; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 6Z5P8GG96U; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleRouter; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 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; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 6Z5P8GG96U; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleRouter; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 6Z5P8GG96U; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleRouter; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + 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 */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..c87d15a3 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..21a3cc14 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/AppDelegate.swift b/packages/wyatt_authentication_bloc/example_router/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..70693e4a --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d36b1fab --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "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/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 00000000..dc9ada47 Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 00000000..28c6bf03 Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 00000000..2ccbfd96 Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 00000000..f091b6b0 Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 00000000..4cde1211 Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 00000000..d0ef06e7 Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 00000000..dcdc2306 Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 00000000..2ccbfd96 Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 00000000..c8f9ed8f Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 00000000..a6d6b860 Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 00000000..a6d6b860 Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 00000000..75b2d164 Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 00000000..c4df70d3 Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 00000000..6a84f41e Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 00000000..d0e1f585 Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 00000000..0bedcf2f --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "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/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 00000000..9da19eac Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 00000000..9da19eac Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 00000000..9da19eac Binary files /dev/null and b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 00000000..89c2725b --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# 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/packages/wyatt_authentication_bloc/example_router/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..f2e259c7 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Base.lproj/Main.storyboard b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 00000000..f3c28516 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Info.plist b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Info.plist new file mode 100644 index 00000000..e2987027 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Example Router + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + example_router + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/packages/wyatt_authentication_bloc/example_router/ios/Runner/Runner-Bridging-Header.h b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..308a2a56 --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/packages/wyatt_authentication_bloc/example_router/ios/firebase_app_id_file.json b/packages/wyatt_authentication_bloc/example_router/ios/firebase_app_id_file.json new file mode 100644 index 00000000..17445d1d --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/ios/firebase_app_id_file.json @@ -0,0 +1,7 @@ +{ + "file_generated_by": "FlutterFire CLI", + "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory", + "GOOGLE_APP_ID": "1:136771801992:ios:bcdca68d2b7d227097203d", + "FIREBASE_PROJECT_ID": "tchat-beta", + "GCM_SENDER_ID": "136771801992" +} \ No newline at end of file diff --git a/packages/wyatt_authentication_bloc/example_router/lib/bootstrap.dart b/packages/wyatt_authentication_bloc/example_router/lib/bootstrap.dart index cc0ab97e..f5fd03eb 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/bootstrap.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/bootstrap.dart @@ -3,23 +3,24 @@ // ----- // File: bootstrap.dart // Created Date: 19/08/2022 15:05:17 -// Last Modified: 19/08/2022 15:21:47 +// Last Modified: Wed Nov 09 2022 // ----- // Copyright (c) 2022 import 'dart:async'; +import 'package:example_router/core/dependency_injection/get_it.dart'; import 'package:example_router/core/utils/app_bloc_observer.dart'; import 'package:example_router/firebase_options.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:go_router/go_router.dart'; Future bootstrap(FutureOr Function() builder) async { await runZonedGuarded( () async { WidgetsFlutterBinding.ensureInitialized(); + Bloc.observer = AppBlocObserver(); FlutterError.onError = (details) { debugPrint(details.toString()); @@ -29,9 +30,7 @@ Future bootstrap(FutureOr Function() builder) async { options: DefaultFirebaseOptions.currentPlatform, ); - GoRouter.setUrlPathStrategy(UrlPathStrategy.path); - - Bloc.observer = AppBlocObserver(); + await GetItInitializer.init(); runApp(await builder()); }, diff --git a/packages/wyatt_authentication_bloc/example_router/lib/core/dependency_injection/get_it.dart b/packages/wyatt_authentication_bloc/example_router/lib/core/dependency_injection/get_it.dart new file mode 100644 index 00000000..f75d34df --- /dev/null +++ b/packages/wyatt_authentication_bloc/example_router/lib/core/dependency_injection/get_it.dart @@ -0,0 +1,34 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:get_it/get_it.dart'; +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; + +final getIt = GetIt.I; + +abstract class GetItInitializer { + static Future init() async { + getIt + ..registerLazySingleton( + () => AuthenticationFirebaseDataSourceImpl(), + ) + ..registerLazySingleton>( + () => AuthenticationCacheDataSourceImpl(), + ); + + await getIt.allReady(); + } +} diff --git a/packages/wyatt_authentication_bloc/example_router/lib/core/utils/forms.dart b/packages/wyatt_authentication_bloc/example_router/lib/core/utils/forms.dart deleted file mode 100644 index ead7fb45..00000000 --- a/packages/wyatt_authentication_bloc/example_router/lib/core/utils/forms.dart +++ /dev/null @@ -1,21 +0,0 @@ -// Author: Hugo Pointcheval -// Email: git@pcl.ovh -// ----- -// File: forms.dart -// Created Date: 19/08/2022 12:00:31 -// Last Modified: 19/08/2022 16:35:52 -// ----- -// Copyright (c) 2022 - -import 'package:example_router/core/constants/form_field.dart'; -import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; - -class Forms { - static FormData getNormalData() => const FormData([ - FormInput( - AppFormField.confirmedPassword, - ConfirmedPassword.pure(), - metadata: FormInputMetadata(export: false), - ), - ]); -} diff --git a/packages/wyatt_authentication_bloc/example_router/lib/firebase_options.dart b/packages/wyatt_authentication_bloc/example_router/lib/firebase_options.dart index 20a9ebf6..f0198262 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/firebase_options.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/firebase_options.dart @@ -24,12 +24,12 @@ class DefaultFirebaseOptions { } switch (defaultTargetPlatform) { case TargetPlatform.android: - return android; - case TargetPlatform.iOS: throw UnsupportedError( - 'DefaultFirebaseOptions have not been configured for ios - ' + 'DefaultFirebaseOptions have not been configured for android - ' 'you can reconfigure this by running the FlutterFire CLI again.', ); + case TargetPlatform.iOS: + return ios; case TargetPlatform.macOS: throw UnsupportedError( 'DefaultFirebaseOptions have not been configured for macos - ' @@ -52,12 +52,15 @@ class DefaultFirebaseOptions { } } - static const FirebaseOptions android = FirebaseOptions( - apiKey: 'AIzaSyAYS14uXupkS158Q5QAFP1864UrUN_yDSk', - appId: '1:136771801992:android:ac3cfeb99fb0763e97203d', + static const FirebaseOptions ios = FirebaseOptions( + apiKey: 'AIzaSyCDbbhjbFrQwLXuIANdJzjkDk8uOETnn7w', + appId: '1:136771801992:ios:bcdca68d2b7d227097203d', messagingSenderId: '136771801992', projectId: 'tchat-beta', databaseURL: 'https://tchat-beta.firebaseio.com', storageBucket: 'tchat-beta.appspot.com', + androidClientId: '136771801992-n2pq8oqutvrqj58e05hbavvc7n1jdfjb.apps.googleusercontent.com', + iosClientId: '136771801992-p629tpo9bk3hcm2955s5ahivdla57ln9.apps.googleusercontent.com', + iosBundleId: 'com.example.exampleRouter', ); } diff --git a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/app/app.dart b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/app/app.dart index 291387e7..9bf7f5cd 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/app/app.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/app/app.dart @@ -3,22 +3,58 @@ // ----- // File: app.dart // Created Date: 19/08/2022 12:05:38 -// Last Modified: Fri Aug 26 2022 +// Last Modified: Thu Nov 10 2022 // ----- // Copyright (c) 2022 +import 'dart:async'; +import 'dart:math'; + +import 'package:example_router/core/constants/form_field.dart'; +import 'package:example_router/core/dependency_injection/get_it.dart'; import 'package:example_router/core/routes/router.dart'; -import 'package:example_router/core/utils/forms.dart'; -import 'package:example_router/presentation/features/home/home_page.dart'; -import 'package:example_router/presentation/features/welcome/welcome_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; + +FutureResult onSignUpSuccess( + Account? account, + WyattForm form, +) async { + const id = -1; + final confirmedPassword = + form.valueOf(AppFormField.confirmedPassword); + + debugPrint( + 'onSignUpSuccess: $account, generatedId: $id, extraFormData: $confirmedPassword'); + return const Ok(id); +} + +FutureResult onAccountChanges(Account? account) async { + final id = Random().nextInt(1000); + debugPrint('onAccountChanges: $account, generatedId: $id'); + return Ok(id); +} class App extends StatelessWidget { - final AuthenticationRepository authenticationRepository = - AuthenticationRepositoryFirebase(); + final AuthenticationRepository authenticationRepository = + AuthenticationRepositoryImpl( + authenticationCacheDataSource: getIt>(), + authenticationRemoteDataSource: getIt(), + onSignUpSuccess: onSignUpSuccess, + onAuthChange: onAccountChanges, + extraSignUpInputs: [ + FormInput( + AppFormField.confirmedPassword, + const ConfirmedPassword.pure(), + metadata: const FormInputMetadata(export: false), + ), + ], + ); App({Key? key}) : super(key: key); @@ -26,13 +62,8 @@ class App extends StatelessWidget { Widget build(BuildContext context) { AuthenticationState? previous; - final AuthenticationCubit authenticationCubit = AuthenticationCubit( - authenticationRepository: authenticationRepository, - onAuthSuccess: (user) async { - debugPrint(user.toString()); - return {}; - }, - ); + final AuthenticationCubit authenticationCubit = + AuthenticationCubit(authenticationRepository: authenticationRepository); final GoRouter router = GoRouter( initialLocation: '/', @@ -42,7 +73,7 @@ class App extends StatelessWidget { color: Colors.red, ), refreshListenable: GoRouterRefreshStream(authenticationCubit.stream), - redirect: (state) { + redirect: (context, state) { final authState = authenticationCubit.state; if (authState != previous) { @@ -59,13 +90,12 @@ class App extends StatelessWidget { if (isOnboarding) { return null; } else { - return state.namedLocation(WelcomePage.pageName); + return '/'; } } else { - final email = authState.user?.email; - debugPrint('Logged as: $email'); + debugPrint('Logged'); if (isOnboarding) { - return state.namedLocation(HomePage.pageName); + return '/home'; } else { return null; } @@ -83,20 +113,15 @@ class App extends StatelessWidget { ], child: MultiBlocProvider( providers: [ - BlocProvider.value( - value: authenticationCubit..init(), + BlocProvider>.value( + value: authenticationCubit, ), - BlocProvider( + BlocProvider>( create: (_) => SignUpCubit( authenticationRepository: authenticationRepository, - formData: Forms.getNormalData(), - onSignUpSuccess: (state, uid) async { - debugPrint(state.toString()); - debugPrint(uid); - }, ), ), - BlocProvider( + BlocProvider>( create: (_) => SignInCubit( authenticationRepository: authenticationRepository, ), @@ -105,11 +130,26 @@ class App extends StatelessWidget { child: MaterialApp.router( title: 'Demo Authentication', debugShowCheckedModeBanner: false, - routerDelegate: router.routerDelegate, - routeInformationParser: router.routeInformationParser, - routeInformationProvider: router.routeInformationProvider, + routerConfig: router, ), ), ); } } + +class GoRouterRefreshStream extends ChangeNotifier { + GoRouterRefreshStream(Stream stream) { + notifyListeners(); + _subscription = stream.asBroadcastStream().listen( + (dynamic _) => notifyListeners(), + ); + } + + late final StreamSubscription _subscription; + + @override + void dispose() { + _subscription.cancel(); + super.dispose(); + } +} diff --git a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/home/home_page.dart b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/home/home_page.dart index 316598cb..e271c7e1 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/home/home_page.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/home/home_page.dart @@ -3,7 +3,7 @@ // ----- // File: home_page.dart // Created Date: 19/08/2022 14:38:24 -// Last Modified: 19/08/2022 16:12:22 +// Last Modified: Wed Nov 09 2022 // ----- // Copyright (c) 2022 @@ -25,7 +25,7 @@ class HomePage extends StatelessWidget { title: const Text('Home'), actions: [ IconButton( - onPressed: () => context.read().logOut(), + onPressed: () => context.read>().signOut(), icon: const Icon(Icons.logout_rounded)) ], ), @@ -34,11 +34,12 @@ class HomePage extends StatelessWidget { child: SingleChildScrollView( child: Column( children: [ - BlocBuilder( - builder: (context, state) { - final email = state.user?.email; - return Text('Logged as $email'); - }, + AuthenticationBuilder( + authenticated: (context, accountWrapper) => + Text('Logged as ${accountWrapper.account?.email} | GeneratedId is ${accountWrapper.data}'), + unauthenticated: (context) => + const Text('Not logged (unauthenticated)'), + unknown: (context) => const Text('Not logged (unknown)'), ), const SizedBox( height: 8, diff --git a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_in/widgets/sign_in_form.dart b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_in/widgets/sign_in_form.dart index ea785177..7df70853 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_in/widgets/sign_in_form.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_in/widgets/sign_in_form.dart @@ -3,30 +3,31 @@ // ----- // File: sign_in_form.dart // Created Date: 19/08/2022 15:24:37 -// Last Modified: 19/08/2022 16:35:01 +// Last Modified: Thu Nov 10 2022 // ----- // Copyright (c) 2022 import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; class _EmailInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - buildWhen: (previous, current) => previous.email != current.email, - builder: (context, state) { + return InputBuilder>( + field: AuthFormField.email, + builder: ((context, cubit, state, field, inputValid) { return TextField( - onChanged: (email) => context.read().emailChanged(email), + onChanged: (email) => cubit.emailChanged(email), keyboardType: TextInputType.emailAddress, decoration: InputDecoration( labelText: 'Email', helperText: '', - errorText: state.email.invalid ? 'Invalid email' : null, + errorText: !inputValid ? 'Invalid email' : null, ), ); - }, + }), ); } } @@ -34,21 +35,19 @@ class _EmailInput extends StatelessWidget { class _PasswordInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - buildWhen: (previous, current) => previous.password != current.password, - builder: (context, state) { + return InputBuilder>( + field: AuthFormField.password, + builder: ((context, cubit, state, field, inputValid) { return TextField( - onChanged: (password) { - context.read().passwordChanged(password); - }, + onChanged: (pwd) => cubit.passwordChanged(pwd), obscureText: true, decoration: InputDecoration( labelText: 'Password', helperText: '', - errorText: state.password.invalid ? 'Invalid password' : null, + errorText: !inputValid ? 'Invalid password' : null, ), ); - }, + }), ); } } @@ -56,18 +55,15 @@ class _PasswordInput extends StatelessWidget { class _SignInButton extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return state.status.isSubmissionInProgress + return SubmitBuilder>( + builder: ((context, cubit, status) { + return status.isSubmissionInProgress ? const CircularProgressIndicator() : ElevatedButton( - onPressed: state.status.isValidated - ? () => - context.read().signInWithEmailAndPassword() - : null, + onPressed: status.isValidated ? () => cubit.submit() : null, child: const Text('Sign in'), ); - }, + }), ); } } @@ -77,11 +73,9 @@ class SignInForm extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocListener( + return BlocListener, SignInState>( listener: (context, state) { - if (state.status.isSubmissionSuccess) { - Navigator.of(context).pop(); - } else if (state.status.isSubmissionFailure) { + if (state.status.isSubmissionFailure) { ScaffoldMessenger.of(context) ..hideCurrentSnackBar() ..showSnackBar( diff --git a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_up/widgets/sign_up_form.dart b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_up/widgets/sign_up_form.dart index 4a7faf42..e01038ea 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_up/widgets/sign_up_form.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sign_up/widgets/sign_up_form.dart @@ -3,12 +3,12 @@ // ----- // File: sign_up_form.dart // Created Date: 19/08/2022 14:41:08 -// Last Modified: Fri Aug 26 2022 +// Last Modified: Thu Nov 10 2022 // ----- // Copyright (c) 2022 import 'package:example_router/core/constants/form_field.dart'; -import 'package:flutter/material.dart'; +import 'package:flutter/material.dart' hide FormField; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; @@ -16,19 +16,19 @@ import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; class _EmailInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - buildWhen: (previous, current) => previous.email != current.email, - builder: (context, state) { + return InputBuilder>( + field: AuthFormField.email, + builder: ((context, cubit, state, field, inputValid) { return TextField( - onChanged: (email) => context.read().emailChanged(email), + onChanged: (email) => cubit.emailChanged(email), keyboardType: TextInputType.emailAddress, decoration: InputDecoration( labelText: 'Email', helperText: '', - errorText: state.email.invalid ? 'Invalid email' : null, + errorText: !inputValid ? 'Invalid email' : null, ), ); - }, + }), ); } } @@ -36,33 +36,27 @@ class _EmailInput extends StatelessWidget { class _PasswordInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - buildWhen: (previous, current) => previous.password != current.password, - builder: (context, state) { + return InputBuilder>( + field: AuthFormField.password, + builder: ((context, cubit, state, field, inputValid) { return TextField( - onChanged: (password) { - context.read().passwordChanged(password); - context.read().dataChanged( - AppFormField.confirmedPassword, - ConfirmedPassword.dirty( - password: password, - value: context - .read() - .state - .data - .valueOf( - AppFormField.confirmedPassword), - ), - ); + onChanged: (pwd) { + cubit.passwordChanged(pwd); + cubit.dataChanged( + AppFormField.confirmedPassword, + ConfirmedPassword.dirty( + password: pwd, + value: state.form + .valueOf(AppFormField.confirmedPassword))); }, obscureText: true, decoration: InputDecoration( labelText: 'Password', helperText: '', - errorText: state.password.invalid ? 'Invalid password' : null, + errorText: !inputValid ? 'Invalid password' : null, ), ); - }, + }), ); } } @@ -70,28 +64,27 @@ class _PasswordInput extends StatelessWidget { class _ConfirmPasswordInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { + return InputBuilder>( + field: AppFormField.confirmedPassword, + builder: ((context, cubit, state, field, inputValid) { return TextField( - onChanged: (confirmPassword) => context - .read() - .dataChanged( - AppFormField.confirmedPassword, - ConfirmedPassword.dirty( - password: context.read().state.password.value, - value: confirmPassword, - ), - ), + onChanged: (pwd) { + cubit.dataChanged( + field, + ConfirmedPassword.dirty( + password: + state.form.valueOf(AuthFormField.password) ?? '', + value: pwd), + ); + }, obscureText: true, decoration: InputDecoration( labelText: 'Confirm password', helperText: '', - errorText: state.data.isNotValid(AppFormField.confirmedPassword) - ? 'Passwords do not match' - : null, + errorText: !inputValid ? 'Passwords do not match' : null, ), ); - }, + }), ); } } @@ -99,17 +92,15 @@ class _ConfirmPasswordInput extends StatelessWidget { class _SignUpButton extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return state.status.isSubmissionInProgress + return SubmitBuilder>( + builder: ((context, cubit, status) { + return status.isSubmissionInProgress ? const CircularProgressIndicator() : ElevatedButton( - onPressed: state.status.isValidated - ? () => context.read().signUpFormSubmitted() - : null, + onPressed: status.isValidated ? () => cubit.submit() : null, child: const Text('Sign up'), ); - }, + }), ); } } @@ -119,11 +110,9 @@ class SignUpForm extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocListener( + return BlocListener, SignUpState>( listener: (context, state) { - if (state.status.isSubmissionSuccess) { - Navigator.of(context).pop(); - } else if (state.status.isSubmissionFailure) { + if (state.status.isSubmissionFailure) { ScaffoldMessenger.of(context) ..hideCurrentSnackBar() ..showSnackBar( diff --git a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sub/sub_page.dart b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sub/sub_page.dart index 34f4558f..14b340b8 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sub/sub_page.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/sub/sub_page.dart @@ -3,7 +3,7 @@ // ----- // File: sub_page.dart // Created Date: 19/08/2022 16:10:05 -// Last Modified: 19/08/2022 16:10:44 +// Last Modified: Wed Nov 09 2022 // ----- // Copyright (c) 2022 @@ -23,7 +23,7 @@ class SubPage extends StatelessWidget { title: const Text('Sub'), actions: [ IconButton( - onPressed: () => context.read().logOut(), + onPressed: () => context.read>().signOut(), icon: const Icon(Icons.logout_rounded)) ], ), diff --git a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/welcome/welcome_page.dart b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/welcome/welcome_page.dart index aa3a10c4..3794f971 100644 --- a/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/welcome/welcome_page.dart +++ b/packages/wyatt_authentication_bloc/example_router/lib/presentation/features/welcome/welcome_page.dart @@ -3,16 +3,14 @@ // ----- // File: welcome_page.dart // Created Date: 19/08/2022 12:33:21 -// Last Modified: 19/08/2022 15:56:05 +// Last Modified: Wed Nov 09 2022 // ----- // Copyright (c) 2022 import 'package:example_router/presentation/features/sign_in/sign_in_page.dart'; import 'package:example_router/presentation/features/sign_up/sign_up_page.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; -import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; class WelcomePage extends StatelessWidget { const WelcomePage({Key? key}) : super(key: key); @@ -24,12 +22,6 @@ class WelcomePage extends StatelessWidget { return Scaffold( appBar: AppBar( title: const Text('Welcome'), - actions: [ - IconButton( - onPressed: () => context.read().changeStatus( - context.read().state.user!), - icon: const Icon(Icons.refresh_rounded)) - ], ), body: SingleChildScrollView( child: Column( diff --git a/packages/wyatt_authentication_bloc/example_router/pubspec.yaml b/packages/wyatt_authentication_bloc/example_router/pubspec.yaml index 5f6dec50..19c6e09e 100644 --- a/packages/wyatt_authentication_bloc/example_router/pubspec.yaml +++ b/packages/wyatt_authentication_bloc/example_router/pubspec.yaml @@ -30,8 +30,8 @@ dependencies: flutter: sdk: flutter - go_router: ^4.2.8 - firebase_core: ^1.21.0 + go_router: ^5.1.5 + firebase_core: ^2.1.1 flutter_bloc: ^8.1.1 wyatt_authentication_bloc: path: "../" @@ -41,10 +41,17 @@ dependencies: url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages ref: wyatt_form_bloc-v0.0.6 path: packages/wyatt_form_bloc + + wyatt_type_utils: + git: + url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages + ref: wyatt_type_utils-v0.0.3+1 + path: packages/wyatt_type_utils # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.2 + cupertino_icons: ^1.0.5 + get_it: ^7.2.0 dev_dependencies: flutter_test: diff --git a/packages/wyatt_authentication_bloc/lib/src/core/constants/form_field.dart b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_field.dart new file mode 100644 index 00000000..295cfc2f --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_field.dart @@ -0,0 +1,20 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +abstract class AuthFormField { + static const email = 'wyattEmailField'; + static const password = 'wyattPasswordField'; +} diff --git a/packages/wyatt_authentication_bloc/lib/src/core/constants/form_name.dart b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_name.dart new file mode 100644 index 00000000..5a788715 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/core/constants/form_name.dart @@ -0,0 +1,20 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +abstract class AuthFormName { + static const String signUpForm = 'wyattSignUpForm'; + static const String signInForm = 'wyattSignInForm'; +} diff --git a/packages/wyatt_authentication_bloc/lib/src/core/core.dart b/packages/wyatt_authentication_bloc/lib/src/core/core.dart new file mode 100644 index 00000000..16b0264b --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/core/core.dart @@ -0,0 +1,21 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'constants/form_field.dart'; +export 'constants/form_name.dart'; +export 'enums/enums.dart'; +export 'exceptions/exceptions.dart'; +export 'utils/utils.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/core/enums/authentication_status.dart b/packages/wyatt_authentication_bloc/lib/src/core/enums/authentication_status.dart new file mode 100644 index 00000000..af10ceae --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/core/enums/authentication_status.dart @@ -0,0 +1,21 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +enum AuthenticationStatus { + unknown, + authenticated, + unauthenticated, +} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/email_verification.dart b/packages/wyatt_authentication_bloc/lib/src/core/enums/enums.dart similarity index 92% rename from packages/wyatt_authentication_bloc/lib/src/features/email_verification/email_verification.dart rename to packages/wyatt_authentication_bloc/lib/src/core/enums/enums.dart index 59beab8e..67d107d6 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/email_verification.dart +++ b/packages/wyatt_authentication_bloc/lib/src/core/enums/enums.dart @@ -1,17 +1,17 @@ // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with this program. If not, see . -export 'cubit/email_verification_cubit.dart'; +export 'authentication_status.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions.dart b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions.dart index 44f258f7..11e7835d 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions.dart +++ b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions.dart @@ -14,13 +14,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -abstract class AuthenticationFailureInterface implements Exception { - String code; - String message; +import 'package:wyatt_architecture/wyatt_architecture.dart'; - AuthenticationFailureInterface(this.code, this.message); +part 'exceptions_firebase.dart'; + +abstract class AuthenticationFailureInterface extends AppException + implements Exception { + String code; + String msg; + + AuthenticationFailureInterface(this.code, this.msg); AuthenticationFailureInterface.fromCode(this.code) - : message = 'An unknown error occurred.'; + : msg = 'An unknown error occurred.'; } /// {@template apply_action_code_failure} @@ -29,7 +34,7 @@ abstract class AuthenticationFailureInterface implements Exception { abstract class ApplyActionCodeFailureInterface extends AuthenticationFailureInterface { /// {@macro apply_action_code_failure} - ApplyActionCodeFailureInterface(super.code, super.message); + ApplyActionCodeFailureInterface(super.code, super.msg); /// {@macro apply_action_code_failure} ApplyActionCodeFailureInterface.fromCode(super.code) : super.fromCode(); @@ -41,7 +46,7 @@ abstract class ApplyActionCodeFailureInterface abstract class SignUpWithEmailAndPasswordFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_up_with_email_and_password_failure} - SignUpWithEmailAndPasswordFailureInterface(super.code, super.message); + SignUpWithEmailAndPasswordFailureInterface(super.code, super.msg); /// {@macro sign_up_with_email_and_password_failure} SignUpWithEmailAndPasswordFailureInterface.fromCode(super.code) @@ -54,7 +59,7 @@ abstract class SignUpWithEmailAndPasswordFailureInterface abstract class FetchSignInMethodsForEmailFailureInterface extends AuthenticationFailureInterface { /// {@macro fetch_sign_in_methods_failure} - FetchSignInMethodsForEmailFailureInterface(super.code, super.message); + FetchSignInMethodsForEmailFailureInterface(super.code, super.msg); /// {@macro fetch_sign_in_methods_failure} FetchSignInMethodsForEmailFailureInterface.fromCode(super.code) @@ -67,7 +72,7 @@ abstract class FetchSignInMethodsForEmailFailureInterface abstract class SignInWithCredentialFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_with_credential_failure} - SignInWithCredentialFailureInterface(super.code, super.message); + SignInWithCredentialFailureInterface(super.code, super.msg); /// {@macro sign_in_with_credential_failure} SignInWithCredentialFailureInterface.fromCode(super.code) : super.fromCode(); @@ -79,7 +84,7 @@ abstract class SignInWithCredentialFailureInterface abstract class SignInAnonymouslyFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_anonymously_failure} - SignInAnonymouslyFailureInterface(super.code, super.message); + SignInAnonymouslyFailureInterface(super.code, super.msg); /// {@macro sign_in_anonymously_failure} SignInAnonymouslyFailureInterface.fromCode(super.code) : super.fromCode(); @@ -91,7 +96,7 @@ abstract class SignInAnonymouslyFailureInterface abstract class SignInWithGoogleFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_with_google_failure} - SignInWithGoogleFailureInterface(super.code, super.message); + SignInWithGoogleFailureInterface(super.code, super.msg); /// {@macro sign_in_with_google_failure} SignInWithGoogleFailureInterface.fromCode(super.code) : super.fromCode(); @@ -103,7 +108,7 @@ abstract class SignInWithGoogleFailureInterface abstract class SignInWithFacebookFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_with_facebook_failure} - SignInWithFacebookFailureInterface(super.code, super.message); + SignInWithFacebookFailureInterface(super.code, super.msg); /// {@macro sign_in_with_facebook_failure} SignInWithFacebookFailureInterface.fromCode(super.code) : super.fromCode(); @@ -115,7 +120,7 @@ abstract class SignInWithFacebookFailureInterface abstract class SignInWithAppleFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_with_apple_failure} - SignInWithAppleFailureInterface(super.code, super.message); + SignInWithAppleFailureInterface(super.code, super.msg); /// {@macro sign_in_with_apple_failure} SignInWithAppleFailureInterface.fromCode(super.code) : super.fromCode(); @@ -127,7 +132,7 @@ abstract class SignInWithAppleFailureInterface abstract class SignInWithTwitterFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_with_twitter_failure} - SignInWithTwitterFailureInterface(super.code, super.message); + SignInWithTwitterFailureInterface(super.code, super.msg); /// {@macro sign_in_with_twitter_failure} SignInWithTwitterFailureInterface.fromCode(super.code) : super.fromCode(); @@ -139,7 +144,7 @@ abstract class SignInWithTwitterFailureInterface abstract class SignInWithEmailLinkFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_with_email_link_failure} - SignInWithEmailLinkFailureInterface(super.code, super.message); + SignInWithEmailLinkFailureInterface(super.code, super.msg); /// {@macro sign_in_with_email_link_failure} SignInWithEmailLinkFailureInterface.fromCode(super.code) : super.fromCode(); @@ -151,7 +156,7 @@ abstract class SignInWithEmailLinkFailureInterface abstract class SignInWithEmailAndPasswordFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_in_with_email_and_password_failure} - SignInWithEmailAndPasswordFailureInterface(super.code, super.message); + SignInWithEmailAndPasswordFailureInterface(super.code, super.msg); /// {@macro sign_in_with_email_and_password_failure} SignInWithEmailAndPasswordFailureInterface.fromCode(super.code) @@ -164,7 +169,7 @@ abstract class SignInWithEmailAndPasswordFailureInterface abstract class SendEmailVerificationFailureInterface extends AuthenticationFailureInterface { /// {@macro send_email_verification_failure} - SendEmailVerificationFailureInterface(super.code, super.message); + SendEmailVerificationFailureInterface(super.code, super.msg); /// {@macro send_email_verification_failure} SendEmailVerificationFailureInterface.fromCode(super.code) : super.fromCode(); @@ -176,7 +181,7 @@ abstract class SendEmailVerificationFailureInterface abstract class SendPasswordResetEmailFailureInterface extends AuthenticationFailureInterface { /// {@macro send_password_reset_email_failure} - SendPasswordResetEmailFailureInterface(super.code, super.message); + SendPasswordResetEmailFailureInterface(super.code, super.msg); /// {@macro send_password_reset_email_failure} SendPasswordResetEmailFailureInterface.fromCode(super.code) @@ -189,7 +194,7 @@ abstract class SendPasswordResetEmailFailureInterface abstract class SendSignInLinkEmailFailureInterface extends AuthenticationFailureInterface { /// {@macro send_sign_in_link_email_failure} - SendSignInLinkEmailFailureInterface(super.code, super.message); + SendSignInLinkEmailFailureInterface(super.code, super.msg); /// {@macro send_sign_in_link_email_failure} SendSignInLinkEmailFailureInterface.fromCode(super.code) : super.fromCode(); @@ -201,7 +206,7 @@ abstract class SendSignInLinkEmailFailureInterface abstract class ConfirmPasswordResetFailureInterface extends AuthenticationFailureInterface { /// {@macro confirm_password_reset_failure} - ConfirmPasswordResetFailureInterface(super.code, super.message); + ConfirmPasswordResetFailureInterface(super.code, super.msg); /// {@macro confirm_password_reset_failure} ConfirmPasswordResetFailureInterface.fromCode(super.code) : super.fromCode(); @@ -213,7 +218,7 @@ abstract class ConfirmPasswordResetFailureInterface abstract class VerifyPasswordResetCodeFailureInterface extends AuthenticationFailureInterface { /// {@macro verify_password_reset_code_failure} - VerifyPasswordResetCodeFailureInterface(super.code, super.message); + VerifyPasswordResetCodeFailureInterface(super.code, super.msg); /// {@macro verify_password_reset_code_failure} VerifyPasswordResetCodeFailureInterface.fromCode(super.code) @@ -225,7 +230,7 @@ abstract class VerifyPasswordResetCodeFailureInterface /// {@endtemplate} abstract class RefreshFailureInterface extends AuthenticationFailureInterface { /// {@macro refresh_failure} - RefreshFailureInterface(super.code, super.message); + RefreshFailureInterface(super.code, super.msg); /// {@macro refresh_failure} RefreshFailureInterface.fromCode(super.code) : super.fromCode(); @@ -236,7 +241,7 @@ abstract class RefreshFailureInterface extends AuthenticationFailureInterface { /// {@endtemplate} abstract class SignOutFailureInterface extends AuthenticationFailureInterface { /// {@macro sign_out_failure} - SignOutFailureInterface(super.code, super.message); + SignOutFailureInterface(super.code, super.msg); /// {@macro sign_out_failure} SignOutFailureInterface.fromCode(super.code) : super.fromCode(); diff --git a/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_firebase.dart b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_firebase.dart index a2d2c108..42f410a2 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_firebase.dart +++ b/packages/wyatt_authentication_bloc/lib/src/core/exceptions/exceptions_firebase.dart @@ -14,133 +14,130 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; +part of 'exceptions.dart'; class ApplyActionCodeFailureFirebase extends ApplyActionCodeFailureInterface { - ApplyActionCodeFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + ApplyActionCodeFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); ApplyActionCodeFailureFirebase.fromCode(String code) : super.fromCode(code) { switch (code) { case 'expired-action-code': - message = 'Action code has expired.'; + msg = 'Action code has expired.'; break; case 'invalid-action-code': - message = 'Action code is invalid.'; + msg = 'Action code is invalid.'; break; case 'user-disabled': - message = - 'This user has been disabled. Please contact support for help.'; + msg = 'This user has been disabled. Please contact support for help.'; break; case 'user-not-found': - message = 'Email is not found, please create an account.'; + msg = 'Email is not found, please create an account.'; break; default: this.code = 'unknown'; - message = 'An unknown error occurred.'; + msg = 'An unknown error occurred.'; } } } class SignUpWithEmailAndPasswordFailureFirebase extends SignUpWithEmailAndPasswordFailureInterface { - SignUpWithEmailAndPasswordFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SignUpWithEmailAndPasswordFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SignUpWithEmailAndPasswordFailureFirebase.fromCode(String code) : super.fromCode(code) { switch (code) { case 'invalid-email': - message = 'The email address is badly formatted.'; + msg = 'The email address is badly formatted.'; break; case 'user-disabled': - message = - 'This user has been disabled. Please contact support for help.'; + msg = 'This user has been disabled. Please contact support for help.'; break; case 'email-already-in-use': - message = 'An account already exists for that email.'; + msg = 'An account already exists for that email.'; break; case 'operation-not-allowed': - message = 'Operation is not allowed. Please contact support.'; + msg = 'Operation is not allowed. Please contact support.'; break; case 'weak-password': - message = 'Please enter a stronger password.'; + msg = 'Please enter a stronger password.'; break; default: this.code = 'unknown'; - message = 'An unknown error occurred.'; + msg = 'An unknown error occurred.'; } } } class FetchSignInMethodsForEmailFailureFirebase extends FetchSignInMethodsForEmailFailureInterface { - FetchSignInMethodsForEmailFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + FetchSignInMethodsForEmailFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); FetchSignInMethodsForEmailFailureFirebase.fromCode(String code) : super.fromCode(code) { switch (code) { case 'invalid-email': - message = 'The email address is badly formatted.'; + msg = 'The email address is badly formatted.'; break; default: this.code = 'unknown'; - message = 'An unknown error occurred.'; + msg = 'An unknown error occurred.'; } } } class SignInAnonymouslyFailureFirebase extends SignInAnonymouslyFailureInterface { - SignInAnonymouslyFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SignInAnonymouslyFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SignInAnonymouslyFailureFirebase.fromCode(String code) : super.fromCode(code) { switch (code) { case 'operation-not-allowed': - message = 'Operation is not allowed. Please contact support.'; + msg = 'Operation is not allowed. Please contact support.'; break; default: this.code = 'unknown'; - message = 'An unknown error occurred.'; + msg = 'An unknown error occurred.'; } } } class SignInWithCredentialFailureFirebase extends SignInWithCredentialFailureInterface { - SignInWithCredentialFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SignInWithCredentialFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SignInWithCredentialFailureFirebase.fromCode(String code) : super.fromCode(code) { switch (code) { case 'account-exists-with-different-credential': - message = 'Account exists with different credentials.'; + msg = 'Account exists with different credentials.'; break; case 'invalid-credential': - message = 'The credential received is malformed or has expired.'; + msg = 'The credential received is malformed or has expired.'; break; case 'operation-not-allowed': - message = 'Operation is not allowed. Please contact support.'; + msg = 'Operation is not allowed. Please contact support.'; break; case 'user-disabled': - message = - 'This user has been disabled. Please contact support for help.'; + msg = 'This user has been disabled. Please contact support for help.'; break; case 'user-not-found': - message = 'Email is not found, please create an account.'; + msg = 'Email is not found, please create an account.'; break; case 'wrong-password': - message = 'Incorrect password, please try again.'; + msg = 'Incorrect password, please try again.'; break; case 'invalid-verification-code': - message = 'The credential verification code received is invalid.'; + msg = 'The credential verification code received is invalid.'; break; case 'invalid-verification-id': - message = 'The credential verification ID received is invalid.'; + msg = 'The credential verification ID received is invalid.'; break; default: this.code = 'unknown'; - message = 'An unknown error occurred.'; + msg = 'An unknown error occurred.'; } } } @@ -148,130 +145,128 @@ class SignInWithCredentialFailureFirebase class SignInWithGoogleFailureFirebase extends SignInWithCredentialFailureFirebase implements SignInWithGoogleFailureInterface { - SignInWithGoogleFailureFirebase([super.code, super.message]); + SignInWithGoogleFailureFirebase([super.code, super.msg]); SignInWithGoogleFailureFirebase.fromCode(super.code) : super.fromCode(); } class SignInWithFacebookFailureFirebase extends SignInWithCredentialFailureFirebase implements SignInWithFacebookFailureInterface { - SignInWithFacebookFailureFirebase([super.code, super.message]); + SignInWithFacebookFailureFirebase([super.code, super.msg]); SignInWithFacebookFailureFirebase.fromCode(super.code) : super.fromCode(); } class SignInWithAppleFailureFirebase extends SignInWithCredentialFailureFirebase implements SignInWithAppleFailureInterface { - SignInWithAppleFailureFirebase([super.code, super.message]); + SignInWithAppleFailureFirebase([super.code, super.msg]); SignInWithAppleFailureFirebase.fromCode(super.code) : super.fromCode(); } class SignInWithTwitterFailureFirebase extends SignInWithCredentialFailureFirebase implements SignInWithAppleFailureInterface { - SignInWithTwitterFailureFirebase([super.code, super.message]); + SignInWithTwitterFailureFirebase([super.code, super.msg]); SignInWithTwitterFailureFirebase.fromCode(super.code) : super.fromCode(); } class SignInWithEmailLinkFailureFirebase extends SignInWithEmailLinkFailureInterface { - SignInWithEmailLinkFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SignInWithEmailLinkFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SignInWithEmailLinkFailureFirebase.fromCode(String code) : super.fromCode(code) { switch (code) { case 'expired-action-code': - message = 'Action code has expired.'; + msg = 'Action code has expired.'; break; case 'invalid-email': - message = 'Email is not valid or badly formatted.'; + msg = 'Email is not valid or badly formatted.'; break; case 'user-disabled': - message = - 'This user has been disabled. Please contact support for help.'; + msg = 'This user has been disabled. Please contact support for help.'; break; default: this.code = 'unknown'; - message = 'An unknown error occurred.'; + msg = 'An unknown error occurred.'; } } } class SignInWithEmailAndPasswordFailureFirebase extends SignInWithEmailAndPasswordFailureInterface { - SignInWithEmailAndPasswordFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SignInWithEmailAndPasswordFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SignInWithEmailAndPasswordFailureFirebase.fromCode(String code) : super.fromCode(code) { switch (code) { case 'invalid-email': - message = 'Email is not valid or badly formatted.'; + msg = 'Email is not valid or badly formatted.'; break; case 'user-disabled': - message = - 'This user has been disabled. Please contact support for help.'; + msg = 'This user has been disabled. Please contact support for help.'; break; case 'user-not-found': - message = 'Email is not found, please create an account.'; + msg = 'Email is not found, please create an account.'; break; case 'wrong-password': - message = 'Incorrect password, please try again.'; + msg = 'Incorrect password, please try again.'; break; default: this.code = 'unknown'; - message = 'An unknown error occurred.'; + msg = 'An unknown error occurred.'; } } } class SendEmailVerificationFailureFirebase extends SendEmailVerificationFailureInterface { - SendEmailVerificationFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SendEmailVerificationFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SendEmailVerificationFailureFirebase.fromCode(super.code) : super.fromCode(); } class SendPasswordResetEmailFailureFirebase extends SendPasswordResetEmailFailureInterface { - SendPasswordResetEmailFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SendPasswordResetEmailFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SendPasswordResetEmailFailureFirebase.fromCode(super.code) : super.fromCode(); } class SendSignInLinkEmailFailureFirebase extends SendSignInLinkEmailFailureInterface { - SendSignInLinkEmailFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SendSignInLinkEmailFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SendSignInLinkEmailFailureFirebase.fromCode(super.code) : super.fromCode(); } class ConfirmPasswordResetFailureFirebase extends ConfirmPasswordResetFailureInterface { - ConfirmPasswordResetFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + ConfirmPasswordResetFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); ConfirmPasswordResetFailureFirebase.fromCode(super.code) : super.fromCode(); } class VerifyPasswordResetCodeFailureFirebase extends VerifyPasswordResetCodeFailureInterface { - VerifyPasswordResetCodeFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + VerifyPasswordResetCodeFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); VerifyPasswordResetCodeFailureFirebase.fromCode(super.code) : super.fromCode(); } class RefreshFailureFirebase extends RefreshFailureInterface { - RefreshFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + RefreshFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); RefreshFailureFirebase.fromCode(super.code) : super.fromCode(); } class SignOutFailureFirebase extends SignOutFailureInterface { - SignOutFailureFirebase([String? code, String? message]) - : super(code ?? 'unknown', message ?? 'An unknown error occurred.'); + SignOutFailureFirebase([String? code, String? msg]) + : super(code ?? 'unknown', msg ?? 'An unknown error occurred.'); SignOutFailureFirebase.fromCode(super.code) : super.fromCode(); } diff --git a/packages/wyatt_authentication_bloc/lib/src/core/enum/auth_cubit_status.dart b/packages/wyatt_authentication_bloc/lib/src/core/utils/utils.dart similarity index 92% rename from packages/wyatt_authentication_bloc/lib/src/core/enum/auth_cubit_status.dart rename to packages/wyatt_authentication_bloc/lib/src/core/utils/utils.dart index 37448fa1..81005a25 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/enum/auth_cubit_status.dart +++ b/packages/wyatt_authentication_bloc/lib/src/core/utils/utils.dart @@ -1,20 +1,17 @@ // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with this program. If not, see . -enum AuthCubitStatus { - started, - stoped, -} +export 'cryptography.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data.dart b/packages/wyatt_authentication_bloc/lib/src/data/data.dart new file mode 100644 index 00000000..42218c55 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/data.dart @@ -0,0 +1,19 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'data_sources/data_sources.dart'; +export 'models/models.dart'; +export 'repositories/repositories.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/data_sources.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/data_sources.dart new file mode 100644 index 00000000..346c8fa7 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/data_sources.dart @@ -0,0 +1,18 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'local/authentication_cache_data_source_impl.dart'; +export 'remote/authentication_firebase_data_source_impl.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_cache_data_source_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_cache_data_source_impl.dart new file mode 100644 index 00000000..57b1191a --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/local/authentication_cache_data_source_impl.dart @@ -0,0 +1,67 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +class AuthenticationCacheDataSourceImpl + extends AuthenticationCacheDataSource { + Account? _account; + T? _data; + + AuthenticationCacheDataSourceImpl(); + + @override + Future storeAccount(Account? account) async { + _account = account; + } + + @override + Future storeData(T? data) async { + _data = data; + } + + @override + Future loadAccount() async { + if (_account.isNotNull) { + return _account!; + } + throw ClientException('Cached account is invalid'); + } + + @override + Future loadData() async { + if (_data.isNotNull) { + return _data!; + } + throw ClientException('Cached data is invalid'); + } + + @override + Future destroy() async { + _data = null; + _account = null; + } + + @override + Future> load() async { + if (_account.isNull) { + throw ClientException('Cached account is invalid'); + } + return AccountWrapperModel(_account, _data); + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart new file mode 100644 index 00000000..f0c55b8d --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/data_sources/remote/authentication_firebase_data_source_impl.dart @@ -0,0 +1,110 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +class AuthenticationFirebaseDataSourceImpl + extends AuthenticationRemoteDataSource { + final FirebaseAuth _firebaseAuth; + + AuthenticationFirebaseDataSourceImpl({FirebaseAuth? firebaseAuth}) + : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance; + + Account _mapper(User user) => AccountModel( + uid: user.uid, + email: user.email, + ); + + @override + Future signInWithEmailAndPassword({ + required String email, + required String password, + }) async { + try { + final userCredential = await _firebaseAuth.signInWithEmailAndPassword( + email: email, + password: password, + ); + final user = userCredential.user; + if (user.isNotNull) { + return _mapper(user!); + } else { + throw Exception(); // Get caught just after. + } + } on FirebaseAuthException catch (e) { + throw SignInWithEmailAndPasswordFailureFirebase.fromCode(e.code); + } catch (_) { + throw SignInWithEmailAndPasswordFailureFirebase(); + } + } + + @override + Future signUp({ + required String email, + required String password, + }) async { + try { + final userCredential = await _firebaseAuth.createUserWithEmailAndPassword( + email: email, + password: password, + ); + final user = userCredential.user; + if (user.isNotNull) { + return _mapper(user!); + } else { + throw Exception(); // Get caught just after. + } + } on FirebaseAuthException catch (e) { + throw SignUpWithEmailAndPasswordFailureFirebase.fromCode(e.code); + } catch (_) { + throw SignUpWithEmailAndPasswordFailureFirebase(); + } + } + + @override + Future signOut() async { + try { + await _firebaseAuth.signOut(); + } catch (_) { + throw SignOutFailureFirebase(); + } + } + + @override + Future getIdentityToken() async { + try { + final token = await _firebaseAuth.currentUser?.getIdToken(); + if (token.isNotNull) { + return token!; + } else { + throw Exception(); // Get caught just after. + } + } catch (_) { + // TODO(hpcl): implement a non ambiguous exception for this case + throw ServerException(); + } + } + + @override + Stream streamAccount() => + _firebaseAuth.userChanges().map((user) { + final Account? account = (user.isNotNull) ? _mapper(user!) : null; + return account; + }); +} diff --git a/packages/wyatt_form_bloc/lib/src/enums/set_operations.dart b/packages/wyatt_authentication_bloc/lib/src/data/models/account_model.dart similarity index 74% rename from packages/wyatt_form_bloc/lib/src/enums/set_operations.dart rename to packages/wyatt_authentication_bloc/lib/src/data/models/account_model.dart index fa203b98..0d1d6b65 100644 --- a/packages/wyatt_form_bloc/lib/src/enums/set_operations.dart +++ b/packages/wyatt_authentication_bloc/lib/src/data/models/account_model.dart @@ -14,16 +14,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -enum SetOperation { - /// Replace entire set with new set. - replace, - - /// Keep common elements between sets. - intersection, - - /// Remove common elements between sets. - difference, - - /// Add new elements to set. - union +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; + +class AccountModel implements Account { + @override + final String uid; + + @override + final String? email; + + AccountModel({required this.uid, required this.email}); } diff --git a/packages/wyatt_authentication_bloc/lib/src/data/models/account_wrapper_model.dart b/packages/wyatt_authentication_bloc/lib/src/data/models/account_wrapper_model.dart new file mode 100644 index 00000000..69bffd98 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/models/account_wrapper_model.dart @@ -0,0 +1,27 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; + +class AccountWrapperModel extends AccountWrapper { + @override + final Account? account; + @override + final T? data; + + AccountWrapperModel(this.account, this.data); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/models/models.dart b/packages/wyatt_authentication_bloc/lib/src/data/models/models.dart new file mode 100644 index 00000000..09cc76bf --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/models/models.dart @@ -0,0 +1,18 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'account_model.dart'; +export 'account_wrapper_model.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/data/models/user_firebase.dart b/packages/wyatt_authentication_bloc/lib/src/data/models/user_firebase.dart deleted file mode 100644 index 31139cf3..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/data/models/user_firebase.dart +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/user.dart' as wyatt; - -class UserFirebase implements wyatt.User { - final User? _user; - - const UserFirebase(User user) : _user = user; - - User? get inner => _user; - - @override - const UserFirebase.empty() : _user = null; - - @override - DateTime? get creationTime => _user?.metadata.creationTime; - - @override - String? get displayName => _user?.displayName; - - @override - String? get email => _user?.email; - - @override - bool get emailVerified => _user?.emailVerified ?? false; - - @override - bool get isAnonymous => _user?.isAnonymous ?? false; - - @override - bool get isEmpty => _user == null; - - @override - bool get isNotEmpty => _user != null; - - @override - DateTime? get lastSignInTime => _user?.metadata.lastSignInTime; - - @override - String? get phoneNumber => _user?.phoneNumber; - - @override - String? get photoURL => _user?.photoURL; - - @override - String? get refreshToken => _user?.refreshToken; - - @override - String get uid => _user?.uid ?? ''; - - @override - String? get providerId => _user?.providerData.first.providerId; - - @override - bool? get isNewUser { - if (_user?.metadata.lastSignInTime == null || - _user?.metadata.creationTime == null) { - return null; - } else { - return _user?.metadata.lastSignInTime == _user?.metadata.creationTime; - } - } - - @override - // ignore: lines_longer_than_80_chars - String toString() => 'UserFirebase(creationTime: $creationTime, displayName: $displayName, email: $email, emailVerified: $emailVerified, isAnonymous: $isAnonymous, lastSignInTime: $lastSignInTime, phoneNumber: $phoneNumber, photoURL: $photoURL, refreshToken: $refreshToken, uid: $uid)'; -} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_firebase.dart b/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_firebase.dart deleted file mode 100644 index 0cf6d5dc..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_firebase.dart +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'dart:async'; - -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:flutter_facebook_auth/flutter_facebook_auth.dart'; -import 'package:google_sign_in/google_sign_in.dart'; -import 'package:sign_in_with_apple/sign_in_with_apple.dart'; -import 'package:twitter_login/twitter_login.dart'; -import 'package:wyatt_authentication_bloc/src/core/enum/auth_cubit_status.dart'; -import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions_firebase.dart'; -import 'package:wyatt_authentication_bloc/src/core/extensions/firebase_auth_user_x.dart'; -import 'package:wyatt_authentication_bloc/src/core/utils/cryptography.dart'; -import 'package:wyatt_authentication_bloc/src/data/models/user_firebase.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/user.dart' - as wyatt; -import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; - -class AuthenticationRepositoryFirebase implements AuthenticationRepository { - final _controller = StreamController(); - final FirebaseAuth _firebaseAuth; - final TwitterLogin? _twitterLogin; - - UserFirebase _userCache = const UserFirebase.empty(); - - AuthenticationRepositoryFirebase({ - FirebaseAuth? firebaseAuth, - TwitterLogin? twitterLogin, - }) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance, - _twitterLogin = twitterLogin { - _controller.sink.add(AuthCubitStatus.stoped); - } - - @override - Stream get cubitStatus => - _controller.stream.asBroadcastStream(); - - @override - void changeCubitStatus(AuthCubitStatus status) => - _controller.sink.add(status); - - @override - Stream get user => - _firebaseAuth.userChanges().map((firebaseUser) { - final UserFirebase user = (firebaseUser == null) - ? const UserFirebase.empty() - : firebaseUser.model; - _userCache = user; - return user; - }); - - @override - wyatt.User get currentUser => _userCache; - - @override - Future applyActionCode(String code) async { - try { - await _firebaseAuth.applyActionCode(code); - } on FirebaseAuthException catch (e) { - throw ApplyActionCodeFailureFirebase.fromCode(e.code); - } catch (_) { - throw ApplyActionCodeFailureFirebase(); - } - } - - @override - Future signUp({ - required String email, - required String password, - }) async { - try { - final creds = await _firebaseAuth.createUserWithEmailAndPassword( - email: email, - password: password, - ); - return creds.user?.uid; - } on FirebaseAuthException catch (e) { - throw SignUpWithEmailAndPasswordFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignUpWithEmailAndPasswordFailureFirebase(); - } - } - - @override - Future> fetchSignInMethodsForEmail({ - required String email, - }) async { - try { - return await _firebaseAuth.fetchSignInMethodsForEmail(email); - } on FirebaseAuthException catch (e) { - throw FetchSignInMethodsForEmailFailureFirebase.fromCode(e.code); - } catch (_) { - throw FetchSignInMethodsForEmailFailureFirebase(); - } - } - - @override - Future signInAnonymously() async { - try { - await _firebaseAuth.signInAnonymously(); - } on FirebaseAuthException catch (e) { - throw SignInAnonymouslyFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignInAnonymouslyFailureFirebase(); - } - } - - @override - Future signInWithGoogle() async { - // Trigger the authentication flow - final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn(); - - // Obtain the auth details from the request - final GoogleSignInAuthentication? googleAuth = - await googleUser?.authentication; - - // Create a new credential - final credential = GoogleAuthProvider.credential( - accessToken: googleAuth?.accessToken, - idToken: googleAuth?.idToken, - ); - - try { - await _firebaseAuth.signInWithCredential(credential); - } on FirebaseAuthException catch (e) { - throw SignInWithGoogleFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignInWithGoogleFailureFirebase(); - } - } - - @override - Future signInWithFacebook() async { - // Trigger the sign-in flow - final LoginResult loginResult = await FacebookAuth.instance.login(); - - // Create a credential from the access token - final OAuthCredential credential = - FacebookAuthProvider.credential(loginResult.accessToken?.token ?? ''); - - try { - await _firebaseAuth.signInWithCredential(credential); - } on FirebaseAuthException catch (e) { - throw SignInWithFacebookFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignInWithFacebookFailureFirebase(); - } - } - - @override - Future signInWithApple() async { - // To prevent replay attacks with the credential returned from Apple, we - // include a nonce in the credential request. When signing in with - // Firebase, the nonce in the id token returned by Apple, is expected to - // match the sha256 hash of `rawNonce`. - final rawNonce = Cryptography.generateNonce(); - final nonce = Cryptography.sha256ofString(rawNonce); - - // Request credential for the currently signed in Apple account. - final appleCredential = await SignInWithApple.getAppleIDCredential( - scopes: [ - AppleIDAuthorizationScopes.email, - AppleIDAuthorizationScopes.fullName, - ], - nonce: nonce, - ); - - // Create an `OAuthCredential` from the credential returned by Apple. - final credential = OAuthProvider('apple.com').credential( - idToken: appleCredential.identityToken, - rawNonce: rawNonce, - ); - - // Sign in the user with Firebase. If the nonce we generated earlier does - // not match the nonce in `appleCredential.identityToken`, - // sign in will fail. - try { - await _firebaseAuth.signInWithCredential(credential); - } on FirebaseAuthException catch (e) { - throw SignInWithAppleFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignInWithAppleFailureFirebase(); - } - } - - @override - Future signInWithTwitter() async { - final twitterLogin = _twitterLogin; - if (twitterLogin == null) { - throw SignInWithTwitterFailureFirebase(); - } - - // Trigger the sign-in flow - final authResult = await twitterLogin.login(); - - // Create a credential from the access token - final credential = TwitterAuthProvider.credential( - accessToken: authResult.authToken!, - secret: authResult.authTokenSecret!, - ); - - try { - await _firebaseAuth.signInWithCredential(credential); - } on FirebaseAuthException catch (e) { - throw SignInWithCredentialFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignInWithCredentialFailureFirebase(); - } - } - - @override - Future signInWithEmailLink(String email, String emailLink) async { - try { - await _firebaseAuth.signInWithEmailLink( - email: email, - emailLink: emailLink, - ); - } on FirebaseAuthException catch (e) { - throw SignInWithEmailLinkFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignInWithEmailLinkFailureFirebase(); - } - } - - @override - Future signInWithEmailAndPassword({ - required String email, - required String password, - }) async { - try { - await _firebaseAuth.signInWithEmailAndPassword( - email: email, - password: password, - ); - } on FirebaseAuthException catch (e) { - throw SignInWithEmailAndPasswordFailureFirebase.fromCode(e.code); - } catch (_) { - throw SignInWithEmailAndPasswordFailureFirebase(); - } - } - - @override - Future sendEmailVerification() async { - try { - await _userCache.inner!.sendEmailVerification(); - } catch (e) { - throw SendEmailVerificationFailureFirebase(); - } - } - - @override - Future sendPasswordResetEmail({required String email}) async { - try { - await _firebaseAuth.sendPasswordResetEmail(email: email); - } on FirebaseAuthException catch (e) { - throw SendPasswordResetEmailFailureFirebase.fromCode(e.code); - } catch (_) { - throw SendPasswordResetEmailFailureFirebase(); - } - } - - @override - Future sendSignInLinkEmail({required String email}) async { - try { - // TODO(hpcl): implement sendSignInLinkEmail - } on FirebaseAuthException catch (e) { - throw SendSignInLinkEmailFailureFirebase.fromCode(e.code); - } catch (_) { - throw SendSignInLinkEmailFailureFirebase(); - } - } - - @override - Future confirmPasswordReset({ - required String code, - required String newPassword, - }) async { - try { - await _firebaseAuth.confirmPasswordReset( - code: code, - newPassword: newPassword, - ); - } on FirebaseAuthException catch (e) { - throw ConfirmPasswordResetFailureFirebase.fromCode(e.code); - } catch (_) { - throw ConfirmPasswordResetFailureFirebase(); - } - throw UnimplementedError(); - } - - @override - Future verifyPasswordResetCode({required String code}) async { - try { - await _firebaseAuth.verifyPasswordResetCode(code); - } on FirebaseAuthException catch (e) { - throw VerifyPasswordResetCodeFailureFirebase.fromCode(e.code); - } catch (_) { - throw VerifyPasswordResetCodeFailureFirebase(); - } - } - - @override - Future signOut() async { - try { - await Future.wait([ - _firebaseAuth.signOut(), - ]); - _userCache = const UserFirebase.empty(); - } catch (_) { - throw SignOutFailureFirebase(); - } - } - - @override - Future refresh() async { - try { - await _userCache.inner!.reload(); - } on FirebaseAuthException catch (e) { - throw RefreshFailureFirebase.fromCode(e.code); - } catch (_) { - throw RefreshFailureFirebase(); - } - } -} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart b/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart new file mode 100644 index 00000000..00bf067c --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/repositories/authentication_repository_impl.dart @@ -0,0 +1,211 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart'; +import 'package:wyatt_authentication_bloc/src/data/models/account_wrapper_model.dart'; +import 'package:wyatt_authentication_bloc/src/domain/data_sources/local/authentication_cache_data_source.dart'; +import 'package:wyatt_authentication_bloc/src/domain/data_sources/remote/authentication_remote_data_source.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; +import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +typedef OnSignUpSuccess = FutureResult Function( + Account? account, + WyattForm form, +); + +typedef OnAuthChange = FutureResult Function(Account? account); + +class AuthenticationRepositoryImpl + extends AuthenticationRepository { + final AuthenticationCacheDataSource _authenticationLocalDataSource; + final AuthenticationRemoteDataSource _authenticationRemoteDataSource; + + late FormRepository _formRepository; + + final OnSignUpSuccess? _onSignUpSuccess; + + final OnAuthChange? _onAccountChanges; + + AuthenticationRepositoryImpl({ + required AuthenticationCacheDataSource authenticationCacheDataSource, + required AuthenticationRemoteDataSource authenticationRemoteDataSource, + FormRepository? formRepository, + // ignore: strict_raw_type + List? extraSignUpInputs, + OnSignUpSuccess? onSignUpSuccess, + OnAuthChange? onAuthChange, + }) : _authenticationLocalDataSource = authenticationCacheDataSource, + _authenticationRemoteDataSource = authenticationRemoteDataSource, + _onSignUpSuccess = onSignUpSuccess, + _onAccountChanges = onAuthChange { + _formRepository = formRepository ?? FormRepositoryImpl(); + if (formRepository != null) { + return; + } + _formRepository + ..registerForm( + WyattFormImpl( + [ + FormInput(AuthFormField.email, const Email.pure()), + FormInput(AuthFormField.password, const Password.pure()) + ], + name: AuthFormName.signInForm, + ), + ) + ..registerForm( + WyattFormImpl( + [ + FormInput(AuthFormField.email, const Email.pure()), + FormInput(AuthFormField.password, const Password.pure()), + ...extraSignUpInputs ?? [] + ], + name: AuthFormName.signUpForm, + ), + ); + } + + @override + FormRepository get formRepository => _formRepository; + + @override + FutureResult signInWithEmailAndPassword({ + required String email, + required String password, + }) => + Result.tryCatchAsync( + () async { + final account = + await _authenticationRemoteDataSource.signInWithEmailAndPassword( + email: email, + password: password, + ); + await _authenticationLocalDataSource.storeAccount(account); + return account; + }, + (error) => error, + ); + + @override + FutureResult signOut() => + Result.tryCatchAsync( + () async { + await _authenticationRemoteDataSource.signOut(); + await _authenticationLocalDataSource.destroy(); + }, + (error) => error, + ); + + @override + FutureResult signUp({ + required String email, + required String password, + }) => + Result.tryCatchAsync( + () async { + final account = await _authenticationRemoteDataSource.signUp( + email: email, + password: password, + ); + await _authenticationLocalDataSource.storeAccount(account); + if (_onSignUpSuccess.isNotNull) { + final dataResult = await _onSignUpSuccess!.call( + account, + _formRepository.accessForm(AuthFormName.signUpForm).clone(), + ); + await dataResult.foldAsync( + _authenticationLocalDataSource.storeData, + (error) => throw error, + ); + } + return account; + }, + (error) => error, + ); + + @override + FutureResult destroyCache() => + Result.tryCatchAsync( + _authenticationLocalDataSource.destroy, + (error) => error, + ); + + @override + FutureResult> getCache() => + Result.tryCatchAsync, AppException, AppException>( + _authenticationLocalDataSource.load, + (error) => error, + ); + + @override + FutureResult getAccount() => + Result.tryCatchAsync( + _authenticationLocalDataSource.loadAccount, + (error) => error, + ); + + @override + FutureResult setAccount( + Account account, + ) => + Result.tryCatchAsync( + () async { + await _authenticationLocalDataSource.storeAccount(account); + }, + (error) => error, + ); + + @override + FutureResult getData() => + Result.tryCatchAsync( + _authenticationLocalDataSource.loadData, + (error) => error, + ); + + @override + FutureResult setData( + T? data, + ) => + Result.tryCatchAsync( + () async { + await _authenticationLocalDataSource.storeData(data); + }, + (error) => error, + ); + + @override + FutureResult getIdentityToken() => + Result.tryCatchAsync( + _authenticationRemoteDataSource.getIdentityToken, + (error) => error, + ); + + @override + Stream>> streamAccount() => + _authenticationRemoteDataSource.streamAccount().map((account) async { + if (_onAccountChanges.isNotNull) { + final dataResult = await _onAccountChanges!.call(account); + return dataResult.map((data) => AccountWrapperModel(account, data)); + } + return Ok, AppException>( + AccountWrapperModel(account, null), + ); + }); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/data/repositories/repositories.dart b/packages/wyatt_authentication_bloc/lib/src/data/repositories/repositories.dart new file mode 100644 index 00000000..7858c9e7 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/data/repositories/repositories.dart @@ -0,0 +1,17 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'authentication_repository_impl.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/data_sources.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/data_sources.dart new file mode 100644 index 00000000..11efe02d --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/data_sources.dart @@ -0,0 +1,18 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'local/authentication_cache_data_source.dart'; +export 'remote/authentication_remote_data_source.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_cache_data_source.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_cache_data_source.dart new file mode 100644 index 00000000..c4d357e5 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/local/authentication_cache_data_source.dart @@ -0,0 +1,29 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; + +abstract class AuthenticationCacheDataSource + extends BaseLocalDataSource { + Future storeAccount(Account? account); + Future storeData(T? data); + Future loadAccount(); + Future loadData(); + Future> load(); + Future destroy(); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/remote/authentication_remote_data_source.dart b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/remote/authentication_remote_data_source.dart new file mode 100644 index 00000000..3bd615e1 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/data_sources/remote/authentication_remote_data_source.dart @@ -0,0 +1,36 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; + +abstract class AuthenticationRemoteDataSource extends BaseRemoteDataSource { + Future signUp({ + required String email, + required String password, + }); + + Future signInWithEmailAndPassword({ + required String email, + required String password, + }); + + Future signOut(); + + Stream streamAccount(); + + Future getIdentityToken(); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/domain.dart b/packages/wyatt_authentication_bloc/lib/src/domain/domain.dart new file mode 100644 index 00000000..7727f7ee --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/domain.dart @@ -0,0 +1,19 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'data_sources/data_sources.dart'; +export 'entities/entities.dart'; +export 'repositories/repositories.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/account.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/account.dart new file mode 100644 index 00000000..97d5deeb --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/account.dart @@ -0,0 +1,27 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; + +abstract class Account extends Entity { + /// The user's unique ID. + String get uid; + + /// The users email address. + /// + /// Will be `null` if signing in anonymously. + String? get email; +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/account_wrapper.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/account_wrapper.dart new file mode 100644 index 00000000..1e1f0034 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/account_wrapper.dart @@ -0,0 +1,23 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; + +abstract class AccountWrapper extends Entity { + Account? get account; + T? get data; +} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/entities.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/entities.dart new file mode 100644 index 00000000..8ecf9215 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/entities/entities.dart @@ -0,0 +1,18 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'account.dart'; +export 'account_wrapper.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/entities/user.dart b/packages/wyatt_authentication_bloc/lib/src/domain/entities/user.dart deleted file mode 100644 index 40c0c7b9..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/domain/entities/user.dart +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -abstract class User { - /// The empty user constructor. - const User.empty(); - - /// The users display name. - /// - /// Will be `null` if signing in anonymously or via password authentication. - String? get displayName; - - /// The users email address. - /// - /// Will be `null` if signing in anonymously. - String? get email; - - /// Returns whether the users email address has been verified. - /// - /// To send a verification email, see `SendEmailVerification`. - /// - /// Once verified, call `reload` to ensure the latest user information is - /// retrieved from Firebase. - bool get emailVerified; - - /// Returns whether the user is a anonymous. - bool get isAnonymous; - - /// Returns the users account creation time. - /// - /// When this account was created as dictated by the server clock. - DateTime? get creationTime; - - /// When the user last signed in as dictated by the server clock. - /// - /// This is only accurate up to a granularity of 2 minutes for consecutive - /// sign-in attempts. - DateTime? get lastSignInTime; - - /// Returns the users phone number. - /// - /// This property will be `null` if the user has not signed in or been has - /// their phone number linked. - String? get phoneNumber; - - /// Returns a photo URL for the user. - /// - /// This property will be populated if the user has signed in or been linked - /// with a 3rd party OAuth provider (such as Google). - String? get photoURL; - - /// Returns a JWT refresh token for the user. - /// - /// This property maybe `null` or empty if the underlying platform does not - /// support providing refresh tokens. - String? get refreshToken; - - /// The user's unique ID. - String get uid; - - /// The provider ID for the user. - String? get providerId; - - /// Whether the user account has been recently created. - bool? get isNewUser; - - /// Convenience getter to determine whether the current user is empty. - bool get isEmpty; - - /// Convenience getter to determine whether the current user is not empty. - bool get isNotEmpty; -} diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart index 35c80a72..cece19c9 100644 --- a/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart +++ b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/authentication_repository.dart @@ -14,126 +14,36 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_authentication_bloc/src/core/enum/auth_cubit_status.dart'; -import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/user.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; -/// {@template authentication_repository} -/// Repository which manages user authentication. -/// {@endtemplate} -abstract class AuthenticationRepository { - /// Stream of [AuthCubitStatus] wich will emit the current cubit status. - Stream get cubitStatus; +abstract class AuthenticationRepository extends BaseRepository { + FormRepository get formRepository; - /// Changes cubit status.(Useful to start or stop the engine.) - void changeCubitStatus(AuthCubitStatus status); - - /// Stream of [User] which will emit the current user when - /// the authentication state changes. - /// - /// Emits [User.empty] if the user is not authenticated. - Stream get user; - - /// Returns the current cached account. - /// Defaults to [User.empty] if there is no cached user. - User get currentUser; - - /// Applies action code - /// - /// [code] - The action code sent to the user's email address. - /// Throw [ApplyActionCodeFailureInterface] if an exception occurs. - Future applyActionCode(String code); - - /// Creates a new user with the provided [email] and [password]. - /// - /// Returns the newly created user's unique identifier. - /// - /// Throws a [SignUpWithEmailAndPasswordFailureInterface] if - /// an exception occurs. - Future signUp({required String email, required String password}); - - /// Fetches sign in methods for [email]. - /// - /// Throws a [FetchSignInMethodsForEmailFailureInterface] if - /// an exception occurs. - Future> fetchSignInMethodsForEmail({required String email}); - - /// Sign in anonimously. - /// - /// Throws a [SignInAnonymouslyFailureInterface] if an exception occurs. - Future signInAnonymously(); - - /// Starts the Sign In with Google Flow. - /// - /// Throws a [SignInWithGoogleFailureInterface] if an exception occurs. - Future signInWithGoogle(); - - /// Starts the Sign In with Facebook Flow. - /// - /// Throws a [SignInWithFacebookFailureInterface] if an exception occurs. - Future signInWithFacebook(); - - /// Starts the Sign In with Apple Flow. - /// - /// Throws a [SignInWithAppleFailureInterface] if an exception occurs. - Future signInWithApple(); - - /// Starts the Sign In with Twitter Flow. - /// - /// Throws a [SignInWithTwitterFailureInterface] if an exception occurs. - Future signInWithTwitter(); - - /// Signs in using an email address and email sign-in link. - /// - /// Throws a [SignInWithEmailLinkFailureInterface] if an exception occurs. - Future signInWithEmailLink( - String email, - String emailLink, - ); - - /// Signs in with the provided [email] and [password]. - /// - /// Throws a [SignInWithEmailAndPasswordFailureInterface] if - /// an exception occurs. - Future signInWithEmailAndPassword({ + FutureResult signUp({ required String email, required String password, }); - /// Sends verification email to the provided [user]. - /// - /// Throws a [SendEmailVerificationFailureInterface] if an exception occurs. - Future sendEmailVerification(); - - /// Sends a password reset email to the provided [email]. - /// - /// Throws a [SendPasswordResetEmailFailureInterface] if an exception occurs. - Future sendPasswordResetEmail({required String email}); - - /// Sends link to login. - /// - /// Throws a [SendSignInLinkEmailFailureInterface] if an exception occurs. - Future sendSignInLinkEmail({required String email}); - - /// Confirms the password reset with the provided [newPassword] and [code]. - /// - /// Throws a [ConfirmPasswordResetFailureInterface] if an exception occurs. - Future confirmPasswordReset({ - required String code, - required String newPassword, + FutureResult signInWithEmailAndPassword({ + required String email, + required String password, }); - /// Verify password reset code. - /// - /// Throws a [VerifyPasswordResetCodeFailureInterface] if an exception occurs. - Future verifyPasswordResetCode({required String code}); + FutureResult signOut(); - /// Signs out the current user which will emit - /// [User.empty] from the [user] Stream. - Future signOut(); + Stream>> streamAccount(); - /// Refreshes the current user. - /// - /// Throws a [RefreshFailureInterface] if an exception occurs. - Future refresh(); + FutureResult getIdentityToken(); + + FutureResult getAccount(); + FutureResult setAccount(Account account); + + FutureResult getData(); + FutureResult setData(T? data); + + FutureResult> getCache(); + FutureResult destroyCache(); } diff --git a/packages/wyatt_authentication_bloc/lib/src/domain/repositories/repositories.dart b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/repositories.dart new file mode 100644 index 00000000..85f8ae88 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/domain/repositories/repositories.dart @@ -0,0 +1,17 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'authentication_repository.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/features/authentication/builder/authentication_builder.dart b/packages/wyatt_authentication_bloc/lib/src/features/authentication/builder/authentication_builder.dart index f10c88c3..4a19e6a9 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/authentication/builder/authentication_builder.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/authentication/builder/authentication_builder.dart @@ -16,7 +16,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/user.dart'; +import 'package:wyatt_authentication_bloc/src/core/enums/authentication_status.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; import 'package:wyatt_authentication_bloc/src/features/authentication/cubit/authentication_cubit.dart'; class AuthenticationBuilder extends StatelessWidget { @@ -29,8 +30,7 @@ class AuthenticationBuilder extends StatelessWidget { final Widget Function( BuildContext context, - User user, - Extra? extra, + AccountWrapper accountWrapper, ) authenticated; final Widget Function(BuildContext context) unauthenticated; final Widget Function(BuildContext context) unknown; @@ -40,8 +40,8 @@ class AuthenticationBuilder extends StatelessWidget { BlocBuilder, AuthenticationState>( builder: (context, state) { if (state.status == AuthenticationStatus.authenticated) { - if (state.user != null) { - return authenticated(context, state.user!, state.extra); + if (state.accountWrapper != null) { + return authenticated(context, state.accountWrapper!); } else { return unauthenticated(context); } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_cubit.dart index 95ae5a59..af9cb0b0 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_cubit.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_cubit.dart @@ -18,83 +18,46 @@ import 'dart:async'; import 'package:equatable/equatable.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_authentication_bloc/src/core/enum/auth_cubit_status.dart'; -import 'package:wyatt_authentication_bloc/src/domain/entities/user.dart'; +import 'package:wyatt_authentication_bloc/src/core/enums/authentication_status.dart'; +import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart'; import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; part 'authentication_state.dart'; class AuthenticationCubit extends Cubit> { - final AuthenticationRepository _authenticationRepository; - late final StreamSubscription _statusSubscription; - - StreamSubscription? _userSubscription; - - final Future Function(User user)? _onAuthSuccess; + final AuthenticationRepository _authenticationRepository; AuthenticationCubit({ - required AuthenticationRepository authenticationRepository, - Future Function(User user)? onAuthSuccess, + required AuthenticationRepository authenticationRepository, }) : _authenticationRepository = authenticationRepository, - _onAuthSuccess = onAuthSuccess, super(const AuthenticationState.unknown()) { - _subscribeStatus(); + _listenForAuthenticationChanges(); } - Future get status async => - _authenticationRepository.cubitStatus.last; - - void _subscribeStatus() { - try { - _statusSubscription = _authenticationRepository.cubitStatus.listen( - (status) { - switch (status) { - case AuthCubitStatus.started: - start(); - break; - case AuthCubitStatus.stoped: - stop(); - break; + void _listenForAuthenticationChanges() { + _authenticationRepository.streamAccount().listen((accountFutureResult) { + accountFutureResult.fold( + (value) { + if (value.account.isNotNull) { + emit(AuthenticationState.authenticated(value)); + return; } + _authenticationRepository.destroyCache(); + emit(const AuthenticationState.unauthenticated()); + return; + }, + (error) { + _authenticationRepository.destroyCache(); + emit(const AuthenticationState.unauthenticated()); + return; }, ); - } catch (_) {} + }); } - Future init() async { - final firstUser = await _authenticationRepository.user.first; - _authenticationRepository.changeCubitStatus(AuthCubitStatus.started); - return changeStatus(firstUser); - } - - bool start() { - _userSubscription = _authenticationRepository.user.listen(changeStatus); - return true; - } - - bool stop() { - _userSubscription?.cancel(); - return true; - } - - Future changeStatus(User user) async { - if (user.isNotEmpty) { - final Extra? extra = await _onAuthSuccess?.call(user); - emit(AuthenticationState.authenticated(user, extra)); - } else { - _authenticationRepository.changeCubitStatus(AuthCubitStatus.stoped); - emit(const AuthenticationState.unauthenticated()); - } - } - - void logOut() { - unawaited(_authenticationRepository.signOut()); - } - - @override - Future close() { - _userSubscription?.cancel(); - _statusSubscription.cancel(); - return super.close(); + FutureOr signOut() { + // TODO(hpcl): maybe force unauthenticated by emitting an event + _authenticationRepository.signOut(); } } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_state.dart index d01fdfb7..0a3bc98e 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_state.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/authentication/cubit/authentication_state.dart @@ -16,42 +16,28 @@ part of 'authentication_cubit.dart'; -enum AuthenticationStatus { - unknown, - authenticated, - unauthenticated, -} - class AuthenticationState extends Equatable { final AuthenticationStatus status; - final User? user; - final Extra? extra; + final AccountWrapper? accountWrapper; - const AuthenticationState._({ - required this.status, - this.user, - this.extra, - }); + const AuthenticationState._({required this.status, this.accountWrapper}); const AuthenticationState.unknown() : this._(status: AuthenticationStatus.unknown); - const AuthenticationState.authenticated( - User user, - Extra? extra, - ) : this._( + const AuthenticationState.authenticated(AccountWrapper accountWrapper) + : this._( status: AuthenticationStatus.authenticated, - user: user, - extra: extra, + accountWrapper: accountWrapper, ); const AuthenticationState.unauthenticated() : this._(status: AuthenticationStatus.unauthenticated); @override - List get props => [status, user, extra]; + List get props => [status]; @override String toString() => - 'AuthenticationState(status: $status, user: $user, extra: $extra)'; + 'AuthenticationState(status: $status, accountWrapper: $accountWrapper)'; } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_cubit.dart deleted file mode 100644 index 2ef607a0..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_cubit.dart +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:equatable/equatable.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; -import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; -import 'package:wyatt_form_bloc/wyatt_form_bloc.dart' show FormStatus; - -part 'email_verification_state.dart'; - -class EmailVerificationCubit extends Cubit { - final AuthenticationRepository _authenticationRepository; - - EmailVerificationCubit({ - required AuthenticationRepository authenticationRepository, - }) : _authenticationRepository = authenticationRepository, - super(const EmailVerificationState()); - - Future sendEmailVerification() async { - emit(state.copyWith(status: FormStatus.submissionInProgress)); - try { - await _authenticationRepository.sendEmailVerification(); - emit(state.copyWith(status: FormStatus.submissionSuccess)); - } on SendEmailVerificationFailureInterface catch (e) { - emit( - state.copyWith( - errorMessage: e.message, - status: FormStatus.submissionFailure, - ), - ); - } catch (_) { - emit(state.copyWith(status: FormStatus.submissionFailure)); - } - } - - Future checkEmailVerification() async { - emit(state.copyWith(status: FormStatus.submissionInProgress)); - try { - await _authenticationRepository.refresh(); - emit( - state.copyWith( - isVerified: _authenticationRepository.currentUser.emailVerified, - status: FormStatus.submissionSuccess, - ), - ); - } on RefreshFailureInterface catch (e) { - emit( - state.copyWith( - errorMessage: e.message, - status: FormStatus.submissionFailure, - ), - ); - } catch (_) { - emit(state.copyWith(status: FormStatus.submissionFailure)); - } - } -} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/features.dart b/packages/wyatt_authentication_bloc/lib/src/features/features.dart new file mode 100644 index 00000000..e1b478e9 --- /dev/null +++ b/packages/wyatt_authentication_bloc/lib/src/features/features.dart @@ -0,0 +1,19 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'authentication/authentication.dart'; +export 'sign_in/sign_in.dart'; +export 'sign_up/sign_up.dart'; diff --git a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_cubit.dart deleted file mode 100644 index 66ab6545..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_cubit.dart +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:equatable/equatable.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; -import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; -import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; - -part 'password_reset_state.dart'; - -class PasswordResetCubit extends Cubit { - final AuthenticationRepository _authenticationRepository; - - final FormValidator _validationStrategy; - - PasswordResetCubit({ - required AuthenticationRepository authenticationRepository, - FormValidator validationStrategy = const EveryInputValidator(), - }) : _authenticationRepository = authenticationRepository, - _validationStrategy = validationStrategy, - super(const PasswordResetState()); - - void emailChanged(String value) { - final Email email = Email.dirty(value); - emit( - state.copyWith( - email: email, - status: _validationStrategy.rawValidate([email]), - ), - ); - } - - Future sendPasswordResetEmail() async { - if (!state.status.isValidated) { - return; - } - emit(state.copyWith(status: FormStatus.submissionInProgress)); - try { - await _authenticationRepository.sendPasswordResetEmail( - email: state.email.value, - ); - emit(state.copyWith(status: FormStatus.submissionSuccess)); - } on SendPasswordResetEmailFailureInterface catch (e) { - emit( - state.copyWith( - errorMessage: e.message, - status: FormStatus.submissionFailure, - ), - ); - } catch (_) { - emit(state.copyWith(status: FormStatus.submissionFailure)); - } - } -} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_state.dart deleted file mode 100644 index e8100c8e..00000000 --- a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/cubit/password_reset_state.dart +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -part of 'password_reset_cubit.dart'; - -class PasswordResetState extends Equatable { - final Email email; - final FormStatus status; - final String? errorMessage; - - const PasswordResetState({ - this.email = const Email.pure(), - this.status = FormStatus.pure, - this.errorMessage, - }); - - PasswordResetState copyWith({ - Email? email, - FormStatus? status, - String? errorMessage, - }) => PasswordResetState( - email: email ?? this.email, - status: status ?? this.status, - errorMessage: errorMessage ?? this.errorMessage, - ); - - @override - List get props => [email, status]; -} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart index 2891dc57..b8cc1358 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_cubit.dart @@ -14,112 +14,132 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:equatable/equatable.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_authentication_bloc/src/core/enum/auth_cubit_status.dart'; -import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; +import 'dart:async'; + +import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart'; import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; part 'sign_in_state.dart'; -class SignInCubit extends Cubit { - final AuthenticationRepository _authenticationRepository; - - final FormValidator _validationStrategy; +class SignInCubit extends FormDataCubit { + final AuthenticationRepository _authenticationRepository; + FormRepository get _formRepository => + _authenticationRepository.formRepository; SignInCubit({ - required AuthenticationRepository authenticationRepository, - FormValidator validationStrategy = const EveryInputValidator(), + required AuthenticationRepository authenticationRepository, }) : _authenticationRepository = authenticationRepository, - _validationStrategy = validationStrategy, - super(const SignInState()); + super( + SignInState( + form: authenticationRepository.formRepository + .accessForm(AuthFormName.signInForm), + ), + ); + + @override + String get formName => AuthFormName.signInForm; void emailChanged(String value) { final Email email = Email.dirty(value); - emit( - state.copyWith( - email: email, - status: _validationStrategy.rawValidate([email, state.password]), - ), - ); + dataChanged(AuthFormField.email, email); } void passwordChanged(String value) { final Password password = Password.dirty(value); + dataChanged(AuthFormField.password, password); + } + + @override + FutureOr dataChanged( + String key, + FormInputValidator dirtyValue, + ) { + final form = _formRepository.accessForm(formName).clone(); + + try { + form.updateValidator(key, dirtyValue); + _formRepository.updateForm(form); + } catch (e) { + rethrow; + } + emit( - state.copyWith( - password: password, - status: _validationStrategy.rawValidate([state.email, password]), + state.copyWith(form: form, status: form.validate()), + ); + } + + @override + FutureOr reset() { + final form = state.form.reset(); + _formRepository.updateForm(form); + emit( + state.copyWith(form: form, status: form.validate()), + ); + } + + @override + FutureOr submit() async { + if (!state.status.isValidated) { + return; + } + + emit(state.copyWith(status: FormStatus.submissionInProgress)); + + final form = _formRepository.accessForm(formName); + final email = form.valueOf(AuthFormField.email); + final password = form.valueOf(AuthFormField.password); + + if (email.isNullOrEmpty || password.isNullOrEmpty) { + emit( + state.copyWith( + errorMessage: 'An error occured while retrieving data from the form.', + status: FormStatus.submissionFailure, + ), + ); + } + + final uid = await _authenticationRepository.signInWithEmailAndPassword( + email: email!, + password: password!, + ); + + emit( + uid.fold( + (value) => state.copyWith(status: FormStatus.submissionSuccess), + (error) => state.copyWith( + errorMessage: error.message, + status: FormStatus.submissionFailure, + ), ), ); } - Future signInAnonymously() async { - if (state.status.isSubmissionInProgress) { - return; - } + @override + FutureOr update( + WyattForm form, { + SetOperation operation = SetOperation.replace, + }) { + final WyattForm current = _formRepository.accessForm(formName).clone(); + final WyattForm newForm = operation.operation.call(current, form); + _formRepository.updateForm(newForm); - emit(state.copyWith(status: FormStatus.submissionInProgress)); - try { - await _authenticationRepository.signInAnonymously(); - _authenticationRepository.changeCubitStatus(AuthCubitStatus.started); - emit(state.copyWith(status: FormStatus.submissionSuccess)); - } on SignInAnonymouslyFailureInterface catch (e) { - emit( - state.copyWith( - errorMessage: e.message, - status: FormStatus.submissionFailure, - ), - ); - } catch (_) { - emit(state.copyWith(status: FormStatus.submissionFailure)); - } + emit( + state.copyWith( + form: newForm, + status: newForm.validate(), + ), + ); } - Future signInWithGoogle() async { - if (state.status.isSubmissionInProgress) { - return; - } - - emit(state.copyWith(status: FormStatus.submissionInProgress)); - try { - await _authenticationRepository.signInWithGoogle(); - _authenticationRepository.changeCubitStatus(AuthCubitStatus.started); - emit(state.copyWith(status: FormStatus.submissionSuccess)); - } on SignInWithGoogleFailureInterface catch (e) { - emit( - state.copyWith( - errorMessage: e.message, - status: FormStatus.submissionFailure, - ), - ); - } catch (_) { - emit(state.copyWith(status: FormStatus.submissionFailure)); - } - } - - Future signInWithEmailAndPassword() async { - if (!state.status.isValidated) { - return; - } - emit(state.copyWith(status: FormStatus.submissionInProgress)); - try { - await _authenticationRepository.signInWithEmailAndPassword( - email: state.email.value, - password: state.password.value, - ); - _authenticationRepository.changeCubitStatus(AuthCubitStatus.started); - emit(state.copyWith(status: FormStatus.submissionSuccess)); - } on SignInWithEmailAndPasswordFailureInterface catch (e) { - emit( - state.copyWith( - errorMessage: e.message, - status: FormStatus.submissionFailure, - ), - ); - } catch (_) { - emit(state.copyWith(status: FormStatus.submissionFailure)); - } + @override + FutureOr validate() { + emit( + state.copyWith( + status: _formRepository.accessForm(formName).validate(), + ), + ); } } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_state.dart index 0e407276..85e4edb1 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_state.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/cubit/sign_in_state.dart @@ -16,28 +16,23 @@ part of 'sign_in_cubit.dart'; -class SignInState extends Equatable { - final Email email; - final Password password; - final FormStatus status; - final String? errorMessage; +class SignInState extends FormDataState { + Email get email => form.validatorOf(AuthFormField.email); + Password get password => form.validatorOf(AuthFormField.password); const SignInState({ - this.email = const Email.pure(), - this.password = const Password.pure(), - this.status = FormStatus.pure, - this.errorMessage, + required super.form, + super.status = FormStatus.pure, + super.errorMessage, }); SignInState copyWith({ - Email? email, - Password? password, + WyattForm? form, FormStatus? status, String? errorMessage, }) => SignInState( - email: email ?? this.email, - password: password ?? this.password, + form: form ?? this.form, status: status ?? this.status, errorMessage: errorMessage ?? this.errorMessage, ); @@ -46,10 +41,6 @@ class SignInState extends Equatable { List get props => [email, password, status]; @override - String toString() => ''' - email: $email, - password: $password, - status: $status, - errorMessage: $errorMessage, - '''; + String toString() => 'SignInState(status: ${status.name} ' + '${(errorMessage != null) ? " [$errorMessage]" : ""}, $form)'; } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/sign_in.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/sign_in.dart index 77700ab6..ea803529 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_in/sign_in.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_in/sign_in.dart @@ -1,16 +1,16 @@ // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with this program. If not, see . diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart index 3e79b7a8..9abdf146 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_cubit.dart @@ -16,152 +16,130 @@ import 'dart:async'; -import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wyatt_authentication_bloc/src/core/enum/auth_cubit_status.dart'; -import 'package:wyatt_authentication_bloc/src/core/exceptions/exceptions.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_field.dart'; +import 'package:wyatt_authentication_bloc/src/core/constants/form_name.dart'; import 'package:wyatt_authentication_bloc/src/domain/repositories/authentication_repository.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; part 'sign_up_state.dart'; -class SignUpCubit extends Cubit { - final AuthenticationRepository _authenticationRepository; - - final Future Function(SignUpState state, String? uid)? _onSignUpSuccess; - final FormValidator _validationStrategy; +class SignUpCubit extends FormDataCubit { + final AuthenticationRepository _authenticationRepository; + FormRepository get _formRepository => + _authenticationRepository.formRepository; SignUpCubit({ - required AuthenticationRepository authenticationRepository, - required FormData formData, - FormValidator validationStrategy = const EveryInputValidator(), - Future Function(SignUpState state, String? uid)? onSignUpSuccess, + required AuthenticationRepository authenticationRepository, }) : _authenticationRepository = authenticationRepository, - _onSignUpSuccess = onSignUpSuccess, - _validationStrategy = validationStrategy, - super(SignUpState(data: formData)); + super( + SignUpState( + form: authenticationRepository.formRepository + .accessForm(AuthFormName.signUpForm), + ), + ); + + @override + String get formName => AuthFormName.signUpForm; void emailChanged(String value) { final Email email = Email.dirty(value); - - final List> toValidate = [ - email, - state.password, - ...state.data.validators(), - ]; - - emit( - state.copyWith( - email: email, - status: _validationStrategy.rawValidate(toValidate), - ), - ); + dataChanged(AuthFormField.email, email); } void passwordChanged(String value) { final Password password = Password.dirty(value); - - final List> toValidate = [ - state.email, - password, - ...state.data.validators(), - ]; - - emit( - state.copyWith( - password: password, - status: _validationStrategy.rawValidate(toValidate), - ), - ); + dataChanged(AuthFormField.password, password); } - // Take from wyatt_form_bloc/wyatt_form_bloc.dart - void dataChanged( - String field, - FormInputValidator dirtyValue, + @override + FutureOr dataChanged( + String key, + FormInputValidator dirtyValue, ) { - final form = state.data.clone(); + final form = _formRepository.accessForm(formName).clone(); - if (form.contains(field)) { - form.updateValidator(field, dirtyValue); - } else { - throw Exception('Form field $field not found'); + try { + form.updateValidator(key, dirtyValue); + _formRepository.updateForm(form); + } catch (e) { + rethrow; } emit( - state.copyWith( - data: form, - status: _validationStrategy.rawValidate( - [ - state.email, - state.password, - ...state.data.validators(), - ], - ), - ), + state.copyWith(form: form, status: form.validate()), ); } - // Take from wyatt_form_bloc/wyatt_form_bloc.dart - void updateFormData( - FormData data, { - SetOperation operation = SetOperation.replace, - }) { - FormData form = data; - - switch (operation) { - case SetOperation.replace: - form = data; - break; - case SetOperation.difference: - form = state.data.difference(data); - break; - case SetOperation.intersection: - form = state.data.intersection(data); - break; - case SetOperation.union: - form = state.data.union(data); - break; - } - + @override + FutureOr reset() { + final form = state.form.reset(); + _formRepository.updateForm(form); emit( - state.copyWith( - data: form, - status: _validationStrategy.rawValidate( - [ - state.email, - state.password, - ...state.data.validators(), - ], - ), - ), + state.copyWith(form: form, status: form.validate()), ); } - Future signUpFormSubmitted() async { + @override + FutureOr submit() async { if (!state.status.isValidated) { return; } + emit(state.copyWith(status: FormStatus.submissionInProgress)); - try { - final uid = await _authenticationRepository.signUp( - email: state.email.value, - password: state.password.value, - ); - await _onSignUpSuccess?.call(state, uid); - _authenticationRepository.changeCubitStatus(AuthCubitStatus.started); - emit(state.copyWith(status: FormStatus.submissionSuccess)); - } on SignUpWithEmailAndPasswordFailureInterface catch (e) { + + final form = _formRepository.accessForm(formName); + final email = form.valueOf(AuthFormField.email); + final password = form.valueOf(AuthFormField.password); + + if (email.isNullOrEmpty || password.isNullOrEmpty) { emit( state.copyWith( - errorMessage: e.message, + errorMessage: 'An error occured while retrieving data from the form.', status: FormStatus.submissionFailure, ), ); - } catch (e) { - debugPrint(e.toString()); - emit(state.copyWith(status: FormStatus.submissionFailure)); } + + final uid = await _authenticationRepository.signUp( + email: email!, + password: password!, + ); + + emit( + uid.fold( + (value) => state.copyWith(status: FormStatus.submissionSuccess), + (error) => state.copyWith( + errorMessage: error.message, + status: FormStatus.submissionFailure, + ), + ), + ); + } + + @override + FutureOr update( + WyattForm form, { + SetOperation operation = SetOperation.replace, + }) { + final WyattForm current = _formRepository.accessForm(formName).clone(); + final WyattForm newForm = operation.operation.call(current, form); + _formRepository.updateForm(newForm); + + emit( + state.copyWith( + form: newForm, + status: newForm.validate(), + ), + ); + } + + @override + FutureOr validate() { + emit( + state.copyWith( + status: _formRepository.accessForm(formName).validate(), + ), + ); } } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_state.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_state.dart index fefe5325..d6ba26c3 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_state.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/cubit/sign_up_state.dart @@ -16,40 +16,32 @@ part of 'sign_up_cubit.dart'; -class SignUpState extends Equatable { - final Email email; - final Password password; - final FormStatus status; - final FormData data; - final String? errorMessage; +class SignUpState extends FormDataState { + Email get email => form.validatorOf(AuthFormField.email); + Password get password => form.validatorOf(AuthFormField.password); const SignUpState({ - required this.data, - this.email = const Email.pure(), - this.password = const Password.pure(), - this.status = FormStatus.pure, - this.errorMessage, + required super.form, + super.status = FormStatus.pure, + super.errorMessage, }); SignUpState copyWith({ - Email? email, - Password? password, + WyattForm? form, FormStatus? status, - FormData? data, String? errorMessage, }) => SignUpState( - email: email ?? this.email, - password: password ?? this.password, + form: form ?? this.form, status: status ?? this.status, - data: data ?? this.data, errorMessage: errorMessage ?? this.errorMessage, ); @override - String toString() => 'SignUpState(email: $email, password: $password, ' - 'status: $status, data: $data, errorMessage: $errorMessage)'; + List get props => [email, password, status, form]; @override - List get props => [email, password, status, data, errorMessage]; + @override + String toString() => 'SignUpState(status: ${status.name} ' + '${(errorMessage != null) ? " [$errorMessage]" : ""}, $form)'; } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/sign_up.dart b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/sign_up.dart index 798c644d..d03bdb75 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/sign_up/sign_up.dart +++ b/packages/wyatt_authentication_bloc/lib/src/features/sign_up/sign_up.dart @@ -1,16 +1,16 @@ // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with this program. If not, see . diff --git a/packages/wyatt_authentication_bloc/lib/src/src.dart b/packages/wyatt_authentication_bloc/lib/src/src.dart index 62ba6ef9..e5a07de0 100644 --- a/packages/wyatt_authentication_bloc/lib/src/src.dart +++ b/packages/wyatt_authentication_bloc/lib/src/src.dart @@ -1,30 +1,20 @@ // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with this program. If not, see . -export 'core/enum/auth_cubit_status.dart'; -export 'core/exceptions/exceptions.dart'; -export 'core/exceptions/exceptions_firebase.dart'; -export 'core/extensions/firebase_auth_user_x.dart'; -export 'core/utils/cryptography.dart'; -export 'data/models/user_firebase.dart'; -export 'data/repositories/authentication_repository_firebase.dart'; -export 'domain/entities/user.dart'; -export 'domain/repositories/authentication_repository.dart'; -export 'features/authentication/authentication.dart'; -export 'features/email_verification/email_verification.dart'; -export 'features/password_reset/password_reset.dart'; -export 'features/sign_in/sign_in.dart'; -export 'features/sign_up/sign_up.dart'; +export 'core/core.dart'; +export 'data/data.dart'; +export 'domain/domain.dart'; +export 'features/features.dart'; diff --git a/packages/wyatt_authentication_bloc/pubspec.yaml b/packages/wyatt_authentication_bloc/pubspec.yaml index a64ff634..48360fa7 100644 --- a/packages/wyatt_authentication_bloc/pubspec.yaml +++ b/packages/wyatt_authentication_bloc/pubspec.yaml @@ -3,6 +3,8 @@ description: Authentication BLoC for Flutter repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_authentication_bloc version: 0.2.1+4 +publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + environment: sdk: ">=2.17.0 <3.0.0" flutter: ">=1.17.0" @@ -12,9 +14,9 @@ dependencies: sdk: flutter crypto: ^3.0.2 - flutter_bloc: ^8.0.1 - equatable: ^2.0.3 - firebase_auth: ^3.3.17 + flutter_bloc: ^8.1.1 + equatable: ^2.0.5 + firebase_auth: ^4.1.1 google_sign_in: ^5.3.0 flutter_facebook_auth: ^4.3.0 sign_in_with_apple: ^3.3.0 @@ -25,16 +27,24 @@ dependencies: url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages ref: wyatt_form_bloc-v0.0.6 path: packages/wyatt_form_bloc + + wyatt_architecture: + git: + url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages + ref: wyatt_architecture-v0.0.2-dev.0 + path: packages/wyatt_architecture + + wyatt_type_utils: + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ + version: 0.0.3+1 dev_dependencies: flutter_test: sdk: flutter - bloc_test: ^9.0.3 + bloc_test: ^9.1.0 mocktail: ^0.3.0 wyatt_analysis: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - ref: wyatt_analysis-v2.2.2 - path: packages/wyatt_analysis + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ + version: 2.2.2 diff --git a/packages/wyatt_form_bloc/README.md b/packages/wyatt_form_bloc/README.md index 74a53324..82fb439a 100644 --- a/packages/wyatt_form_bloc/README.md +++ b/packages/wyatt_form_bloc/README.md @@ -16,16 +16,16 @@ * along with this program. If not, see . --> -# Dart - Form BLoC +# Flutter - Form BLoC

Style: Wyatt Analysis - SDK: Dart & Flutter + SDK: Flutter

-Form Bloc for Dart & Flutter. +Form Bloc for Flutter. ## Features diff --git a/packages/wyatt_form_bloc/analysis_options.yaml b/packages/wyatt_form_bloc/analysis_options.yaml index cc27c8ca..b0c6aced 100644 --- a/packages/wyatt_form_bloc/analysis_options.yaml +++ b/packages/wyatt_form_bloc/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:wyatt_analysis/analysis_options.yaml +include: package:wyatt_analysis/analysis_options.flutter.yaml analyzer: exclude: "!example/**" \ No newline at end of file diff --git a/packages/wyatt_form_bloc/example/ios/Flutter/AppFrameworkInfo.plist b/packages/wyatt_form_bloc/example/ios/Flutter/AppFrameworkInfo.plist index 8d4492f9..9625e105 100644 --- a/packages/wyatt_form_bloc/example/ios/Flutter/AppFrameworkInfo.plist +++ b/packages/wyatt_form_bloc/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 9.0 + 11.0 diff --git a/packages/wyatt_form_bloc/example/ios/Runner.xcodeproj/project.pbxproj b/packages/wyatt_form_bloc/example/ios/Runner.xcodeproj/project.pbxproj index abeae7fe..8a34f9c6 100644 --- a/packages/wyatt_form_bloc/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/wyatt_form_bloc/example/ios/Runner.xcodeproj/project.pbxproj @@ -272,7 +272,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -349,7 +349,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -398,7 +398,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/packages/wyatt_form_bloc/example/ios/Runner/Info.plist b/packages/wyatt_form_bloc/example/ios/Runner/Info.plist index 7f67e595..18f4a4be 100644 --- a/packages/wyatt_form_bloc/example/ios/Runner/Info.plist +++ b/packages/wyatt_form_bloc/example/ios/Runner/Info.plist @@ -43,5 +43,7 @@ UIViewControllerBasedStatusBarAppearance + CADisableMinimumFrameDurationOnPhone + diff --git a/packages/wyatt_form_bloc/example/lib/app/app.dart b/packages/wyatt_form_bloc/example/lib/app/app.dart index 611f20ac..63c35292 100644 --- a/packages/wyatt_form_bloc/example/lib/app/app.dart +++ b/packages/wyatt_form_bloc/example/lib/app/app.dart @@ -18,7 +18,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:form_bloc_example/app/metadata.dart'; import 'package:form_bloc_example/constants.dart'; -import 'package:form_bloc_example/cubit/custom_form_cubit.dart'; +import 'package:form_bloc_example/simple_custom_form_cubit/simple_custom_form_cubit.dart'; import 'package:form_bloc_example/sign_up/sign_up_page.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; @@ -29,43 +29,60 @@ class App extends StatelessWidget { const App({Key? key}) : super(key: key); static List getNormalEntries() { - return const [ - FormInput(formFieldName, Name.pure(), metadata: FormInputMetadata(extra: blue)), - FormInput(formFieldEmail, Email.pure(), metadata: FormInputMetadata(extra: blue)), - FormInput(formFieldPhone, Phone.pure(), metadata: FormInputMetadata(extra: red)), + return [ + FormInput(formFieldName, const Name.pure('Test'), + metadata: const FormInputMetadata(extra: blue)), + FormInput(formFieldEmail, const Email.pure(), + metadata: const FormInputMetadata(extra: blue)), FormInput( - formFieldList, ListOption.pure(defaultValue: ['checkbox3'])), - FormInput(formFieldRadio, TextString.pure()), - FormInput(formFieldPro, Boolean.pure(), - metadata: FormInputMetadata(name: 'business')), - FormInput(formFieldHidden, Boolean.pure(), - metadata: FormInputMetadata(export: false, extra: blue)), + formFieldList, const ListOption.pure(choices: ['c1', 'c2', 'c3'],defaultValue: 'c3')), + FormInput(formFieldRadio, const TextString.pure()), + FormInput(formFieldPro, const Boolean.pure(), + metadata: const FormInputMetadata(name: 'business')), + FormInput(formFieldHidden, const Boolean.pure(), + metadata: + const FormInputMetadata(export: false, extra: blue)), ]; } static List getBusinessEntries() { - const entries = [ - FormInput(formFieldSiren, Siren.pure()), - FormInput(formFieldIban, Iban.pure()), + final entries = [ + FormInput(formFieldPhone, const Phone.pure(), + metadata: const FormInputMetadata(extra: red)), ]; return getNormalEntries() + entries; } - static FormData getNormalFormData() { - return FormData(getNormalEntries()); + static WyattForm getNormalFormData() { + return WyattFormImpl(getNormalEntries(), name: formSignUp); } - static FormData getProFormData() { - return FormData(getBusinessEntries()); + static WyattForm getProFormData() { + return WyattFormImpl(getBusinessEntries(), name: formSignUp); } @override Widget build(BuildContext context) { - FormDataCubit formCubit = CustomFormCubit(inputs: getNormalFormData()); + FormRepository formRepository = FormRepositoryImpl() + ..registerForm(getNormalFormData()); + + // FormRepository formRepository = FormRepositoryImpl() + // ..registerForm(WyattFormImpl([ + // FormInput(formFieldName, const Name.pure('Test'), + // metadata: const FormInputMetadata(extra: blue)), + // ], name: formSignUp)); - return BlocProvider( - create: (context) => formCubit, - child: const WidgetTree(), + SimpleCustomFormCubit formCubit = SimpleCustomFormCubit( + formRepository, + formSignUp, + ); + + return RepositoryProvider.value( + value: formRepository, + child: BlocProvider( + create: (context) => formCubit, + child: const WidgetTree(), + ), ); } } diff --git a/packages/wyatt_form_bloc/example/lib/app/metadata.dart b/packages/wyatt_form_bloc/example/lib/app/metadata.dart index b4e68725..6d66f961 100644 --- a/packages/wyatt_form_bloc/example/lib/app/metadata.dart +++ b/packages/wyatt_form_bloc/example/lib/app/metadata.dart @@ -28,7 +28,5 @@ class Metadata { }); @override - String toString() { - return category.toString(); - } + String toString() => 'Metadata(category: $category)'; } diff --git a/packages/wyatt_form_bloc/example/lib/constants.dart b/packages/wyatt_form_bloc/example/lib/constants.dart index c1c52795..a52efc92 100644 --- a/packages/wyatt_form_bloc/example/lib/constants.dart +++ b/packages/wyatt_form_bloc/example/lib/constants.dart @@ -14,11 +14,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +const String formSignUp = 'signUp'; + const String formFieldName = 'name'; const String formFieldPhone = 'phone'; const String formFieldEmail = 'email'; -const String formFieldSiren = 'siren'; -const String formFieldIban = 'iban'; const String formFieldList = 'list'; const String formFieldRadio = 'radio'; const String formFieldHidden = 'hidden'; diff --git a/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart b/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart index 947faf6d..c1727ce5 100644 --- a/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart +++ b/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart @@ -14,39 +14,34 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:form_bloc_example/app/app.dart'; import 'package:form_bloc_example/app/metadata.dart'; import 'package:form_bloc_example/constants.dart'; +import 'package:form_bloc_example/simple_custom_form_cubit/simple_custom_form_cubit.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; -class CategoryIndicator extends StatelessWidget { - const CategoryIndicator( - {Key? key, required this.field, required this.builder}) - : super(key: key); - - final String field; - final Function(BuildContext context, FormDataState state) builder; - - Color computeColor(Metadata meta) { - switch (meta.category) { - case Category.perso: - return Colors.blue; - case Category.business: - return Colors.red; - } +Color computeColor(Metadata? meta) { + switch (meta?.category) { + case Category.perso: + return Colors.blue; + case Category.business: + return Colors.red; + case null: + return Colors.green; } +} +class _NameInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: ((context, state) { - final meta = state.data.metadataOf(field).extra as Metadata; + return InputBuilderTextController( + field: formFieldName, + builder: + (context, cubit, state, field, inputValid, controller, metadata) { + final meta = state.form.metadataOf(field).extra; final color = computeColor(meta); - return Row( children: [ Container( @@ -57,58 +52,25 @@ class CategoryIndicator extends StatelessWidget { borderRadius: BorderRadius.circular(8), ), ), - const SizedBox(width: 20,), + const SizedBox( + width: 20, + ), SizedBox( width: MediaQuery.of(context).size.width - 45, - child: builder(context, state), + child: TextField( + controller: controller, + onChanged: (value) => + cubit.dataChanged(field, Name.dirty(value)), + keyboardType: TextInputType.name, + decoration: InputDecoration( + labelText: 'name', + helperText: '', + errorText: !inputValid ? 'invalid name' : null, + ), + ), ) ], ); - }), - ); - } -} - -class _NameInput extends StatelessWidget { - @override - Widget build(BuildContext context) { - return CategoryIndicator( - field: formFieldName, - builder: (context, state) { - return TextField( - onChanged: (name) => context - .read() - .dataChanged(formFieldName, Name.dirty(name)), - keyboardType: TextInputType.name, - decoration: InputDecoration( - labelText: 'name', - helperText: '', - errorText: - state.data.isNotValid(formFieldName) ? 'invalid name' : null, - ), - ); - }); - } -} - -class _EmailInput extends StatelessWidget { - @override - Widget build(BuildContext context) { - return CategoryIndicator( - field: formFieldEmail, - builder: (context, state) { - return TextField( - onChanged: (email) => context - .read() - .dataChanged(formFieldEmail, Email.dirty(email)), - keyboardType: TextInputType.emailAddress, - decoration: InputDecoration( - labelText: 'email', - helperText: '', - errorText: - state.data.isNotValid(formFieldEmail) ? 'invalid email' : null, - ), - ); }, ); } @@ -117,67 +79,58 @@ class _EmailInput extends StatelessWidget { class _PhoneInput extends StatelessWidget { @override Widget build(BuildContext context) { - return CategoryIndicator( - field: formFieldPhone, - builder: (context, state) { - return TextField( - onChanged: (phone) => context - .read() - .dataChanged(formFieldPhone, Phone.dirty(phone)), - keyboardType: TextInputType.phone, - decoration: InputDecoration( - labelText: 'phone', - helperText: '', - errorText: - state.data.isNotValid(formFieldPhone) ? 'invalid phone' : null, - ), + return InputBuilderMetadata( + field: formFieldPhone, + builder: (context, cubit, state, field, inputValid, metadata) { + final meta = state.form.metadataOf(field).extra; + final color = computeColor(meta); + return Row( + children: [ + Container( + height: 8, + width: 8, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(8), + ), + ), + const SizedBox( + width: 20, + ), + SizedBox( + width: MediaQuery.of(context).size.width - 45, + child: TextField( + onChanged: (value) => + cubit.dataChanged(field, Phone.dirty(value)), + keyboardType: TextInputType.phone, + decoration: InputDecoration( + labelText: 'phone', + helperText: '', + errorText: !inputValid ? 'invalid phone' : null, + ), + ), + ) + ], ); }, ); } } -class _SirenInput extends StatelessWidget { +class _EmailInput extends StatelessWidget { @override Widget build(BuildContext context) { - return CategoryIndicator( - field: formFieldName, - builder: (context, state) { - return TextField( - onChanged: (siren) => context - .read() - .dataChanged(formFieldSiren, Siren.dirty(siren)), - keyboardType: TextInputType.number, - decoration: InputDecoration( - labelText: 'siren', - helperText: '', - errorText: - state.data.isNotValid(formFieldSiren) ? 'invalid SIREN' : null, - ), - ); - }, - ); - } -} - -class _IbanInput extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return TextField( - onChanged: (iban) => context - .read() - .dataChanged(formFieldIban, Iban.dirty(iban)), - keyboardType: TextInputType.text, - decoration: InputDecoration( - labelText: 'iban', - helperText: '', - errorText: - state.data.isNotValid(formFieldIban) ? 'invalid IBAN' : null, - ), - ); - }, + return InputBuilder( + field: formFieldEmail, + builder: (context, cubit, state, field, inputValid) => TextField( + onChanged: (value) => cubit.dataChanged(field, Email.dirty(value)), + keyboardType: TextInputType.emailAddress, + decoration: InputDecoration( + labelText: 'email', + helperText: '', + errorText: !inputValid ? 'invalid email' : null, + ), + ), ); } } @@ -185,11 +138,11 @@ class _IbanInput extends StatelessWidget { class _CheckListInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - final input = - state.data.validatorOf>(formFieldList); - final options = input.value; + return InputBuilder( + field: formFieldList, + builder: (context, cubit, state, field, inputValid) { + final input = state.form.validatorOf>(field); + final choices = ['c1', 'c2', 'c3']; return Column( mainAxisSize: MainAxisSize.min, @@ -197,34 +150,34 @@ class _CheckListInput extends StatelessWidget { ListTile( title: const Text('Checkbox1'), trailing: Checkbox( - value: options.contains('checkbox1'), + value: input.value == choices[0], onChanged: (_) { - context.read().dataChanged( - formFieldList, - input.select('checkbox1'), - ); + cubit.dataChanged( + field, + ListOption.dirty(choices: choices, value: choices[0]), + ); }), ), ListTile( title: const Text('Checkbox2'), trailing: Checkbox( - value: options.contains('checkbox2'), + value: input.value == choices[1], onChanged: (_) { - context.read().dataChanged( - formFieldList, - input.select('checkbox2'), - ); + cubit.dataChanged( + field, + ListOption.dirty(choices: choices, value: choices[1]), + ); }), ), ListTile( title: const Text('Checkbox3 (default)'), trailing: Checkbox( - value: options.contains('checkbox3'), + value: input.value == choices[2], onChanged: (_) { - context.read().dataChanged( - formFieldList, - input.select('checkbox3'), - ); + cubit.dataChanged( + field, + ListOption.dirty(choices: choices, value: choices[2]), + ); }), ), ], @@ -237,9 +190,10 @@ class _CheckListInput extends StatelessWidget { class _RadioListInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - final input = state.data.validatorOf(formFieldRadio); + return InputBuilder( + field: formFieldRadio, + builder: ((context, cubit, state, field, inputValid) { + final input = state.form.validatorOf(field); return Column( mainAxisSize: MainAxisSize.min, @@ -250,10 +204,10 @@ class _RadioListInput extends StatelessWidget { groupValue: true, value: input.value == 'radio1', onChanged: (_) { - context.read().dataChanged( - formFieldRadio, - const TextString.dirty('radio1'), - ); + cubit.dataChanged( + field, + const TextString.dirty('radio1'), + ); }), ), ListTile( @@ -262,10 +216,10 @@ class _RadioListInput extends StatelessWidget { groupValue: true, value: input.value == 'radio2', onChanged: (_) { - context.read().dataChanged( - formFieldRadio, - const TextString.dirty('radio2'), - ); + cubit.dataChanged( + field, + const TextString.dirty('radio2'), + ); }), ), ListTile( @@ -274,15 +228,15 @@ class _RadioListInput extends StatelessWidget { groupValue: true, value: input.value == 'radio3', onChanged: (_) { - context.read().dataChanged( - formFieldRadio, - const TextString.dirty('radio3'), - ); + cubit.dataChanged( + field, + const TextString.dirty('radio3'), + ); }), ), ], ); - }, + }), ); } } @@ -292,17 +246,18 @@ class _CheckHiddenInput extends StatelessWidget { Widget build(BuildContext context) { return ListTile( title: const Text('This input is not exported'), - trailing: BlocBuilder( - builder: (context, state) { + trailing: InputBuilder( + field: formFieldHidden, + builder: (context, cubit, state, field, inputValid) { return Checkbox( - value: state.data.validatorOf(formFieldHidden).value, + value: state.form.validatorOf(field).value, onChanged: (v) { final value = v!; // state is false, so value can't be null - context.read().dataChanged( - formFieldHidden, - Boolean.dirty(value: value), - ); + cubit.dataChanged( + field, + Boolean.dirty(value: value), + ); }); }, ), @@ -315,25 +270,24 @@ class _CheckIsProInput extends StatelessWidget { Widget build(BuildContext context) { return ListTile( title: const Text('Are you a pro?'), - trailing: BlocBuilder( - builder: (context, state) { + trailing: InputBuilder( + field: formFieldPro, + builder: (context, cubit, state, field, inputValid) { return Checkbox( - value: state.data.validatorOf(formFieldPro).value, - onChanged: (isPro) { - final value = isPro!; // state is false, so value can't be null + value: state.form.validatorOf(field).value, + onChanged: (v) { + final value = v!; // state is false, so value can't be null - context.read().dataChanged( - formFieldPro, - Boolean.dirty(value: value), - ); + cubit.dataChanged( + field, + Boolean.dirty(value: value), + ); if (value) { - context.read().updateFormData( - App.getProFormData(), + cubit.update(App.getProFormData(), operation: SetOperation.union); } else { - context.read().updateFormData( - App.getNormalFormData(), + cubit.update(App.getNormalFormData(), operation: SetOperation.intersection); } }); @@ -346,49 +300,28 @@ class _CheckIsProInput extends StatelessWidget { class _SignUpButton extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - buildWhen: (previous, current) => previous.status != current.status, - builder: (context, state) { - return state.status.isSubmissionInProgress - ? const CircularProgressIndicator() - : ElevatedButton( - onPressed: state.status.isValidated - ? () => context.read().submitForm() - : null, - child: const Text('SIGN UP'), - ); - }, - ); - } -} - -class _DebugButton extends StatelessWidget { - @override - Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return ElevatedButton( - onPressed: () { - log(state.toString()); - }, - child: const Text('DEBUG'), - ); - }, - ); + return SubmitBuilder( + builder: (context, cubit, status) { + return status.isSubmissionInProgress + ? const CircularProgressIndicator() + : ElevatedButton( + onPressed: status.isValidated ? () => cubit.submit() : null, + child: const Text('SIGN UP'), + ); + }); } } class _ResetButton extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return ElevatedButton( - onPressed: () => context.read().resetForm(), - child: const Text('RESET'), - ); - }, - ); + return SubmitBuilder( + builder: (context, cubit, status) { + return ElevatedButton( + onPressed: () => cubit.reset(), + child: const Text('RESET'), + ); + }); } } @@ -397,7 +330,7 @@ class SignUpForm extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocListener( + return BlocListener( listener: (context, state) { if (state.status.isSubmissionSuccess) { Navigator.of(context).pop(); // Never happens here @@ -418,8 +351,6 @@ class SignUpForm extends StatelessWidget { const SizedBox(height: 8), _EmailInput(), const SizedBox(height: 8), - _PhoneInput(), - const SizedBox(height: 8), _CheckListInput(), const SizedBox(height: 8), _RadioListInput(), @@ -428,13 +359,12 @@ class SignUpForm extends StatelessWidget { const SizedBox(height: 8), _CheckIsProInput(), const SizedBox(height: 8), - BlocBuilder( + BlocBuilder( builder: (context, state) { - if (state.data.validatorOf(formFieldPro).value) { + if (state.form.validatorOf(formFieldPro).value ?? + false) { return Column(children: [ - _SirenInput(), - const SizedBox(height: 8), - _IbanInput(), + _PhoneInput(), const SizedBox(height: 8), ]); } @@ -444,8 +374,6 @@ class SignUpForm extends StatelessWidget { const SizedBox(height: 8), _SignUpButton(), const SizedBox(height: 8), - _DebugButton(), - const SizedBox(height: 8), _ResetButton(), ], ), diff --git a/packages/wyatt_form_bloc/example/lib/sign_up/widgets/simple_sign_up_form.dart b/packages/wyatt_form_bloc/example/lib/sign_up/widgets/simple_sign_up_form.dart new file mode 100644 index 00000000..a3a93310 --- /dev/null +++ b/packages/wyatt_form_bloc/example/lib/sign_up/widgets/simple_sign_up_form.dart @@ -0,0 +1,57 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:form_bloc_example/app/metadata.dart'; +import 'package:form_bloc_example/constants.dart'; +import 'package:form_bloc_example/simple_custom_form_cubit/simple_custom_form_cubit.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; + +class _NameInput extends StatelessWidget { + @override + Widget build(BuildContext context) { + return InputBuilderTextController( + field: formFieldName, + builder: + (context, cubit, state, field, inputValid, controller, metadata) { + return TextField( + controller: controller, + onChanged: (value) => cubit.dataChanged(field, Name.dirty(value)), + keyboardType: TextInputType.name, + decoration: InputDecoration( + labelText: 'name', + helperText: '', + errorText: !inputValid ? 'invalid name' : null, + ), + ); + }, + ); + } +} + +class SimpleSignUpForm extends StatelessWidget { + const SimpleSignUpForm({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + _NameInput(), + const SizedBox(height: 8), + ], + ); + } +} diff --git a/packages/wyatt_form_bloc/example/lib/cubit/custom_form_cubit.dart b/packages/wyatt_form_bloc/example/lib/simple_custom_form_cubit/simple_custom_form_cubit.dart similarity index 78% rename from packages/wyatt_form_bloc/example/lib/cubit/custom_form_cubit.dart rename to packages/wyatt_form_bloc/example/lib/simple_custom_form_cubit/simple_custom_form_cubit.dart index 3f211c60..bb23ed9a 100644 --- a/packages/wyatt_form_bloc/example/lib/cubit/custom_form_cubit.dart +++ b/packages/wyatt_form_bloc/example/lib/simple_custom_form_cubit/simple_custom_form_cubit.dart @@ -18,12 +18,13 @@ import 'dart:developer'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; -class CustomFormCubit extends FormDataCubit { - CustomFormCubit({required FormData inputs}) : super(inputs: inputs); +class SimpleCustomFormCubit extends FormDataCubitImpl { + SimpleCustomFormCubit(super._formRepository, super._formName) : super(); @override - Future submitForm() { - log(state.data.toMap().toString()); + Future submit() { + final value = FormJsonEncoder().encode(state.form); + log(value); return Future.value(); } diff --git a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/password_reset.dart b/packages/wyatt_form_bloc/lib/src/core/core.dart similarity index 94% rename from packages/wyatt_authentication_bloc/lib/src/features/password_reset/password_reset.dart rename to packages/wyatt_form_bloc/lib/src/core/core.dart index 43919e02..9d6c64d8 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/password_reset/password_reset.dart +++ b/packages/wyatt_form_bloc/lib/src/core/core.dart @@ -14,4 +14,4 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -export 'cubit/password_reset_cubit.dart'; +export 'enums/enums.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/enums/enums.dart b/packages/wyatt_form_bloc/lib/src/core/enums/enums.dart similarity index 100% rename from packages/wyatt_form_bloc/lib/src/enums/enums.dart rename to packages/wyatt_form_bloc/lib/src/core/enums/enums.dart diff --git a/packages/wyatt_form_bloc/lib/src/enums/form_input_status.dart b/packages/wyatt_form_bloc/lib/src/core/enums/form_input_status.dart similarity index 100% rename from packages/wyatt_form_bloc/lib/src/enums/form_input_status.dart rename to packages/wyatt_form_bloc/lib/src/core/enums/form_input_status.dart diff --git a/packages/wyatt_form_bloc/lib/src/enums/form_status.dart b/packages/wyatt_form_bloc/lib/src/core/enums/form_status.dart similarity index 100% rename from packages/wyatt_form_bloc/lib/src/enums/form_status.dart rename to packages/wyatt_form_bloc/lib/src/core/enums/form_status.dart diff --git a/packages/wyatt_form_bloc/lib/src/core/enums/set_operations.dart b/packages/wyatt_form_bloc/lib/src/core/enums/set_operations.dart new file mode 100644 index 00000000..3e27f437 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/core/enums/set_operations.dart @@ -0,0 +1,39 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_form_bloc/src/data/form_operations/form_difference.dart'; +import 'package:wyatt_form_bloc/src/data/form_operations/form_intersection.dart'; +import 'package:wyatt_form_bloc/src/data/form_operations/form_replace.dart'; +import 'package:wyatt_form_bloc/src/data/form_operations/form_union.dart'; +import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart'; + +enum SetOperation { + /// Replace entire set with new set. + replace(FormReplace()), + + /// Keep common elements between sets. + intersection(FormIntersection()), + + /// Remove common elements between sets. + difference(FormDifference()), + + /// Add new elements to set. + union(FormUnion()); + + final FormOperation operation; + + const SetOperation(this.operation); +} diff --git a/packages/wyatt_form_bloc/lib/src/enums/validation_error.dart b/packages/wyatt_form_bloc/lib/src/core/enums/validation_error.dart similarity index 97% rename from packages/wyatt_form_bloc/lib/src/enums/validation_error.dart rename to packages/wyatt_form_bloc/lib/src/core/enums/validation_error.dart index 5a0b436e..4966b6b8 100644 --- a/packages/wyatt_form_bloc/lib/src/enums/validation_error.dart +++ b/packages/wyatt_form_bloc/lib/src/core/enums/validation_error.dart @@ -23,5 +23,6 @@ abstract class ValidationError {} enum ValidationStandardError implements ValidationError { invalid, - empty + empty, + notEqual, } diff --git a/packages/wyatt_form_bloc/lib/src/cubit/form_data_cubit.dart b/packages/wyatt_form_bloc/lib/src/cubit/form_data_cubit.dart deleted file mode 100644 index 5434acac..00000000 --- a/packages/wyatt_form_bloc/lib/src/cubit/form_data_cubit.dart +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'dart:async'; - -import 'package:bloc/bloc.dart'; -import 'package:equatable/equatable.dart'; -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/form/form.dart'; -import 'package:wyatt_form_bloc/src/validators/form/every_input_validator.dart'; - -part 'form_data_state.dart'; - -abstract class FormDataCubit extends Cubit { - FormValidator validationStrategy; - FormData formCopy; - - FormDataCubit({ - required FormData inputs, - FormValidator validator = const EveryInputValidator(), - }) : formCopy = inputs.clone(), - validationStrategy = validator, - super(FormDataState(data: inputs)); - - /// Change value of a field. - /// - /// Inputs: - /// - `field`: The key of the field to change. - /// - `dirtyValue`: The new value of the field. (Wrapped in a dirty validator) - void dataChanged( - String field, - FormInputValidator dirtyValue, - ) { - final form = state.data.clone(); - - if (form.contains(field)) { - form.updateValidator(field, dirtyValue); - } else { - throw Exception('Form field $field not found'); - } - - emit( - state.copyWith( - data: form, - status: validationStrategy.validate(form), - ), - ); - } - - /// Just validate the form manually. (Useful if you just update the strategy) - void validate() { - final form = state.data; - emit(state.copyWith(status: validationStrategy.validate(form))); - } - - /// Update entries list. - /// - /// Inputs: - /// - `data`: The new entries list. - /// - `operation`: The operation to perform on the entries set. - void updateFormData( - FormData data, { - SetOperation operation = SetOperation.replace, - }) { - FormData form = data; - - switch (operation) { - case SetOperation.replace: - form = data; - break; - case SetOperation.difference: - form = state.data.difference(data); - break; - case SetOperation.intersection: - form = state.data.intersection(data); - break; - case SetOperation.union: - form = state.data.union(data); - break; - } - - emit( - state.copyWith( - data: form, - status: validationStrategy.validate(form), - ), - ); - } - - /// Reset all form inputs - void resetForm() { - emit(FormDataState(data: formCopy)); - } - - /// Submit the form. - Future submitForm(); -} diff --git a/packages/wyatt_form_bloc/lib/src/data/data.dart b/packages/wyatt_form_bloc/lib/src/data/data.dart new file mode 100644 index 00000000..f86212c5 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/data.dart @@ -0,0 +1,35 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'form/wyatt_form_impl.dart'; +export 'form_encoders/form_json_encoder.dart'; +export 'form_encoders/form_map_encoder.dart'; +export 'form_operations/form_difference.dart'; +export 'form_operations/form_intersection.dart'; +export 'form_operations/form_replace.dart'; +export 'form_operations/form_union.dart'; +export 'form_validators/every_input_validator.dart'; +export 'form_validators/only_required_input_validator.dart'; +export 'input_validators/boolean.dart'; +export 'input_validators/confirmed_password.dart'; +export 'input_validators/email.dart'; +export 'input_validators/enum_option.dart'; +export 'input_validators/list_option.dart'; +export 'input_validators/name.dart'; +export 'input_validators/password.dart'; +export 'input_validators/phone.dart'; +export 'input_validators/text_string.dart'; +export 'repositories/form_repository_impl.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart b/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart new file mode 100644 index 00000000..d336b329 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart @@ -0,0 +1,153 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/data/form_validators/every_input_validator.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input_metadata.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart'; +import 'package:wyatt_form_bloc/src/domain/form_validators/form_validator.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; + +// ignore: must_be_immutable +class WyattFormImpl extends WyattForm { + final List< + FormInput, + dynamic>> _inputs; + final FormValidator _validator; + final String _name; + + late List< + FormInput, + dynamic>> _inputsInitial; + + WyattFormImpl( + this._inputs, { + required String name, + FormValidator validationStrategy = const EveryInputValidator(), + }) : _name = name, + _validator = validationStrategy { + _inputsInitial = _inputs.map((input) => input.clone()).toList(); + } + + @override + List< + FormInput, + dynamic>> get inputs => _inputs; + + @override + FormValidator get formValidationStrategy => _validator; + + @override + String get name => _name; + + @override + bool containsKey(String key) => inputs.any((input) => input.key == key); + + @override + List> + asValidatorList() => inputs + .map>( + (input) => input.validator as FormInputValidator, + ) + .toList(); + + @override + FormInput, dynamic> + inputOf(String key) { + if (containsKey(key)) { + return inputs.firstWhere((input) => input.key == key); + } else { + throw Exception( + 'FormInput with key `$key` does not exist in form `$name`', + ); + } + } + + @override + Error? errorOf(String key) => + (inputOf(key).validator as FormInputValidator).error; + + @override + FormInputMetadata metadataOf(String key) => + inputOf(key).metadata as FormInputMetadata; + + @override + Validator validatorOf< + Validator extends FormInputValidator>( + String key, + ) => + inputOf(key).validator as Validator; + + @override + Value? valueOf(String key) => + (inputOf(key).validator as FormInputValidator).value; + + @override + FormStatus validate() => formValidationStrategy.validate(this); + + @override + WyattForm clone() { + final clone = WyattFormImpl( + _inputs.map((input) => input.clone()).toList(), + name: _name, + validationStrategy: formValidationStrategy, + ).._inputsInitial = _inputsInitial; + return clone; + } + + @override + WyattForm reset() { + final newForm = WyattFormImpl( + _inputsInitial, + name: _name, + validationStrategy: formValidationStrategy, + ).._inputsInitial = _inputsInitial; + return newForm; + } + + @override + void updateMetadata(String key, FormInputMetadata metadata) { + final index = _inputs.indexOf( + inputOf(key), + ); + _inputs[index] = _inputs[index].copyWith(metadata: metadata); + } + + @override + void updateValidator( + String key, + FormInputValidator dirtyValue, + ) { + final index = _inputs.indexOf( + inputOf(key), + ); + _inputs[index] = _inputs[index].copyWith(validator: dirtyValue); + } + + @override + WyattForm operationWith(FormOperation operation, WyattForm other) => + operation.call(this, other); + + @override + List get props => [_inputs, _name, _validator]; + + @override + String toString() => 'WyattForm(name: $name, validation: ' + '${_validator.runtimeType}, inputs: $inputs)'; +} diff --git a/packages/wyatt_form_bloc/lib/src/form/form.dart b/packages/wyatt_form_bloc/lib/src/data/form_encoders/form_json_encoder.dart similarity index 62% rename from packages/wyatt_form_bloc/lib/src/form/form.dart rename to packages/wyatt_form_bloc/lib/src/data/form_encoders/form_json_encoder.dart index 041263fc..a4d3d636 100644 --- a/packages/wyatt_form_bloc/lib/src/form/form.dart +++ b/packages/wyatt_form_bloc/lib/src/data/form_encoders/form_json_encoder.dart @@ -16,13 +16,15 @@ import 'dart:convert'; -import 'package:equatable/equatable.dart'; -import 'package:wyatt_form_bloc/src/enums/form_input_status.dart'; -import 'package:wyatt_form_bloc/src/enums/form_status.dart'; -import 'package:wyatt_form_bloc/src/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/data/form_encoders/form_map_encoder.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_encoders/form_encoder.dart'; -part 'form_data.dart'; -part 'form_input.dart'; -part 'form_input_metadata.dart'; -part 'form_input_validator.dart'; -part 'form_validator.dart'; +class FormJsonEncoder extends FormEncoder { + @override + String encode(WyattForm form) { + final mapEncoder = FormMapEncoder(); + final map = mapEncoder.encode(form); + return jsonEncode(map); + } +} diff --git a/packages/wyatt_form_bloc/lib/src/data/form_encoders/form_map_encoder.dart b/packages/wyatt_form_bloc/lib/src/data/form_encoders/form_map_encoder.dart new file mode 100644 index 00000000..9d682976 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/form_encoders/form_map_encoder.dart @@ -0,0 +1,32 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_encoders/form_encoder.dart'; + +class FormMapEncoder extends FormEncoder> { + @override + Map encode(WyattForm form) { + final inputs = form.inputs; + final map = {}; + for (final input in inputs) { + if (input.metadata.export) { + map[input.name] = input.validator.value; + } + } + return map; + } +} diff --git a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_difference.dart b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_difference.dart new file mode 100644 index 00000000..14a78d9c --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_difference.dart @@ -0,0 +1,51 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/data/form/wyatt_form_impl.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; + +class FormDifference extends FormOperation { + const FormDifference(); + + @override + WyattForm call(WyattForm a, WyattForm b) { + final inputs = < + FormInput, + dynamic>>[]; + + for (final i in b.inputs) { + if (!a.containsKey(i.key)) { + inputs.add(i); + } + } + + for (final i in a.inputs) { + if (!b.containsKey(i.key)) { + inputs.add(i); + } + } + + return WyattFormImpl( + inputs, + name: a.name, + validationStrategy: a.formValidationStrategy, + ); + } +} diff --git a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_intersection.dart b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_intersection.dart new file mode 100644 index 00000000..2c1d4cb6 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_intersection.dart @@ -0,0 +1,45 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/data/form/wyatt_form_impl.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; + +class FormIntersection extends FormOperation { + const FormIntersection(); + + @override + WyattForm call(WyattForm a, WyattForm b) { + final inputs = < + FormInput, + dynamic>>[]; + + for (final i in a.inputs) { + if (b.containsKey(i.key)) { + inputs.add(i); + } + } + + return WyattFormImpl( + inputs, + name: a.name, + validationStrategy: a.formValidationStrategy, + ); + } +} diff --git a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_replace.dart b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_replace.dart new file mode 100644 index 00000000..9c5ab986 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_replace.dart @@ -0,0 +1,25 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart'; + +class FormReplace extends FormOperation { + const FormReplace(); + + @override + WyattForm call(WyattForm a, WyattForm b) => b; +} diff --git a/packages/wyatt_form_bloc/lib/src/data/form_operations/form_union.dart b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_union.dart new file mode 100644 index 00000000..a466750b --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/form_operations/form_union.dart @@ -0,0 +1,49 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/data/form/wyatt_form_impl.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; + +class FormUnion extends FormOperation { + const FormUnion(); + + @override + WyattForm call(WyattForm a, WyattForm b) { + final inputs = < + FormInput, + dynamic>>[]; + + for (final i in a.inputs) { + inputs.add(i); + } + + for (final i in b.inputs) { + if (!a.containsKey(i.key)) { + inputs.add(i); + } + } + + return WyattFormImpl( + inputs, + name: a.name, + validationStrategy: a.formValidationStrategy, + ); + } +} diff --git a/packages/wyatt_form_bloc/lib/src/validators/form/every_input_validator.dart b/packages/wyatt_form_bloc/lib/src/data/form_validators/every_input_validator.dart similarity index 73% rename from packages/wyatt_form_bloc/lib/src/validators/form/every_input_validator.dart rename to packages/wyatt_form_bloc/lib/src/data/form_validators/every_input_validator.dart index fba42286..adfd60bc 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/form/every_input_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/data/form_validators/every_input_validator.dart @@ -14,7 +14,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_validators/form_validator.dart'; /// {@template every} /// Check and validate every input of a form @@ -24,18 +27,13 @@ class EveryInputValidator extends FormValidator { const EveryInputValidator() : super(); @override - FormStatus validate(FormData form) { + FormStatus validate(WyattForm form) { if (isPure(form)) { return FormStatus.pure; } - return rawValidate(form.validators()); - } + final validators = form.asValidatorList(); - @override - FormStatus rawValidate( - List> validators, - ) { if (validators.any((validator) => validator.valid == false)) { return FormStatus.invalid; } diff --git a/packages/wyatt_form_bloc/lib/src/data/form_validators/only_required_input_validator.dart b/packages/wyatt_form_bloc/lib/src/data/form_validators/only_required_input_validator.dart new file mode 100644 index 00000000..bd83d295 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/form_validators/only_required_input_validator.dart @@ -0,0 +1,29 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/form_validators/form_validator.dart'; + +class OnlyRequiredInputValidator extends FormValidator { + const OnlyRequiredInputValidator() : super(); + + @override + FormStatus validate(WyattForm form) { + // TODO(hpcl): use metadata to check if input is required or not. + return FormStatus.valid; + } +} diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/boolean.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/boolean.dart similarity index 74% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/boolean.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/boolean.dart index e28f5ad1..71f470ca 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/boolean.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/boolean.dart @@ -14,21 +14,25 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/form/form.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; /// {@template boolean} /// Form input for a bool input /// {@endtemplate} -class Boolean extends FormInputValidator { +class Boolean extends NullableValidator { /// {@macro boolean} const Boolean.pure({bool? defaultValue = false}) : super.pure(defaultValue ?? false); /// {@macro boolean} const Boolean.dirty({bool value = false}) : super.dirty(value); + + @override + ValidationStandardError get onNull => ValidationStandardError.invalid; @override ValidationStandardError? validator(bool? value) => - value != null ? null : ValidationStandardError.invalid; + value != null ? null : onNull; + } diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/confirmed_password.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/confirmed_password.dart similarity index 59% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/confirmed_password.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/confirmed_password.dart index 54899cf2..b8df4c4c 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/confirmed_password.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/confirmed_password.dart @@ -14,25 +14,34 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/form/form.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; /// {@template confirmed_password} /// Form input for a confirmed password input. /// {@endtemplate} class ConfirmedPassword - extends FormInputValidator { + extends EqualityValidator { /// {@macro confirmed_password} - const ConfirmedPassword.pure({this.password = ''}) : super.pure(''); + const ConfirmedPassword.pure({this.password = '', String? defaultValue}) + : super.pure(defaultValue); /// {@macro confirmed_password} - const ConfirmedPassword.dirty({required this.password, String value = ''}) + const ConfirmedPassword.dirty({required this.password, String? value}) : super.dirty(value); /// The original password. final String password; @override - ValidationStandardError? validator(String? value) => - password == value ? null : ValidationStandardError.invalid; + String get another => password; + + @override + ValidationStandardError get onNotEqual => ValidationStandardError.notEqual; + + @override + ValidationStandardError get onNull => ValidationStandardError.invalid; + + @override + List get props => super.props + [password]; } diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/email.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/email.dart similarity index 85% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/email.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/email.dart index 4961c672..c718dfdb 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/email.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/email.dart @@ -14,15 +14,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; /// {@template email} /// Form input for an email input. /// {@endtemplate} class Email extends RegexValidator { /// {@macro email} - const Email.pure() : super.pure(); + const Email.pure([super.value]) : super.pure(); /// {@macro email} const Email.dirty([super.value = '']) : super.dirty(); diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/siren.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/enum_option.dart similarity index 52% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/siren.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/enum_option.dart index 798c33f4..8a939fba 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/siren.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/enum_option.dart @@ -14,24 +14,27 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; -/// {@template siren} -/// Form input for a SIREN input. -/// {@endtemplate} -class Siren extends RegexValidator { - /// {@macro siren} - const Siren.pure() : super.pure(); +class EnumOption extends AnyValidator, ValidationError> { + const EnumOption.pure({this.enums = const [], T? defaultValue}) + : super.pure(defaultValue); - /// {@macro siren} - const Siren.dirty([super.value = '']) : super.dirty(); + const EnumOption.dirty({required this.enums, T? value}) + : super.dirty(value); + + final List enums; @override - ValidationStandardError get onEmpty => ValidationStandardError.empty; - @override - ValidationStandardError get onError => ValidationStandardError.invalid; + List get allChoices => enums; @override - RegExp get regex => RegExp(r'(\d{9}|\d{3}[ ]\d{3}[ ]\d{3})$'); + ValidationError get onError => ValidationStandardError.invalid; + + @override + ValidationError get onNull => ValidationStandardError.invalid; + + @override + bool test(T? element, T value) => element == value; } diff --git a/packages/wyatt_form_bloc/lib/src/data/input_validators/list_option.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/list_option.dart new file mode 100644 index 00000000..13f28986 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/list_option.dart @@ -0,0 +1,40 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; + +class ListOption extends AnyValidator, ValidationError> { + const ListOption.pure({this.choices = const [], T? defaultValue}) + : super.pure(defaultValue); + + const ListOption.dirty({required this.choices, T? value}) + : super.dirty(value); + + final Iterable choices; + + @override + Iterable get allChoices => choices; + + @override + ValidationError get onError => ValidationStandardError.invalid; + + @override + ValidationError get onNull => ValidationStandardError.invalid; + + @override + bool test(T? element, T value) => element == value; +} diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/name.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/name.dart similarity index 85% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/name.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/name.dart index cf3b6558..6ade3e21 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/name.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/name.dart @@ -14,15 +14,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; /// {@template name} /// Form input for a name input. /// {@endtemplate} class Name extends RegexValidator { /// {@macro name} - const Name.pure() : super.pure(); + const Name.pure([super.value]) : super.pure(); /// {@macro name} const Name.dirty([super.value = '']) : super.dirty(); diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/password.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/password.dart similarity index 81% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/password.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/password.dart index 8a6beab0..5ec35d91 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/password.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/password.dart @@ -14,18 +14,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; /// {@template password} /// Form input for a password input. /// {@endtemplate} class Password extends RegexValidator { /// {@macro password} - const Password.pure() : super.pure(); + const Password.pure([super.value]) : super.pure(); /// {@macro password} - const Password.dirty([super.value = '']) : super.dirty(); + const Password.dirty([super.value]) : super.dirty(); @override ValidationStandardError get onEmpty => ValidationStandardError.empty; diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/phone.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/phone.dart similarity index 85% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/phone.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/phone.dart index 9f4dd1af..74c93c2e 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/phone.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/phone.dart @@ -14,15 +14,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; /// {@template phone} /// Form input for a phone input. /// {@endtemplate} class Phone extends RegexValidator { /// {@macro phone} - const Phone.pure() : super.pure(); + const Phone.pure([super.value]) : super.pure(); /// {@macro phone} const Phone.dirty([super.value = '']) : super.dirty(); diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/text_string.dart b/packages/wyatt_form_bloc/lib/src/data/input_validators/text_string.dart similarity index 84% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/text_string.dart rename to packages/wyatt_form_bloc/lib/src/data/input_validators/text_string.dart index 61d0def3..9bf9e0be 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/text_string.dart +++ b/packages/wyatt_form_bloc/lib/src/data/input_validators/text_string.dart @@ -14,15 +14,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/text_validator.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; /// {@template text_string} /// Form input for a text input /// {@endtemplate} class TextString extends TextValidator { /// {@macro text_string} - const TextString.pure() : super.pure(); + const TextString.pure([super.value]) : super.pure(); /// {@macro text_string} const TextString.dirty([super.value = '']) : super.dirty(); diff --git a/packages/wyatt_form_bloc/lib/src/data/repositories/form_repository_impl.dart b/packages/wyatt_form_bloc/lib/src/data/repositories/form_repository_impl.dart new file mode 100644 index 00000000..b720c0f6 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/data/repositories/form_repository_impl.dart @@ -0,0 +1,63 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/repositories/form_repository.dart'; + +class FormRepositoryImpl extends FormRepository { + final Map _runtimeForms = {}; + + @override + Map get runtimeForms => _runtimeForms; + + @override + WyattForm accessForm(String formName) { + if (_runtimeForms.containsKey(formName)) { + return _runtimeForms[formName]!; + } else { + throw ClientException( + 'Form $formName is not registered. Just use ' + '`FormRepository.register(yourForm);` before any operation on it.', + ); + } + } + + @override + void registerForm(WyattForm form) { + _runtimeForms[form.name] = form; + } + + @override + void updateForm(WyattForm form) { + if (_runtimeForms.containsKey(form.name)) { + _runtimeForms[form.name] = form; + } else { + throw ClientException( + 'Form ${form.name} is not registered. Just use ' + '`FormRepository.register(yourForm);` before any operation on it.', + ); + } + } + + @override + void unregisterForm(String formName) { + _runtimeForms.remove(formName); + } + + @override + String toString() => 'FormRepository($_runtimeForms)'; +} diff --git a/packages/wyatt_form_bloc/lib/src/domain/domain.dart b/packages/wyatt_form_bloc/lib/src/domain/domain.dart new file mode 100644 index 00000000..a7eae716 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/domain/domain.dart @@ -0,0 +1,24 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'entities/form_input.dart'; +export 'entities/form_input_metadata.dart'; +export 'form/wyatt_form.dart'; +export 'form_encoders/form_encoder.dart'; +export 'form_operations/form_operation.dart'; +export 'form_validators/form_validator.dart'; +export 'input_validators/form_input_validator.dart'; +export 'repositories/form_repository.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/form/form_input.dart b/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart similarity index 57% rename from packages/wyatt_form_bloc/lib/src/form/form_input.dart rename to packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart index 6ab60d99..0947e7aa 100644 --- a/packages/wyatt_form_bloc/lib/src/form/form_input.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/entities/form_input.dart @@ -15,27 +15,36 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -part of 'form.dart'; +import 'package:equatable/equatable.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input_metadata.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; -class FormInput> - extends Equatable { +// ignore: must_be_immutable +class FormInput< + Value, + Validator extends FormInputValidator, + Extra> extends Equatable implements Entity { final String key; final Validator validator; - final FormInputMetadata metadata; + late FormInputMetadata metadata; - String get name => metadata._name ?? key; + String get name => metadata.name ?? key; - const FormInput( + FormInput( this.key, this.validator, { // ignore: avoid_redundant_argument_values - this.metadata = const FormInputMetadata(export: true), - }); + FormInputMetadata? metadata, + }) { + this.metadata = metadata ?? FormInputMetadata(); + } - FormInput copyWith({ + FormInput copyWith({ String? key, Validator? validator, - FormInputMetadata? metadata, + FormInputMetadata? metadata, }) => FormInput( key ?? this.key, @@ -43,14 +52,16 @@ class FormInput> metadata: metadata ?? this.metadata, ); - FormInput clone() => copyWith( + FormInput clone() => copyWith( key: key, validator: validator, metadata: metadata, ); - @override - bool? get stringify => true; @override List get props => [key, validator, metadata]; + + @override + String toString() => + 'FormInput(name: $name, $validator)'; } diff --git a/packages/wyatt_form_bloc/lib/src/form/form_input_metadata.dart b/packages/wyatt_form_bloc/lib/src/domain/entities/form_input_metadata.dart similarity index 69% rename from packages/wyatt_form_bloc/lib/src/form/form_input_metadata.dart rename to packages/wyatt_form_bloc/lib/src/domain/entities/form_input_metadata.dart index bed46368..df21c950 100644 --- a/packages/wyatt_form_bloc/lib/src/form/form_input_metadata.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/entities/form_input_metadata.dart @@ -15,33 +15,35 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -part of 'form.dart'; +import 'package:equatable/equatable.dart'; +import 'package:wyatt_architecture/wyatt_architecture.dart'; -class FormInputMetadata extends Equatable { +class FormInputMetadata extends Equatable + implements Entity { final bool export; - final String? _name; - final T? extra; + final String? name; + final Extra? extra; const FormInputMetadata({ this.export = true, + this.name, this.extra, - String? name, - }) : _name = name; + }); - FormInputMetadata copyWith({ + FormInputMetadata copyWith({ bool? export, String? name, - T? extra, + Extra? extra, }) => - FormInputMetadata( + FormInputMetadata( export: export ?? this.export, - name: name ?? _name, + name: name ?? this.name, extra: extra ?? this.extra, ); - FormInputMetadata clone() => copyWith( + FormInputMetadata clone() => copyWith( export: export, - name: _name, + name: name, extra: extra, ); @@ -49,5 +51,5 @@ class FormInputMetadata extends Equatable { bool? get stringify => true; @override - List get props => [export, _name, extra]; + List get props => [export, name, extra]; } diff --git a/packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart b/packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart new file mode 100644 index 00000000..1b156c94 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart @@ -0,0 +1,61 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// ignore_for_file: strict_raw_type + +import 'package:equatable/equatable.dart'; +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input_metadata.dart'; +import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart'; +import 'package:wyatt_form_bloc/src/domain/form_validators/form_validator.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; + +abstract class WyattForm extends Equatable { + List get inputs; + FormValidator get formValidationStrategy; + String get name; + + bool containsKey(String key); + + FormInput inputOf(String key); + Validator validatorOf< + Validator extends FormInputValidator>( + String key, + ); + Error? errorOf(String key); + Value? valueOf(String key); + FormInputMetadata metadataOf(String key); + + List> + asValidatorList(); + + void updateValidator( + String key, + FormInputValidator dirtyValue, + ); + + void updateMetadata( + String key, + FormInputMetadata metadata, + ); + + FormStatus validate(); + WyattForm clone(); + WyattForm operationWith(FormOperation operation, WyattForm other); + WyattForm reset(); +} diff --git a/packages/wyatt_authentication_bloc/lib/src/core/extensions/firebase_auth_user_x.dart b/packages/wyatt_form_bloc/lib/src/domain/form_encoders/form_encoder.dart similarity index 76% rename from packages/wyatt_authentication_bloc/lib/src/core/extensions/firebase_auth_user_x.dart rename to packages/wyatt_form_bloc/lib/src/domain/form_encoders/form_encoder.dart index 70b870c3..c69c226d 100644 --- a/packages/wyatt_authentication_bloc/lib/src/core/extensions/firebase_auth_user_x.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/form_encoders/form_encoder.dart @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:wyatt_authentication_bloc/src/data/models/user_firebase.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; -extension FirebaseAuthUserX on User { - UserFirebase get model => UserFirebase(this); +// ignore: one_member_abstracts +abstract class FormEncoder { + Output encode(WyattForm form); } diff --git a/packages/wyatt_form_bloc/lib/src/domain/form_operations/form_operation.dart b/packages/wyatt_form_bloc/lib/src/domain/form_operations/form_operation.dart new file mode 100644 index 00000000..eaf8f960 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/domain/form_operations/form_operation.dart @@ -0,0 +1,24 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; + +// ignore: one_member_abstracts +abstract class FormOperation { + const FormOperation(); + // TODO(hpcl): handle operation on `initialInputs` + WyattForm call(WyattForm a, WyattForm b); +} diff --git a/packages/wyatt_form_bloc/lib/src/form/form_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/form_validators/form_validator.dart similarity index 74% rename from packages/wyatt_form_bloc/lib/src/form/form_validator.dart rename to packages/wyatt_form_bloc/lib/src/domain/form_validators/form_validator.dart index 958d4e3e..45137ab7 100644 --- a/packages/wyatt_form_bloc/lib/src/form/form_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/form_validators/form_validator.dart @@ -14,7 +14,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -part of 'form.dart'; +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; /// {@template form_validator} /// A [FormValidator] represents the global validaton state of a Form. @@ -23,13 +25,9 @@ abstract class FormValidator { /// {@macro form_validator} const FormValidator(); - bool isPure(FormData form) => form - .validators() + bool isPure(WyattForm form) => form + .asValidatorList() .every((validator) => validator.pure); - FormStatus validate(FormData form); - - FormStatus rawValidate( - List> validators, - ); + FormStatus validate(WyattForm form); } diff --git a/packages/wyatt_form_bloc/lib/src/domain/input_validators/any_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/any_validator.dart new file mode 100644 index 00000000..396924d7 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/any_validator.dart @@ -0,0 +1,51 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'form_input_validator.dart'; + +abstract class AnyValidator, + E extends ValidationError> extends FormInputValidator { + const AnyValidator.pure(super.value) : super.pure(); + const AnyValidator.dirty(super.value) : super.dirty(); + + I get allChoices; + + bool test(O? element, O value); + + E get onError; + + /// If value is null. + E get onNull; + + @override + E? validator(O? value) { + if (value == null) { + return onNull; + } + if (allChoices.any( + (element) => test(element, value), + )) { + return null; + } + return onError; + } + + @override + List get props => super.props + [allChoices]; + + @override + String toString() => '${super.toString()}, choices: $allChoices'; +} diff --git a/packages/wyatt_form_bloc/lib/src/domain/input_validators/equality_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/equality_validator.dart new file mode 100644 index 00000000..3a70b9ad --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/equality_validator.dart @@ -0,0 +1,51 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'form_input_validator.dart'; + +/// {@template equality_validator} +/// Abstract equality validator validating a value when equals to another. +/// {@endtemplate} +abstract class EqualityValidator + extends FormInputValidator { + const EqualityValidator.pure(super.value) : super.pure(); + const EqualityValidator.dirty(super.value) : super.dirty(); + + O get another; + + /// If values are different. + E get onNotEqual; + + /// If value is null. + E get onNull; + + @override + E? validator(O? value) { + if (value == null) { + return onNull; + } + if (value != another) { + return onNotEqual; + } + return null; + } + + @override + List get props => super.props + [another]; + + @override + String toString() => '${super.toString()}, another: $another'; +} diff --git a/packages/wyatt_form_bloc/lib/src/form/form_input_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart similarity index 84% rename from packages/wyatt_form_bloc/lib/src/form/form_input_validator.dart rename to packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart index 61f47cf3..676cf137 100644 --- a/packages/wyatt_form_bloc/lib/src/form/form_input_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/form_input_validator.dart @@ -14,7 +14,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -part of 'form.dart'; +import 'package:equatable/equatable.dart'; +import 'package:wyatt_form_bloc/src/core/enums/form_input_status.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; + +part 'any_validator.dart'; +part 'equality_validator.dart'; +part 'nullable_validator.dart'; +part 'regex_validator.dart'; +part 'text_validator.dart'; /// {@template form_input_validator} /// A [FormInputValidator] represents the value of a single form input field. @@ -39,21 +47,21 @@ part of 'form.dart'; /// } /// ``` /// {@endtemplate} -abstract class FormInputValidator +abstract class FormInputValidator extends Equatable { const FormInputValidator._(this.value, [this.pure = true]); /// Constructor which create a `pure` [FormInputValidator] with a given value. - const FormInputValidator.pure(V value) : this._(value); + const FormInputValidator.pure(Value value) : this._(value); /// Constructor which create a `dirty` [FormInputValidator] with a /// given value. - const FormInputValidator.dirty(V value) : this._(value, false); + const FormInputValidator.dirty(Value value) : this._(value, false); /// The value of the given [FormInputValidator]. /// For example, if you have a `FormInputValidator` for `FirstName`, /// the value could be 'Joe'. - final V value; + final Value? value; /// If the [FormInputValidator] is pure (has been touched/modified). /// Typically when the `FormInputValidator` is initially created, @@ -80,7 +88,7 @@ abstract class FormInputValidator /// Returns a validation error if the [FormInputValidator] is invalid. /// Returns `null` if the [FormInputValidator] is valid. - E? get error => validator(value); + Error? get error => validator(value); /// Whether the [FormInputValidator] value is valid according to the /// overridden `validator`. @@ -96,11 +104,11 @@ abstract class FormInputValidator /// A function that must return a validation error if the provided /// [value] is invalid and `null` otherwise. - E? validator(V value); - - @override - bool? get stringify => true; + Error? validator(Value? value); @override List get props => [value, pure]; + + @override + String toString() => 'value: $value, status: ${status.name}'; } diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/enum_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/nullable_validator.dart similarity index 57% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/enum_validator.dart rename to packages/wyatt_form_bloc/lib/src/domain/input_validators/nullable_validator.dart index 63c3ef60..e478e2ec 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/enum_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/nullable_validator.dart @@ -14,19 +14,24 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/validation_error.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/text_validator.dart'; +part of 'form_input_validator.dart'; -class EnumValidator extends TextValidator { - /// {@macro text_string} - const EnumValidator.pure() : super.pure(); +/// {@template nullable_validator} +/// Abstract nullable validator not validating null values. +/// {@endtemplate} +abstract class NullableValidator + extends FormInputValidator { + const NullableValidator.pure(super.value) : super.pure(); + const NullableValidator.dirty(super.value) : super.dirty(); - /// {@macro text_string} - EnumValidator.dirty(E value) : super.dirty(value.toString()); + /// If value is null. + E get onNull; @override - ValidationStandardError get onEmpty => ValidationStandardError.empty; - - @override - ValidationStandardError get onNull => ValidationStandardError.invalid; + E? validator(O? value) { + if (value == null) { + return onNull; + } + return null; + } } diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/base/regex_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/regex_validator.dart similarity index 80% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/base/regex_validator.dart rename to packages/wyatt_form_bloc/lib/src/domain/input_validators/regex_validator.dart index 16d41ab2..971e9566 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/base/regex_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/regex_validator.dart @@ -14,20 +14,21 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/validation_error.dart'; -import 'package:wyatt_form_bloc/src/form/form.dart'; +part of 'form_input_validator.dart'; /// {@template regex_validator} /// Abstract regex validator for form input. /// {@endtemplate} abstract class RegexValidator - extends FormInputValidator { - const RegexValidator.pure() : super.pure(''); - const RegexValidator.dirty([super.value = '']) : super.dirty(); + extends FormInputValidator { + const RegexValidator.pure(super.value) : super.pure(); + const RegexValidator.dirty(super.value) : super.dirty(); RegExp get regex; + /// If the value is **not** null, but empty. E get onEmpty; + /// If value does not conform to regex. E get onError; diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/base/text_validator.dart b/packages/wyatt_form_bloc/lib/src/domain/input_validators/text_validator.dart similarity index 78% rename from packages/wyatt_form_bloc/lib/src/validators/inputs/base/text_validator.dart rename to packages/wyatt_form_bloc/lib/src/domain/input_validators/text_validator.dart index c57697f1..6e70e027 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/base/text_validator.dart +++ b/packages/wyatt_form_bloc/lib/src/domain/input_validators/text_validator.dart @@ -14,13 +14,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:wyatt_form_bloc/src/enums/validation_error.dart'; -import 'package:wyatt_form_bloc/src/form/form.dart'; +part of 'form_input_validator.dart'; abstract class TextValidator - extends FormInputValidator { - const TextValidator.pure() : super.pure(''); - const TextValidator.dirty([super.value = '']) : super.dirty(); + extends FormInputValidator { + const TextValidator.pure(super.value) : super.pure(); + const TextValidator.dirty(super.value) : super.dirty(); /// If the value is **not** null, but empty. E get onEmpty; diff --git a/packages/wyatt_form_bloc/lib/src/domain/repositories/form_repository.dart b/packages/wyatt_form_bloc/lib/src/domain/repositories/form_repository.dart new file mode 100644 index 00000000..3b5f1f05 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/domain/repositories/form_repository.dart @@ -0,0 +1,27 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:wyatt_architecture/wyatt_architecture.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; + +abstract class FormRepository extends BaseRepository { + Map get runtimeForms; + + void registerForm(WyattForm form); + void updateForm(WyattForm form); + WyattForm accessForm(String formName); + void unregisterForm(String formName); +} diff --git a/packages/wyatt_form_bloc/lib/src/form/form_data.dart b/packages/wyatt_form_bloc/lib/src/form/form_data.dart deleted file mode 100644 index 86e67940..00000000 --- a/packages/wyatt_form_bloc/lib/src/form/form_data.dart +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -part of 'form.dart'; - -class FormData extends Equatable { - final List _inputs; - - const FormData(this._inputs); - const FormData.empty() : this(const []); - - /// Returns all inputs as a list - List inputs() => _inputs; - - /// Returns the input for the associated key - FormInput inputOf(String key) { - if (contains(key)) { - return _inputs.firstWhere((input) => input.key == key); - } else { - throw Exception('FormInput with key `$key` does not exist in form'); - } - } - - /// Updates a input (perform a replace at index). - void updateInput(String key, FormInput input) { - if (contains(key)) { - final index = _inputs.indexOf( - inputOf(key), - ); - _inputs[index] = input; - } - } - - /// Returns all associated validators as a list - List> validators() => - _inputs - .map>( - (input) => input.validator as FormInputValidator, - ) - .toList(); - - /// A [FormInputValidator] represents the value of a single form input field. - /// It contains information about the [FormInputStatus], value, as well - /// as validation status. - T validatorOf(String key) => inputOf(key).validator as T; - - /// Updates validator of a given input. (perform copyWith) - void updateValidator( - String key, - FormInputValidator dirtyValue, - ) { - if (contains(key)) { - final index = _inputs.indexOf( - inputOf(key), - ); - _inputs[index] = _inputs[index].copyWith(validator: dirtyValue); - } - } - - /// Returns a validation error if the [FormInputValidator] is invalid. - /// Returns null if the [FormInputValidator] is valid. - E? errorOf(String key) => - (inputOf(key).validator as FormInputValidator).error; - - /// The value of the associated [FormInputValidator]. For example, - /// if you have a FormInputValidator for FirstName, the value could be 'Joe'. - V valueOf(String key) => - (inputOf(key).validator as FormInputValidator).value; - - /// Returns `true` if the [FormInputValidator] is not valid. - /// Same as `E? errorOf(String key) != null` - bool isNotValid(String key) => !inputOf(key).validator.valid; - - /// Returns all associated metadata as a list - List> metadata() => _inputs - .map>( - (input) => input.metadata as FormInputMetadata, - ) - .toList(); - - /// Returns the metadata associated. With `M` the type of extra data. - FormInputMetadata metadataOf(String key) => - inputOf(key).metadata as FormInputMetadata; - - /// Updates metadata of a given input. (perform copyWith) - void updateMetadata(String key, FormInputMetadata meta) { - if (contains(key)) { - final index = _inputs.indexOf( - inputOf(key), - ); - _inputs[index] = _inputs[index].copyWith(metadata: meta); - } - } - - /// Check if this contains an input with the given key. - bool contains(String key) => _inputs.any((input) => input.key == key); - - /// Makes an intersection set operation and returns newly created [FormData] - FormData intersection(FormData other) { - final List inputs = []; - - for (final FormInput i in _inputs) { - if (other.contains(i.key)) { - inputs.add(i); - } - } - - return FormData(inputs); - } - - /// Makes a difference set operation and returns newly created [FormData] - FormData difference(FormData other) { - final List inputs = []; - - for (final FormInput i in other._inputs) { - if (!contains(i.key)) { - inputs.add(i); - } - } - - for (final FormInput i in _inputs) { - if (!other.contains(i.key)) { - inputs.add(i); - } - } - - return FormData(inputs); - } - - /// Makes an union set operation and returns newly created [FormData] - FormData union(FormData other) { - final List inputs = []; - - for (final FormInput i in _inputs) { - inputs.add(i); - } - - for (final FormInput i in other._inputs) { - if (!contains(i.key)) { - inputs.add(i); - } - } - - return FormData(inputs); - } - - /// Deeply copy this. - FormData clone() => FormData( - _inputs.map((input) => input.clone()).toList(), - ); - - /// Export this to [Map] format. - Map toMap() { - final map = {}; - for (final input in _inputs) { - if (input.metadata.export) { - map[input.name] = input.validator.value; - } - } - return map; - } - - /// Export this to [String] format. - String toJson() => jsonEncode(toMap()); - - @override - bool? get stringify => true; - - @override - List get props => _inputs; -} diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart new file mode 100644 index 00000000..3af6c99b --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_cubit.dart @@ -0,0 +1,49 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'dart:async'; + +import 'package:equatable/equatable.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/core/enums/set_operations.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; + +part 'form_data_state.dart'; + +abstract class FormDataCubit extends Cubit { + FormDataCubit(super.initialState) : super(); + + String get formName; + + FutureOr dataChanged( + String key, + FormInputValidator dirtyValue, + ); + + FutureOr update( + WyattForm form, { + SetOperation operation = SetOperation.replace, + }); + + FutureOr validate(); + + FutureOr reset(); + + FutureOr submit(); +} diff --git a/packages/wyatt_form_bloc/lib/src/cubit/form_data_state.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_state.dart similarity index 69% rename from packages/wyatt_form_bloc/lib/src/cubit/form_data_state.dart rename to packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_state.dart index 4629b0e6..57ab4c95 100644 --- a/packages/wyatt_form_bloc/lib/src/cubit/form_data_state.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data/form_data_state.dart @@ -16,35 +16,22 @@ part of 'form_data_cubit.dart'; -class FormDataState extends Equatable { +abstract class FormDataState extends Equatable { /// Global status of a form. final FormStatus status; - + /// FormData with all inputs, and associated metadata. - final FormData data; + final WyattForm form; /// Optional error message. final String? errorMessage; const FormDataState({ - required this.data, + required this.form, this.status = FormStatus.pure, this.errorMessage, }); - FormDataState copyWith({ - FormStatus? status, - FormData? data, - String? errorMessage, - }) => FormDataState( - status: status ?? this.status, - data: data ?? this.data, - errorMessage: errorMessage ?? this.errorMessage, - ); - @override - bool? get stringify => true; - - @override - List get props => [status, data, errorMessage]; + List get props => [status, form, errorMessage]; } diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_cubit_impl.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_cubit_impl.dart new file mode 100644 index 00000000..2eb50aa7 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_cubit_impl.dart @@ -0,0 +1,98 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'dart:async'; + +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/core/enums/set_operations.dart'; +import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart'; +import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart'; +import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart'; +import 'package:wyatt_form_bloc/src/domain/repositories/form_repository.dart'; +import 'package:wyatt_form_bloc/src/presentation/features/form_data/form_data_cubit.dart'; + +part 'form_data_state_impl.dart'; + +abstract class FormDataCubitImpl extends FormDataCubit { + final FormRepository _formRepository; + final String _formName; + + FormDataCubitImpl(this._formRepository, this._formName) + : super(FormDataStateImpl(form: _formRepository.accessForm(_formName))); + + @override + String get formName => _formName; + + @override + FutureOr dataChanged( + String key, + FormInputValidator dirtyValue, + ) { + final form = _formRepository.accessForm(_formName).clone(); + + try { + form.updateValidator(key, dirtyValue); + _formRepository.updateForm(form); + } catch (e) { + rethrow; + } + + emit( + state.copyWith( + form: form, + status: form.validate(), + ), + ); + } + + @override + FutureOr update( + WyattForm form, { + SetOperation operation = SetOperation.replace, + }) { + final WyattForm current = _formRepository.accessForm(_formName).clone(); + final WyattForm newForm = operation.operation.call(current, form); + _formRepository.updateForm(newForm); + + emit( + state.copyWith( + form: newForm, + status: newForm.validate(), + ), + ); + } + + @override + FutureOr reset() { + final form = state.form.reset(); + _formRepository.updateForm(form); + emit( + state.copyWith( + form: form, + status: form.validate(), + ), + ); + } + + @override + FutureOr validate() { + emit( + state.copyWith( + status: state.form.validate(), + ), + ); + } +} diff --git a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_state.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart similarity index 55% rename from packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_state.dart rename to packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart index f05f2caf..e31750ce 100644 --- a/packages/wyatt_authentication_bloc/lib/src/features/email_verification/cubit/email_verification_state.dart +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/form_data_impl/form_data_state_impl.dart @@ -14,29 +14,30 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -part of 'email_verification_cubit.dart'; +part of 'form_data_cubit_impl.dart'; -class EmailVerificationState extends Equatable { - final bool isVerified; - final FormStatus status; - final String? errorMessage; - - const EmailVerificationState({ - this.isVerified = false, - this.status = FormStatus.pure, - this.errorMessage, +class FormDataStateImpl extends FormDataState { + const FormDataStateImpl({ + required super.form, + super.status = FormStatus.pure, + super.errorMessage, }); - EmailVerificationState copyWith({ - bool? isVerified, + FormDataStateImpl copyWith({ FormStatus? status, + WyattForm? form, String? errorMessage, - }) => EmailVerificationState( - isVerified: isVerified ?? this.isVerified, - status: status ?? this.status, - errorMessage: errorMessage ?? this.errorMessage, - ); + }) => + FormDataStateImpl( + status: status ?? this.status, + form: form ?? this.form, + errorMessage: errorMessage ?? this.errorMessage, + ); @override - List get props => [isVerified, status]; + List get props => [status, form, errorMessage]; + + @override + String toString() => 'FormDataSate(status: ${status.name} ' + '${(errorMessage != null) ? " [$errorMessage]" : ""}, $form)'; } diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder.dart new file mode 100644 index 00000000..c6cb9006 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder.dart @@ -0,0 +1,43 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; + +class InputBuilder extends StatelessWidget { + const InputBuilder({required this.field, required this.builder, super.key}); + + final String field; + + final Widget Function( + BuildContext context, + Cubit cubit, + FormDataState state, + String field, + bool inputValid, + ) builder; + + @override + Widget build(BuildContext context) => + BlocBuilder( + builder: (context, state) { + final cubit = context.watch(); + final inputValid = state.form.validatorOf(field).valid; + return builder.call(context, cubit, state, field, inputValid); + }, + ); +} diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_metadata.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_metadata.dart new file mode 100644 index 00000000..123287fc --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_metadata.dart @@ -0,0 +1,57 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input_metadata.dart'; +import 'package:wyatt_form_bloc/src/presentation/presentation.dart'; + +class InputBuilderMetadata + extends StatelessWidget { + const InputBuilderMetadata({ + required this.field, + required this.builder, + super.key, + }); + + final String field; + + final Widget Function( + BuildContext context, + Cubit cubit, + FormDataState state, + String field, + bool inputValid, + FormInputMetadata? metadata, + ) builder; + + @override + Widget build(BuildContext context) => BlocBuilder( + builder: (context, state) { + final cubit = context.read(); + final inputValid = state.form.validatorOf(field).valid; + final metadata = state.form.metadataOf(field); + return builder.call( + context, + cubit, + state, + field, + inputValid, + metadata, + ); + }, + ); +} diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_text_controller.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_text_controller.dart new file mode 100644 index 00000000..17f5c16e --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/input_builder_text_controller.dart @@ -0,0 +1,75 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_form_bloc/src/domain/entities/form_input_metadata.dart'; +import 'package:wyatt_form_bloc/src/domain/repositories/form_repository.dart'; +import 'package:wyatt_form_bloc/src/presentation/features/form_data/form_data_cubit.dart'; + +class InputBuilderTextController extends StatelessWidget { + InputBuilderTextController({ + required this.field, + required this.builder, + super.key, + }); + + final String field; + + final Widget Function( + BuildContext context, + Cubit cubit, + FormDataState state, + String field, + bool inputValid, + TextEditingController textEditingController, + FormInputMetadata? metadata, + ) builder; + + final TextEditingController _controller = TextEditingController(); + + @override + Widget build(BuildContext context) { + final formName = context.watch().formName; + final value = + context.read().accessForm(formName).valueOf(field); + _controller + ..text = value ?? '' + ..selection = TextSelection.fromPosition( + TextPosition( + offset: _controller.text.length, + ), + ); + + return BlocBuilder( + builder: (context, state) { + final cubit = context.read(); + final inputValid = state.form.validatorOf(field).valid; + final metadata = state.form.metadataOf(field); + return builder.call( + context, + cubit, + state, + field, + inputValid, + _controller, + metadata, + ); + }, + ); + } +} diff --git a/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/submit_builder.dart b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/submit_builder.dart new file mode 100644 index 00000000..ed1abd42 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/features/widgets/submit_builder.dart @@ -0,0 +1,37 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wyatt_form_bloc/src/core/enums/form_status.dart'; +import 'package:wyatt_form_bloc/src/presentation/features/form_data/form_data_cubit.dart'; + +class SubmitBuilder extends StatelessWidget { + const SubmitBuilder({required this.builder, super.key}); + + final Widget Function(BuildContext context, Cubit cubit, FormStatus status) + builder; + + @override + Widget build(BuildContext context) => BlocBuilder( + buildWhen: (previous, current) => previous.status != current.status, + builder: (context, state) => builder.call( + context, + context.read(), + state.status, + ), + ); +} diff --git a/packages/wyatt_form_bloc/lib/src/presentation/presentation.dart b/packages/wyatt_form_bloc/lib/src/presentation/presentation.dart new file mode 100644 index 00000000..e0b0377d --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/presentation/presentation.dart @@ -0,0 +1,22 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +export 'features/form_data/form_data_cubit.dart'; +export 'features/form_data_impl/form_data_cubit_impl.dart'; +export 'features/widgets/input_builder.dart'; +export 'features/widgets/input_builder_metadata.dart'; +export 'features/widgets/input_builder_text_controller.dart'; +export 'features/widgets/submit_builder.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/src.dart b/packages/wyatt_form_bloc/lib/src/src.dart index dd7f4605..c75563a1 100644 --- a/packages/wyatt_form_bloc/lib/src/src.dart +++ b/packages/wyatt_form_bloc/lib/src/src.dart @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -export 'cubit/form_data_cubit.dart'; -export 'enums/enums.dart'; -export 'form/form.dart'; -export 'validators/validators.dart'; +export 'core/core.dart'; +export 'data/data.dart'; +export 'domain/domain.dart'; +export 'presentation/presentation.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/iban.dart b/packages/wyatt_form_bloc/lib/src/validators/inputs/iban.dart deleted file mode 100644 index 74bef3e3..00000000 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/iban.dart +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart'; - -/// {@template iban} -/// Form input for an IBAN input. -/// {@endtemplate} -class Iban extends RegexValidator { - /// {@macro iban} - const Iban.pure() : super.pure(); - - /// {@macro iban} - const Iban.dirty([super.value = '']) : super.dirty(); - - @override - ValidationStandardError get onEmpty => ValidationStandardError.empty; - @override - ValidationStandardError get onError => ValidationStandardError.invalid; - - @override - RegExp get regex => RegExp( - r'^(?:((?:IT|SM)\d{2}[A-Z]{1}\d{22})|(NL\d{2}[A-Z]{4}\d{10})|(LV\d{2}[A-Z]{4}\d{13})|((?:BG|GB|IE)\d{2}[A-Z]{4}\d{14})|(GI\d{2}[A-Z]{4}\d{15})|(RO\d{2}[A-Z]{4}\d{16})|(MT\d{2}[A-Z]{4}\d{23})|(NO\d{13})|((?:DK|FI)\d{16})|((?:SI)\d{17})|((?:AT|EE|LU|LT)\d{18})|((?:HR|LI|CH)\d{19})|((?:DE|VA)\d{20})|((?:AD|CZ|ES|MD|SK|SE)\d{22})|(PT\d{23})|((?:IS)\d{24})|((?:BE)\d{14})|((?:FR|MC|GR)\d{25})|((?:PL|HU|CY)\d{26}))$', - ); -} diff --git a/packages/wyatt_form_bloc/lib/src/validators/inputs/list_option.dart b/packages/wyatt_form_bloc/lib/src/validators/inputs/list_option.dart deleted file mode 100644 index 00ddd74b..00000000 --- a/packages/wyatt_form_bloc/lib/src/validators/inputs/list_option.dart +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/form/form.dart'; - -/// {@template list_option} -/// Form input for a list input -/// {@endtemplate} -class ListOption - extends FormInputValidator, ValidationStandardError> { - /// {@macro list_option} - const ListOption.pure({List? defaultValue}) - : super.pure(defaultValue ?? const []); - - /// {@macro list_option} - const ListOption.dirty({List? value}) : super.dirty(value ?? const []); - - ListOption select(T? v) { - if (v == null) { - return this; - } - if (value.contains(v)) { - final List newValue = List.from(value)..remove(v); - return ListOption.dirty(value: newValue); - } else { - final List newValue = List.from(value)..add(v); - return ListOption.dirty(value: newValue); - } - } - - @override - ValidationStandardError? validator(List? value) => - value?.isNotEmpty ?? false == true - ? null - : ValidationStandardError.invalid; -} diff --git a/packages/wyatt_form_bloc/lib/src/validators/validators.dart b/packages/wyatt_form_bloc/lib/src/validators/validators.dart deleted file mode 100644 index b9eaa4b6..00000000 --- a/packages/wyatt_form_bloc/lib/src/validators/validators.dart +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -export 'form/every_input_validator.dart'; -export 'inputs/base/regex_validator.dart'; -export 'inputs/base/text_validator.dart'; -export 'inputs/boolean.dart'; -export 'inputs/confirmed_password.dart'; -export 'inputs/email.dart'; -export 'inputs/enum_validator.dart'; -export 'inputs/iban.dart'; -export 'inputs/list_option.dart'; -export 'inputs/name.dart'; -export 'inputs/password.dart'; -export 'inputs/phone.dart'; -export 'inputs/siren.dart'; -export 'inputs/text_string.dart'; diff --git a/packages/wyatt_form_bloc/pubspec.yaml b/packages/wyatt_form_bloc/pubspec.yaml index 7b1e7c2a..c9c7afa9 100644 --- a/packages/wyatt_form_bloc/pubspec.yaml +++ b/packages/wyatt_form_bloc/pubspec.yaml @@ -3,18 +3,33 @@ description: Manage forms in Dart & Flutter with Bloc repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_form_bloc version: 0.0.6 +publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub + environment: - sdk: '>=2.17.2 <3.0.0' + sdk: ">=2.17.2 <3.0.0" dependencies: - bloc: ^8.1.0 + flutter: + sdk: flutter + + flutter_bloc: ^8.1.0 equatable: ^2.0.5 -dev_dependencies: - test: ^1.21.4 - - wyatt_analysis: + wyatt_architecture: git: url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - ref: wyatt_analysis-v2.2.2 - path: packages/wyatt_analysis + ref: wyatt_architecture-v0.0.2-dev.0 + path: packages/wyatt_architecture + + wyatt_type_utils: + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ + version: 0.0.3+1 + + +dev_dependencies: + flutter_test: + sdk: flutter + + wyatt_analysis: + hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ + version: 2.2.2