Merge pull request 'auth/wyatt_arch_migration' (#25) from auth/wyatt_arch_migration into master

Reviewed-on: #25
This commit is contained in:
Hugo Pointcheval 2022-11-10 18:40:27 +00:00
commit 92f8b2916c
164 changed files with 4283 additions and 2287 deletions

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
</dict>
</plist>

View File

@ -0,0 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

View File

@ -0,0 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

View File

@ -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

View File

@ -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

View File

@ -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 = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
/* 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 = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
66B357379C2757D2844F12BB /* Pods */,
BC1E25CE0DADDF7B7201CCF8 /* Frameworks */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
);
name = Products;
sourceTree = "<group>";
};
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 = "<group>";
};
BC1E25CE0DADDF7B7201CCF8 /* Frameworks */ = {
isa = PBXGroup;
children = (
B0A061B2E527F311149C3581 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* 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 = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* 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 */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@ -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)
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

View File

@ -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.

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Example Router</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>example_router</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1 @@
#import "GeneratedPluginRegistrant.h"

View File

@ -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"
}

View File

@ -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<void> bootstrap(FutureOr<Widget> Function() builder) async {
await runZonedGuarded(
() async {
WidgetsFlutterBinding.ensureInitialized();
Bloc.observer = AppBlocObserver();
FlutterError.onError = (details) {
debugPrint(details.toString());
@ -29,9 +30,7 @@ Future<void> bootstrap(FutureOr<Widget> Function() builder) async {
options: DefaultFirebaseOptions.currentPlatform,
);
GoRouter.setUrlPathStrategy(UrlPathStrategy.path);
Bloc.observer = AppBlocObserver();
await GetItInitializer.init();
runApp(await builder());
},

View File

@ -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 <https://www.gnu.org/licenses/>.
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<void> init() async {
getIt
..registerLazySingleton<AuthenticationRemoteDataSource>(
() => AuthenticationFirebaseDataSourceImpl(),
)
..registerLazySingleton<AuthenticationCacheDataSource<int>>(
() => AuthenticationCacheDataSourceImpl<int>(),
);
await getIt.allReady();
}
}

View File

@ -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<void>(export: false),
),
]);
}

View File

@ -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',
);
}

View File

@ -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<int?> onSignUpSuccess(
Account? account,
WyattForm form,
) async {
const id = -1;
final confirmedPassword =
form.valueOf<String?>(AppFormField.confirmedPassword);
debugPrint(
'onSignUpSuccess: $account, generatedId: $id, extraFormData: $confirmedPassword');
return const Ok<int, AppException>(id);
}
FutureResult<int?> onAccountChanges(Account? account) async {
final id = Random().nextInt(1000);
debugPrint('onAccountChanges: $account, generatedId: $id');
return Ok<int, AppException>(id);
}
class App extends StatelessWidget {
final AuthenticationRepository authenticationRepository =
AuthenticationRepositoryFirebase();
final AuthenticationRepository<int> authenticationRepository =
AuthenticationRepositoryImpl(
authenticationCacheDataSource: getIt<AuthenticationCacheDataSource<int>>(),
authenticationRemoteDataSource: getIt<AuthenticationRemoteDataSource>(),
onSignUpSuccess: onSignUpSuccess,
onAuthChange: onAccountChanges,
extraSignUpInputs: [
FormInput(
AppFormField.confirmedPassword,
const ConfirmedPassword.pure(),
metadata: const FormInputMetadata<void>(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<int> 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<AuthenticationCubit>.value(
value: authenticationCubit..init(),
BlocProvider<AuthenticationCubit<int>>.value(
value: authenticationCubit,
),
BlocProvider<SignUpCubit>(
BlocProvider<SignUpCubit<int>>(
create: (_) => SignUpCubit(
authenticationRepository: authenticationRepository,
formData: Forms.getNormalData(),
onSignUpSuccess: (state, uid) async {
debugPrint(state.toString());
debugPrint(uid);
},
),
),
BlocProvider<SignInCubit>(
BlocProvider<SignInCubit<int>>(
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<dynamic> stream) {
notifyListeners();
_subscription = stream.asBroadcastStream().listen(
(dynamic _) => notifyListeners(),
);
}
late final StreamSubscription<dynamic> _subscription;
@override
void dispose() {
_subscription.cancel();
super.dispose();
}
}

View File

@ -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<AuthenticationCubit>().logOut(),
onPressed: () => context.read<AuthenticationCubit<int>>().signOut(),
icon: const Icon(Icons.logout_rounded))
],
),
@ -34,11 +34,12 @@ class HomePage extends StatelessWidget {
child: SingleChildScrollView(
child: Column(
children: [
BlocBuilder<AuthenticationCubit, AuthenticationState>(
builder: (context, state) {
final email = state.user?.email;
return Text('Logged as $email');
},
AuthenticationBuilder<int>(
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,

View File

@ -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<SignInCubit, SignInState>(
buildWhen: (previous, current) => previous.email != current.email,
builder: (context, state) {
return InputBuilder<SignInCubit<int>>(
field: AuthFormField.email,
builder: ((context, cubit, state, field, inputValid) {
return TextField(
onChanged: (email) => context.read<SignInCubit>().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<SignInCubit, SignInState>(
buildWhen: (previous, current) => previous.password != current.password,
builder: (context, state) {
return InputBuilder<SignInCubit<int>>(
field: AuthFormField.password,
builder: ((context, cubit, state, field, inputValid) {
return TextField(
onChanged: (password) {
context.read<SignInCubit>().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<SignInCubit, SignInState>(
builder: (context, state) {
return state.status.isSubmissionInProgress
return SubmitBuilder<SignInCubit<int>>(
builder: ((context, cubit, status) {
return status.isSubmissionInProgress
? const CircularProgressIndicator()
: ElevatedButton(
onPressed: state.status.isValidated
? () =>
context.read<SignInCubit>().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<SignInCubit, SignInState>(
return BlocListener<SignInCubit<int>, 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(

View File

@ -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<SignUpCubit, SignUpState>(
buildWhen: (previous, current) => previous.email != current.email,
builder: (context, state) {
return InputBuilder<SignUpCubit<int>>(
field: AuthFormField.email,
builder: ((context, cubit, state, field, inputValid) {
return TextField(
onChanged: (email) => context.read<SignUpCubit>().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<SignUpCubit, SignUpState>(
buildWhen: (previous, current) => previous.password != current.password,
builder: (context, state) {
return InputBuilder<SignUpCubit<int>>(
field: AuthFormField.password,
builder: ((context, cubit, state, field, inputValid) {
return TextField(
onChanged: (password) {
context.read<SignUpCubit>().passwordChanged(password);
context.read<SignUpCubit>().dataChanged(
AppFormField.confirmedPassword,
ConfirmedPassword.dirty(
password: password,
value: context
.read<SignUpCubit>()
.state
.data
.valueOf<String>(
AppFormField.confirmedPassword),
),
);
onChanged: (pwd) {
cubit.passwordChanged(pwd);
cubit.dataChanged(
AppFormField.confirmedPassword,
ConfirmedPassword.dirty(
password: pwd,
value: state.form
.valueOf<String?>(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<SignUpCubit, SignUpState>(
builder: (context, state) {
return InputBuilder<SignUpCubit<int>>(
field: AppFormField.confirmedPassword,
builder: ((context, cubit, state, field, inputValid) {
return TextField(
onChanged: (confirmPassword) => context
.read<SignUpCubit>()
.dataChanged(
AppFormField.confirmedPassword,
ConfirmedPassword.dirty(
password: context.read<SignUpCubit>().state.password.value,
value: confirmPassword,
),
),
onChanged: (pwd) {
cubit.dataChanged(
field,
ConfirmedPassword.dirty(
password:
state.form.valueOf<String?>(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<SignUpCubit, SignUpState>(
builder: (context, state) {
return state.status.isSubmissionInProgress
return SubmitBuilder<SignUpCubit<int>>(
builder: ((context, cubit, status) {
return status.isSubmissionInProgress
? const CircularProgressIndicator()
: ElevatedButton(
onPressed: state.status.isValidated
? () => context.read<SignUpCubit>().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<SignUpCubit, SignUpState>(
return BlocListener<SignUpCubit<int>, 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(

View File

@ -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<AuthenticationCubit>().logOut(),
onPressed: () => context.read<AuthenticationCubit<int>>().signOut(),
icon: const Icon(Icons.logout_rounded))
],
),

View File

@ -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<AuthenticationCubit>().changeStatus(
context.read<AuthenticationCubit>().state.user!),
icon: const Icon(Icons.refresh_rounded))
],
),
body: SingleChildScrollView(
child: Column(

View File

@ -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:

View File

@ -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 <https://www.gnu.org/licenses/>.
abstract class AuthFormField {
static const email = 'wyattEmailField';
static const password = 'wyattPasswordField';
}

View File

@ -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 <https://www.gnu.org/licenses/>.
abstract class AuthFormName {
static const String signUpForm = 'wyattSignUpForm';
static const String signInForm = 'wyattSignInForm';
}

View File

@ -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 <https://www.gnu.org/licenses/>.
export 'constants/form_field.dart';
export 'constants/form_name.dart';
export 'enums/enums.dart';
export 'exceptions/exceptions.dart';
export 'utils/utils.dart';

View File

@ -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 <https://www.gnu.org/licenses/>.
enum AuthenticationStatus {
unknown,
authenticated,
unauthenticated,
}

View File

@ -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 <https://www.gnu.org/licenses/>.
export 'cubit/email_verification_cubit.dart';
export 'authentication_status.dart';

View File

@ -14,13 +14,18 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
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();

View File

@ -14,133 +14,130 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
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();
}

View File

@ -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 <https://www.gnu.org/licenses/>.
enum AuthCubitStatus {
started,
stoped,
}
export 'cryptography.dart';

View File

@ -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 <https://www.gnu.org/licenses/>.
export 'data_sources/data_sources.dart';
export 'models/models.dart';
export 'repositories/repositories.dart';

View File

@ -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 <https://www.gnu.org/licenses/>.
export 'local/authentication_cache_data_source_impl.dart';
export 'remote/authentication_firebase_data_source_impl.dart';

View File

@ -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 <https://www.gnu.org/licenses/>.
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<T extends Object>
extends AuthenticationCacheDataSource<T> {
Account? _account;
T? _data;
AuthenticationCacheDataSourceImpl();
@override
Future<void> storeAccount(Account? account) async {
_account = account;
}
@override
Future<void> storeData(T? data) async {
_data = data;
}
@override
Future<Account> loadAccount() async {
if (_account.isNotNull) {
return _account!;
}
throw ClientException('Cached account is invalid');
}
@override
Future<T> loadData() async {
if (_data.isNotNull) {
return _data!;
}
throw ClientException('Cached data is invalid');
}
@override
Future<void> destroy() async {
_data = null;
_account = null;
}
@override
Future<AccountWrapper<T>> load() async {
if (_account.isNull) {
throw ClientException('Cached account is invalid');
}
return AccountWrapperModel(_account, _data);
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
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<Account> 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<Account> 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<void> signOut() async {
try {
await _firebaseAuth.signOut();
} catch (_) {
throw SignOutFailureFirebase();
}
}
@override
Future<String> 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<Account?> streamAccount() =>
_firebaseAuth.userChanges().map<Account?>((user) {
final Account? account = (user.isNotNull) ? _mapper(user!) : null;
return account;
});
}

View File

@ -14,16 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
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});
}

View File

@ -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 <https://www.gnu.org/licenses/>.
import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
import 'package:wyatt_authentication_bloc/src/domain/entities/account_wrapper.dart';
class AccountWrapperModel<T> extends AccountWrapper<T> {
@override
final Account? account;
@override
final T? data;
AccountWrapperModel(this.account, this.data);
}

View File

@ -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 <https://www.gnu.org/licenses/>.
export 'account_model.dart';
export 'account_wrapper_model.dart';

View File

@ -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 <https://www.gnu.org/licenses/>.
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)';
}

View File

@ -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 <https://www.gnu.org/licenses/>.
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<AuthCubitStatus>();
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<AuthCubitStatus> get cubitStatus =>
_controller.stream.asBroadcastStream();
@override
void changeCubitStatus(AuthCubitStatus status) =>
_controller.sink.add(status);
@override
Stream<wyatt.User> 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<void> applyActionCode(String code) async {
try {
await _firebaseAuth.applyActionCode(code);
} on FirebaseAuthException catch (e) {
throw ApplyActionCodeFailureFirebase.fromCode(e.code);
} catch (_) {
throw ApplyActionCodeFailureFirebase();
}
}
@override
Future<String?> 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<List<String>> 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<void> signInAnonymously() async {
try {
await _firebaseAuth.signInAnonymously();
} on FirebaseAuthException catch (e) {
throw SignInAnonymouslyFailureFirebase.fromCode(e.code);
} catch (_) {
throw SignInAnonymouslyFailureFirebase();
}
}
@override
Future<void> 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<void> 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<void> 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<void> 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<void> 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<void> 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<void> sendEmailVerification() async {
try {
await _userCache.inner!.sendEmailVerification();
} catch (e) {
throw SendEmailVerificationFailureFirebase();
}
}
@override
Future<void> 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<void> sendSignInLinkEmail({required String email}) async {
try {
// TODO(hpcl): implement sendSignInLinkEmail
} on FirebaseAuthException catch (e) {
throw SendSignInLinkEmailFailureFirebase.fromCode(e.code);
} catch (_) {
throw SendSignInLinkEmailFailureFirebase();
}
}
@override
Future<void> 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<void> verifyPasswordResetCode({required String code}) async {
try {
await _firebaseAuth.verifyPasswordResetCode(code);
} on FirebaseAuthException catch (e) {
throw VerifyPasswordResetCodeFailureFirebase.fromCode(e.code);
} catch (_) {
throw VerifyPasswordResetCodeFailureFirebase();
}
}
@override
Future<void> signOut() async {
try {
await Future.wait([
_firebaseAuth.signOut(),
]);
_userCache = const UserFirebase.empty();
} catch (_) {
throw SignOutFailureFirebase();
}
}
@override
Future<void> refresh() async {
try {
await _userCache.inner!.reload();
} on FirebaseAuthException catch (e) {
throw RefreshFailureFirebase.fromCode(e.code);
} catch (_) {
throw RefreshFailureFirebase();
}
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
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<T> = FutureResult<T?> Function(
Account? account,
WyattForm form,
);
typedef OnAuthChange<T> = FutureResult<T?> Function(Account? account);
class AuthenticationRepositoryImpl<T extends Object>
extends AuthenticationRepository<T> {
final AuthenticationCacheDataSource<T> _authenticationLocalDataSource;
final AuthenticationRemoteDataSource _authenticationRemoteDataSource;
late FormRepository _formRepository;
final OnSignUpSuccess<T>? _onSignUpSuccess;
final OnAuthChange<T>? _onAccountChanges;
AuthenticationRepositoryImpl({
required AuthenticationCacheDataSource<T> authenticationCacheDataSource,
required AuthenticationRemoteDataSource authenticationRemoteDataSource,
FormRepository? formRepository,
// ignore: strict_raw_type
List<FormInput>? extraSignUpInputs,
OnSignUpSuccess<T>? onSignUpSuccess,
OnAuthChange<T>? 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<Account> signInWithEmailAndPassword({
required String email,
required String password,
}) =>
Result.tryCatchAsync<Account, AppException, AppException>(
() async {
final account =
await _authenticationRemoteDataSource.signInWithEmailAndPassword(
email: email,
password: password,
);
await _authenticationLocalDataSource.storeAccount(account);
return account;
},
(error) => error,
);
@override
FutureResult<void> signOut() =>
Result.tryCatchAsync<void, AppException, AppException>(
() async {
await _authenticationRemoteDataSource.signOut();
await _authenticationLocalDataSource.destroy();
},
(error) => error,
);
@override
FutureResult<Account> signUp({
required String email,
required String password,
}) =>
Result.tryCatchAsync<Account, AppException, AppException>(
() 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<void> destroyCache() =>
Result.tryCatchAsync<void, AppException, AppException>(
_authenticationLocalDataSource.destroy,
(error) => error,
);
@override
FutureResult<AccountWrapper<T>> getCache() =>
Result.tryCatchAsync<AccountWrapper<T>, AppException, AppException>(
_authenticationLocalDataSource.load,
(error) => error,
);
@override
FutureResult<Account> getAccount() =>
Result.tryCatchAsync<Account, AppException, AppException>(
_authenticationLocalDataSource.loadAccount,
(error) => error,
);
@override
FutureResult<void> setAccount(
Account account,
) =>
Result.tryCatchAsync<void, AppException, AppException>(
() async {
await _authenticationLocalDataSource.storeAccount(account);
},
(error) => error,
);
@override
FutureResult<T> getData() =>
Result.tryCatchAsync<T, AppException, AppException>(
_authenticationLocalDataSource.loadData,
(error) => error,
);
@override
FutureResult<void> setData(
T? data,
) =>
Result.tryCatchAsync<void, AppException, AppException>(
() async {
await _authenticationLocalDataSource.storeData(data);
},
(error) => error,
);
@override
FutureResult<String> getIdentityToken() =>
Result.tryCatchAsync<String, AppException, AppException>(
_authenticationRemoteDataSource.getIdentityToken,
(error) => error,
);
@override
Stream<FutureResult<AccountWrapper<T>>> streamAccount() =>
_authenticationRemoteDataSource.streamAccount().map((account) async {
if (_onAccountChanges.isNotNull) {
final dataResult = await _onAccountChanges!.call(account);
return dataResult.map((data) => AccountWrapperModel(account, data));
}
return Ok<AccountWrapperModel<T>, AppException>(
AccountWrapperModel<T>(account, null),
);
});
}

View File

@ -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 <https://www.gnu.org/licenses/>.
export 'authentication_repository_impl.dart';

View File

@ -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 <https://www.gnu.org/licenses/>.
export 'local/authentication_cache_data_source.dart';
export 'remote/authentication_remote_data_source.dart';

View File

@ -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 <https://www.gnu.org/licenses/>.
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<T extends Object>
extends BaseLocalDataSource {
Future<void> storeAccount(Account? account);
Future<void> storeData(T? data);
Future<Account> loadAccount();
Future<T> loadData();
Future<AccountWrapper<T>> load();
Future<void> destroy();
}

View File

@ -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 <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/wyatt_architecture.dart';
import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
abstract class AuthenticationRemoteDataSource extends BaseRemoteDataSource {
Future<Account> signUp({
required String email,
required String password,
});
Future<Account> signInWithEmailAndPassword({
required String email,
required String password,
});
Future<void> signOut();
Stream<Account?> streamAccount();
Future<String> getIdentityToken();
}

View File

@ -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 <https://www.gnu.org/licenses/>.
export 'data_sources/data_sources.dart';
export 'entities/entities.dart';
export 'repositories/repositories.dart';

View File

@ -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 <https://www.gnu.org/licenses/>.
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;
}

View File

@ -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 <https://www.gnu.org/licenses/>.
import 'package:wyatt_architecture/wyatt_architecture.dart';
import 'package:wyatt_authentication_bloc/src/domain/entities/account.dart';
abstract class AccountWrapper<T> extends Entity {
Account? get account;
T? get data;
}

View File

@ -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 <https://www.gnu.org/licenses/>.
export 'account.dart';
export 'account_wrapper.dart';

View File

@ -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 <https://www.gnu.org/licenses/>.
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;
}

View File

@ -14,126 +14,36 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
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<AuthCubitStatus> get cubitStatus;
abstract class AuthenticationRepository<T> 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<User> 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<void> 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<String?> signUp({required String email, required String password});
/// Fetches sign in methods for [email].
///
/// Throws a [FetchSignInMethodsForEmailFailureInterface] if
/// an exception occurs.
Future<List<String>> fetchSignInMethodsForEmail({required String email});
/// Sign in anonimously.
///
/// Throws a [SignInAnonymouslyFailureInterface] if an exception occurs.
Future<void> signInAnonymously();
/// Starts the Sign In with Google Flow.
///
/// Throws a [SignInWithGoogleFailureInterface] if an exception occurs.
Future<void> signInWithGoogle();
/// Starts the Sign In with Facebook Flow.
///
/// Throws a [SignInWithFacebookFailureInterface] if an exception occurs.
Future<void> signInWithFacebook();
/// Starts the Sign In with Apple Flow.
///
/// Throws a [SignInWithAppleFailureInterface] if an exception occurs.
Future<void> signInWithApple();
/// Starts the Sign In with Twitter Flow.
///
/// Throws a [SignInWithTwitterFailureInterface] if an exception occurs.
Future<void> signInWithTwitter();
/// Signs in using an email address and email sign-in link.
///
/// Throws a [SignInWithEmailLinkFailureInterface] if an exception occurs.
Future<void> signInWithEmailLink(
String email,
String emailLink,
);
/// Signs in with the provided [email] and [password].
///
/// Throws a [SignInWithEmailAndPasswordFailureInterface] if
/// an exception occurs.
Future<void> signInWithEmailAndPassword({
FutureResult<Account> signUp({
required String email,
required String password,
});
/// Sends verification email to the provided [user].
///
/// Throws a [SendEmailVerificationFailureInterface] if an exception occurs.
Future<void> sendEmailVerification();
/// Sends a password reset email to the provided [email].
///
/// Throws a [SendPasswordResetEmailFailureInterface] if an exception occurs.
Future<void> sendPasswordResetEmail({required String email});
/// Sends link to login.
///
/// Throws a [SendSignInLinkEmailFailureInterface] if an exception occurs.
Future<void> sendSignInLinkEmail({required String email});
/// Confirms the password reset with the provided [newPassword] and [code].
///
/// Throws a [ConfirmPasswordResetFailureInterface] if an exception occurs.
Future<void> confirmPasswordReset({
required String code,
required String newPassword,
FutureResult<Account> signInWithEmailAndPassword({
required String email,
required String password,
});
/// Verify password reset code.
///
/// Throws a [VerifyPasswordResetCodeFailureInterface] if an exception occurs.
Future<void> verifyPasswordResetCode({required String code});
FutureResult<void> signOut();
/// Signs out the current user which will emit
/// [User.empty] from the [user] Stream.
Future<void> signOut();
Stream<FutureResult<AccountWrapper<T>>> streamAccount();
/// Refreshes the current user.
///
/// Throws a [RefreshFailureInterface] if an exception occurs.
Future<void> refresh();
FutureResult<String> getIdentityToken();
FutureResult<Account> getAccount();
FutureResult<void> setAccount(Account account);
FutureResult<T> getData();
FutureResult<void> setData(T? data);
FutureResult<AccountWrapper<T>> getCache();
FutureResult<void> destroyCache();
}

View File

@ -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 <https://www.gnu.org/licenses/>.
export 'authentication_repository.dart';

View File

@ -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<Extra> extends StatelessWidget {
@ -29,8 +30,7 @@ class AuthenticationBuilder<Extra> extends StatelessWidget {
final Widget Function(
BuildContext context,
User user,
Extra? extra,
AccountWrapper<Extra> accountWrapper,
) authenticated;
final Widget Function(BuildContext context) unauthenticated;
final Widget Function(BuildContext context) unknown;
@ -40,8 +40,8 @@ class AuthenticationBuilder<Extra> extends StatelessWidget {
BlocBuilder<AuthenticationCubit<Extra>, AuthenticationState<Extra>>(
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);
}

View File

@ -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<Extra> extends Cubit<AuthenticationState<Extra>> {
final AuthenticationRepository _authenticationRepository;
late final StreamSubscription<AuthCubitStatus> _statusSubscription;
StreamSubscription<User>? _userSubscription;
final Future<Extra?> Function(User user)? _onAuthSuccess;
final AuthenticationRepository<Extra> _authenticationRepository;
AuthenticationCubit({
required AuthenticationRepository authenticationRepository,
Future<Extra?> Function(User user)? onAuthSuccess,
required AuthenticationRepository<Extra> authenticationRepository,
}) : _authenticationRepository = authenticationRepository,
_onAuthSuccess = onAuthSuccess,
super(const AuthenticationState.unknown()) {
_subscribeStatus();
_listenForAuthenticationChanges();
}
Future<AuthCubitStatus> 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<void> 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<void> 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<void> close() {
_userSubscription?.cancel();
_statusSubscription.cancel();
return super.close();
FutureOr<void> signOut() {
// TODO(hpcl): maybe force unauthenticated by emitting an event
_authenticationRepository.signOut();
}
}

View File

@ -16,42 +16,28 @@
part of 'authentication_cubit.dart';
enum AuthenticationStatus {
unknown,
authenticated,
unauthenticated,
}
class AuthenticationState<Extra> extends Equatable {
final AuthenticationStatus status;
final User? user;
final Extra? extra;
final AccountWrapper<Extra>? 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<Extra> accountWrapper)
: this._(
status: AuthenticationStatus.authenticated,
user: user,
extra: extra,
accountWrapper: accountWrapper,
);
const AuthenticationState.unauthenticated()
: this._(status: AuthenticationStatus.unauthenticated);
@override
List<Object?> get props => [status, user, extra];
List<Object?> get props => [status];
@override
String toString() =>
'AuthenticationState(status: $status, user: $user, extra: $extra)';
'AuthenticationState(status: $status, accountWrapper: $accountWrapper)';
}

View File

@ -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 <https://www.gnu.org/licenses/>.
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<EmailVerificationState> {
final AuthenticationRepository _authenticationRepository;
EmailVerificationCubit({
required AuthenticationRepository authenticationRepository,
}) : _authenticationRepository = authenticationRepository,
super(const EmailVerificationState());
Future<void> 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<void> 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));
}
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
export 'authentication/authentication.dart';
export 'sign_in/sign_in.dart';
export 'sign_up/sign_up.dart';

View File

@ -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 <https://www.gnu.org/licenses/>.
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<PasswordResetState> {
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<void> 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));
}
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
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<Object> get props => [email, status];
}

View File

@ -14,112 +14,132 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
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<SignInState> {
final AuthenticationRepository _authenticationRepository;
final FormValidator _validationStrategy;
class SignInCubit<Extra> extends FormDataCubit<SignInState> {
final AuthenticationRepository<Extra> _authenticationRepository;
FormRepository get _formRepository =>
_authenticationRepository.formRepository;
SignInCubit({
required AuthenticationRepository authenticationRepository,
FormValidator validationStrategy = const EveryInputValidator(),
required AuthenticationRepository<Extra> 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<void> dataChanged<Value>(
String key,
FormInputValidator<Value, ValidationError> 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<void> reset() {
final form = state.form.reset();
_formRepository.updateForm(form);
emit(
state.copyWith(form: form, status: form.validate()),
);
}
@override
FutureOr<void> submit() async {
if (!state.status.isValidated) {
return;
}
emit(state.copyWith(status: FormStatus.submissionInProgress));
final form = _formRepository.accessForm(formName);
final email = form.valueOf<String?>(AuthFormField.email);
final password = form.valueOf<String?>(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<void> signInAnonymously() async {
if (state.status.isSubmissionInProgress) {
return;
}
@override
FutureOr<void> 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<void> 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<void> 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<void> validate() {
emit(
state.copyWith(
status: _formRepository.accessForm(formName).validate(),
),
);
}
}

View File

@ -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<Object> 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)';
}

View File

@ -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 <https://www.gnu.org/licenses/>.

View File

@ -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<SignUpState> {
final AuthenticationRepository _authenticationRepository;
final Future<void> Function(SignUpState state, String? uid)? _onSignUpSuccess;
final FormValidator _validationStrategy;
class SignUpCubit<Extra> extends FormDataCubit<SignUpState> {
final AuthenticationRepository<Extra> _authenticationRepository;
FormRepository get _formRepository =>
_authenticationRepository.formRepository;
SignUpCubit({
required AuthenticationRepository authenticationRepository,
required FormData formData,
FormValidator validationStrategy = const EveryInputValidator(),
Future<void> Function(SignUpState state, String? uid)? onSignUpSuccess,
required AuthenticationRepository<Extra> 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<FormInputValidator<dynamic, ValidationError>> toValidate = [
email,
state.password,
...state.data.validators<dynamic, ValidationError>(),
];
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<FormInputValidator<dynamic, ValidationError>> toValidate = [
state.email,
password,
...state.data.validators<dynamic, ValidationError>(),
];
emit(
state.copyWith(
password: password,
status: _validationStrategy.rawValidate(toValidate),
),
);
dataChanged(AuthFormField.password, password);
}
// Take from wyatt_form_bloc/wyatt_form_bloc.dart
void dataChanged<T>(
String field,
FormInputValidator<T, ValidationError> dirtyValue,
@override
FutureOr<void> dataChanged<Value>(
String key,
FormInputValidator<Value, ValidationError> 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<dynamic, ValidationError>(),
],
),
),
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<void> reset() {
final form = state.form.reset();
_formRepository.updateForm(form);
emit(
state.copyWith(
data: form,
status: _validationStrategy.rawValidate(
[
state.email,
state.password,
...state.data.validators<dynamic, ValidationError>(),
],
),
),
state.copyWith(form: form, status: form.validate()),
);
}
Future<void> signUpFormSubmitted() async {
@override
FutureOr<void> 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<String?>(AuthFormField.email);
final password = form.valueOf<String?>(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<void> 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<void> validate() {
emit(
state.copyWith(
status: _formRepository.accessForm(formName).validate(),
),
);
}
}

View File

@ -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<Object?> get props => [email, password, status, form];
@override
List<Object?> get props => [email, password, status, data, errorMessage];
@override
String toString() => 'SignUpState(status: ${status.name} '
'${(errorMessage != null) ? " [$errorMessage]" : ""}, $form)';
}

View File

@ -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 <https://www.gnu.org/licenses/>.

View File

@ -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 <https://www.gnu.org/licenses/>.
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';

View File

@ -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

View File

@ -16,16 +16,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
# Dart - Form BLoC
# Flutter - Form BLoC
<p align="left">
<a href="https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis">
<img src="https://img.shields.io/badge/Style-Wyatt%20Analysis-blue.svg?style=flat-square" alt="Style: Wyatt Analysis" />
</a>
<img src="https://img.shields.io/badge/SDK-Dart%20%7C%20Flutter-blue?style=flat-square" alt="SDK: Dart & Flutter" />
<img src="https://img.shields.io/badge/SDK-Flutter-blue?style=flat-square" alt="SDK: Flutter" />
</p>
Form Bloc for Dart & Flutter.
Form Bloc for Flutter.
## Features

View File

@ -1,4 +1,4 @@
include: package:wyatt_analysis/analysis_options.yaml
include: package:wyatt_analysis/analysis_options.flutter.yaml
analyzer:
exclude: "!example/**"

View File

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

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