mirror of
https://github.com/bettercoding-dev/flutter-jwt-auth.git
synced 2025-08-24 09:11:38 +08:00
implement jwt flow
This commit is contained in:
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[submodule "shelf-jwt-test-server"]
|
||||||
|
path = shelf-jwt-test-server
|
||||||
|
url = git@github.com:bettercoding-dev/shelf-jwt-test-server.git
|
||||||
|
[submodule "server/shelf-jwt-test-server"]
|
||||||
|
path = server/shelf-jwt-test-server
|
||||||
|
url = git@github.com:bettercoding-dev/shelf-jwt-test-server.git
|
@ -1 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
@ -1 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
44
ios/Podfile
Normal file
44
ios/Podfile
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# Uncomment this line to define a global platform for your project
|
||||||
|
# platform :ios, '12.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__))
|
||||||
|
target 'RunnerTests' do
|
||||||
|
inherit! :search_paths
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
post_install do |installer|
|
||||||
|
installer.pods_project.targets.each do |target|
|
||||||
|
flutter_additional_ios_build_settings(target)
|
||||||
|
end
|
||||||
|
end
|
22
ios/Podfile.lock
Normal file
22
ios/Podfile.lock
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
PODS:
|
||||||
|
- Flutter (1.0.0)
|
||||||
|
- flutter_secure_storage (3.3.1):
|
||||||
|
- Flutter
|
||||||
|
|
||||||
|
DEPENDENCIES:
|
||||||
|
- Flutter (from `Flutter`)
|
||||||
|
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||||
|
|
||||||
|
EXTERNAL SOURCES:
|
||||||
|
Flutter:
|
||||||
|
:path: Flutter
|
||||||
|
flutter_secure_storage:
|
||||||
|
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
||||||
|
|
||||||
|
SPEC CHECKSUMS:
|
||||||
|
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||||
|
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
||||||
|
|
||||||
|
PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796
|
||||||
|
|
||||||
|
COCOAPODS: 1.15.2
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
|
1646D1EEE5DF6FE5BAD39A15 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91D9E65E8A5E264762FF8B1A /* Pods_RunnerTests.framework */; };
|
||||||
|
261FEC04840279EDAC19C313 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A02DCFF8620D3F72F79A3840 /* Pods_Runner.framework */; };
|
||||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
@ -40,14 +42,19 @@
|
|||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
132BB70143962167930A6E31 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; 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>"; };
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
33E36FBF3F48DA58460C0E68 /* 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>"; };
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
|
4E08E345669F7FAB9ABC4F0B /* 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>"; };
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; 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>"; };
|
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>"; };
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||||
|
8F0EC2398A99C280A77C69B2 /* 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>"; };
|
||||||
|
91D9E65E8A5E264762FF8B1A /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.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>"; };
|
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; };
|
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
@ -55,13 +62,25 @@
|
|||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; 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>"; };
|
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>"; };
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
A02DCFF8620D3F72F79A3840 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
C1A8494C902218FF87CAC30F /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
ED0E05E65940F20CD74F80A1 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
595AB5F2277E9FB394A4FBFD /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
1646D1EEE5DF6FE5BAD39A15 /* Pods_RunnerTests.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
261FEC04840279EDAC19C313 /* Pods_Runner.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -94,6 +113,8 @@
|
|||||||
97C146F01CF9000F007C117D /* Runner */,
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||||
|
A25A5221F0DECAE777A7C39A /* Pods */,
|
||||||
|
C3358ABD8B73863554D6CBCE /* Frameworks */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@ -121,6 +142,28 @@
|
|||||||
path = Runner;
|
path = Runner;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
A25A5221F0DECAE777A7C39A /* Pods */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
8F0EC2398A99C280A77C69B2 /* Pods-Runner.debug.xcconfig */,
|
||||||
|
33E36FBF3F48DA58460C0E68 /* Pods-Runner.release.xcconfig */,
|
||||||
|
4E08E345669F7FAB9ABC4F0B /* Pods-Runner.profile.xcconfig */,
|
||||||
|
ED0E05E65940F20CD74F80A1 /* Pods-RunnerTests.debug.xcconfig */,
|
||||||
|
132BB70143962167930A6E31 /* Pods-RunnerTests.release.xcconfig */,
|
||||||
|
C1A8494C902218FF87CAC30F /* Pods-RunnerTests.profile.xcconfig */,
|
||||||
|
);
|
||||||
|
path = Pods;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
C3358ABD8B73863554D6CBCE /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
A02DCFF8620D3F72F79A3840 /* Pods_Runner.framework */,
|
||||||
|
91D9E65E8A5E264762FF8B1A /* Pods_RunnerTests.framework */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
@ -128,8 +171,10 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
|
7EE5E162952D2EF1724B6F3C /* [CP] Check Pods Manifest.lock */,
|
||||||
331C807D294A63A400263BE5 /* Sources */,
|
331C807D294A63A400263BE5 /* Sources */,
|
||||||
331C807F294A63A400263BE5 /* Resources */,
|
331C807F294A63A400263BE5 /* Resources */,
|
||||||
|
595AB5F2277E9FB394A4FBFD /* Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@ -145,12 +190,14 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
|
C1E76FD3B568DD3E0EEA9500 /* [CP] Check Pods Manifest.lock */,
|
||||||
9740EEB61CF901F6004384FC /* Run Script */,
|
9740EEB61CF901F6004384FC /* Run Script */,
|
||||||
97C146EA1CF9000F007C117D /* Sources */,
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
|
26958E994E7C110BC936614B /* [CP] Embed Pods Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@ -222,6 +269,23 @@
|
|||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
26958E994E7C110BC936614B /* [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;
|
||||||
|
};
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
alwaysOutOfDate = 1;
|
||||||
@ -238,6 +302,28 @@
|
|||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||||
};
|
};
|
||||||
|
7EE5E162952D2EF1724B6F3C /* [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-RunnerTests-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 */ = {
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
alwaysOutOfDate = 1;
|
||||||
@ -253,6 +339,28 @@
|
|||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||||
};
|
};
|
||||||
|
C1E76FD3B568DD3E0EEA9500 /* [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;
|
||||||
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
@ -362,7 +470,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = 79C8VHVD3P;
|
DEVELOPMENT_TEAM = 78A8AZ76DR;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
@ -379,6 +487,7 @@
|
|||||||
};
|
};
|
||||||
331C8088294A63A400263BE5 /* Debug */ = {
|
331C8088294A63A400263BE5 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = ED0E05E65940F20CD74F80A1 /* Pods-RunnerTests.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
@ -396,6 +505,7 @@
|
|||||||
};
|
};
|
||||||
331C8089294A63A400263BE5 /* Release */ = {
|
331C8089294A63A400263BE5 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 132BB70143962167930A6E31 /* Pods-RunnerTests.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
@ -411,6 +521,7 @@
|
|||||||
};
|
};
|
||||||
331C808A294A63A400263BE5 /* Profile */ = {
|
331C808A294A63A400263BE5 /* Profile */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = C1A8494C902218FF87CAC30F /* Pods-RunnerTests.profile.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
@ -542,7 +653,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = 79C8VHVD3P;
|
DEVELOPMENT_TEAM = 78A8AZ76DR;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
@ -565,7 +676,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = 79C8VHVD3P;
|
DEVELOPMENT_TEAM = 78A8AZ76DR;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
3
ios/Runner.xcworkspace/contents.xcworkspacedata
generated
3
ios/Runner.xcworkspace/contents.xcworkspacedata
generated
@ -4,4 +4,7 @@
|
|||||||
<FileRef
|
<FileRef
|
||||||
location = "group:Runner.xcodeproj">
|
location = "group:Runner.xcodeproj">
|
||||||
</FileRef>
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
</Workspace>
|
</Workspace>
|
||||||
|
25
lib/auth/client/auth_client.dart
Normal file
25
lib/auth/client/auth_client.dart
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:retrofit/retrofit.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/client/login_request.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/client/refresh_token_request.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/model/auth_data.dart';
|
||||||
|
import 'package:flutter_jwt_auth/global_providers.dart';
|
||||||
|
|
||||||
|
part 'auth_client.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
AuthClient authClient(AuthClientRef ref) => AuthClient(
|
||||||
|
ref.watch(dioProvider),
|
||||||
|
);
|
||||||
|
|
||||||
|
@RestApi()
|
||||||
|
abstract class AuthClient {
|
||||||
|
factory AuthClient(Dio dio) = _AuthClient;
|
||||||
|
|
||||||
|
@POST('/login')
|
||||||
|
Future<AuthData> login(@Body() LoginRequest request);
|
||||||
|
|
||||||
|
@POST('/refresh')
|
||||||
|
Future<AuthData> refresh(@Body() RefreshTokenRequest request);
|
||||||
|
}
|
140
lib/auth/client/auth_client.g.dart
Normal file
140
lib/auth/client/auth_client.g.dart
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'auth_client.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RetrofitGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element
|
||||||
|
|
||||||
|
class _AuthClient implements AuthClient {
|
||||||
|
_AuthClient(
|
||||||
|
this._dio, {
|
||||||
|
this.baseUrl,
|
||||||
|
this.errorLogger,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Dio _dio;
|
||||||
|
|
||||||
|
String? baseUrl;
|
||||||
|
|
||||||
|
final ParseErrorLogger? errorLogger;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<AuthData> login(LoginRequest request) async {
|
||||||
|
final _extra = <String, dynamic>{};
|
||||||
|
final queryParameters = <String, dynamic>{};
|
||||||
|
final _headers = <String, dynamic>{};
|
||||||
|
final _data = request;
|
||||||
|
final _options = _setStreamType<AuthData>(Options(
|
||||||
|
method: 'POST',
|
||||||
|
headers: _headers,
|
||||||
|
extra: _extra,
|
||||||
|
)
|
||||||
|
.compose(
|
||||||
|
_dio.options,
|
||||||
|
'/login',
|
||||||
|
queryParameters: queryParameters,
|
||||||
|
data: _data,
|
||||||
|
)
|
||||||
|
.copyWith(
|
||||||
|
baseUrl: _combineBaseUrls(
|
||||||
|
_dio.options.baseUrl,
|
||||||
|
baseUrl,
|
||||||
|
)));
|
||||||
|
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
|
||||||
|
late AuthData _value;
|
||||||
|
try {
|
||||||
|
_value = AuthData.fromJson(_result.data!);
|
||||||
|
} on Object catch (e, s) {
|
||||||
|
errorLogger?.logError(e, s, _options);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<AuthData> refresh(RefreshTokenRequest request) async {
|
||||||
|
final _extra = <String, dynamic>{};
|
||||||
|
final queryParameters = <String, dynamic>{};
|
||||||
|
final _headers = <String, dynamic>{};
|
||||||
|
final _data = request;
|
||||||
|
final _options = _setStreamType<AuthData>(Options(
|
||||||
|
method: 'POST',
|
||||||
|
headers: _headers,
|
||||||
|
extra: _extra,
|
||||||
|
)
|
||||||
|
.compose(
|
||||||
|
_dio.options,
|
||||||
|
'/refresh',
|
||||||
|
queryParameters: queryParameters,
|
||||||
|
data: _data,
|
||||||
|
)
|
||||||
|
.copyWith(
|
||||||
|
baseUrl: _combineBaseUrls(
|
||||||
|
_dio.options.baseUrl,
|
||||||
|
baseUrl,
|
||||||
|
)));
|
||||||
|
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
|
||||||
|
late AuthData _value;
|
||||||
|
try {
|
||||||
|
_value = AuthData.fromJson(_result.data!);
|
||||||
|
} on Object catch (e, s) {
|
||||||
|
errorLogger?.logError(e, s, _options);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
|
||||||
|
if (T != dynamic &&
|
||||||
|
!(requestOptions.responseType == ResponseType.bytes ||
|
||||||
|
requestOptions.responseType == ResponseType.stream)) {
|
||||||
|
if (T == String) {
|
||||||
|
requestOptions.responseType = ResponseType.plain;
|
||||||
|
} else {
|
||||||
|
requestOptions.responseType = ResponseType.json;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return requestOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
String _combineBaseUrls(
|
||||||
|
String dioBaseUrl,
|
||||||
|
String? baseUrl,
|
||||||
|
) {
|
||||||
|
if (baseUrl == null || baseUrl.trim().isEmpty) {
|
||||||
|
return dioBaseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
final url = Uri.parse(baseUrl);
|
||||||
|
|
||||||
|
if (url.isAbsolute) {
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Uri.parse(dioBaseUrl).resolveUri(url).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$authClientHash() => r'cd6faf293e6975a9091a92d7534d8e4a7d33284b';
|
||||||
|
|
||||||
|
/// See also [authClient].
|
||||||
|
@ProviderFor(authClient)
|
||||||
|
final authClientProvider = AutoDisposeProvider<AuthClient>.internal(
|
||||||
|
authClient,
|
||||||
|
name: r'authClientProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product') ? null : _$authClientHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef AuthClientRef = AutoDisposeProviderRef<AuthClient>;
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
15
lib/auth/client/login_request.dart
Normal file
15
lib/auth/client/login_request.dart
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'login_request.freezed.dart';
|
||||||
|
part 'login_request.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class LoginRequest with _$LoginRequest {
|
||||||
|
const factory LoginRequest({
|
||||||
|
required String username,
|
||||||
|
}) = _LoginRequest;
|
||||||
|
|
||||||
|
factory LoginRequest.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$LoginRequestFromJson(json);
|
||||||
|
}
|
174
lib/auth/client/login_request.freezed.dart
Normal file
174
lib/auth/client/login_request.freezed.dart
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'login_request.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||||
|
|
||||||
|
LoginRequest _$LoginRequestFromJson(Map<String, dynamic> json) {
|
||||||
|
return _LoginRequest.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$LoginRequest {
|
||||||
|
String get username => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this LoginRequest to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of LoginRequest
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$LoginRequestCopyWith<LoginRequest> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $LoginRequestCopyWith<$Res> {
|
||||||
|
factory $LoginRequestCopyWith(
|
||||||
|
LoginRequest value, $Res Function(LoginRequest) then) =
|
||||||
|
_$LoginRequestCopyWithImpl<$Res, LoginRequest>;
|
||||||
|
@useResult
|
||||||
|
$Res call({String username});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$LoginRequestCopyWithImpl<$Res, $Val extends LoginRequest>
|
||||||
|
implements $LoginRequestCopyWith<$Res> {
|
||||||
|
_$LoginRequestCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of LoginRequest
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? username = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
username: null == username
|
||||||
|
? _value.username
|
||||||
|
: username // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$LoginRequestImplCopyWith<$Res>
|
||||||
|
implements $LoginRequestCopyWith<$Res> {
|
||||||
|
factory _$$LoginRequestImplCopyWith(
|
||||||
|
_$LoginRequestImpl value, $Res Function(_$LoginRequestImpl) then) =
|
||||||
|
__$$LoginRequestImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({String username});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$LoginRequestImplCopyWithImpl<$Res>
|
||||||
|
extends _$LoginRequestCopyWithImpl<$Res, _$LoginRequestImpl>
|
||||||
|
implements _$$LoginRequestImplCopyWith<$Res> {
|
||||||
|
__$$LoginRequestImplCopyWithImpl(
|
||||||
|
_$LoginRequestImpl _value, $Res Function(_$LoginRequestImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of LoginRequest
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? username = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$LoginRequestImpl(
|
||||||
|
username: null == username
|
||||||
|
? _value.username
|
||||||
|
: username // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$LoginRequestImpl with DiagnosticableTreeMixin implements _LoginRequest {
|
||||||
|
const _$LoginRequestImpl({required this.username});
|
||||||
|
|
||||||
|
factory _$LoginRequestImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$LoginRequestImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String username;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
|
||||||
|
return 'LoginRequest(username: $username)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||||
|
super.debugFillProperties(properties);
|
||||||
|
properties
|
||||||
|
..add(DiagnosticsProperty('type', 'LoginRequest'))
|
||||||
|
..add(DiagnosticsProperty('username', username));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$LoginRequestImpl &&
|
||||||
|
(identical(other.username, username) ||
|
||||||
|
other.username == username));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, username);
|
||||||
|
|
||||||
|
/// Create a copy of LoginRequest
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$LoginRequestImplCopyWith<_$LoginRequestImpl> get copyWith =>
|
||||||
|
__$$LoginRequestImplCopyWithImpl<_$LoginRequestImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$LoginRequestImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _LoginRequest implements LoginRequest {
|
||||||
|
const factory _LoginRequest({required final String username}) =
|
||||||
|
_$LoginRequestImpl;
|
||||||
|
|
||||||
|
factory _LoginRequest.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$LoginRequestImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get username;
|
||||||
|
|
||||||
|
/// Create a copy of LoginRequest
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$LoginRequestImplCopyWith<_$LoginRequestImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
17
lib/auth/client/login_request.g.dart
Normal file
17
lib/auth/client/login_request.g.dart
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'login_request.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$LoginRequestImpl _$$LoginRequestImplFromJson(Map<String, dynamic> json) =>
|
||||||
|
_$LoginRequestImpl(
|
||||||
|
username: json['username'] as String,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$LoginRequestImplToJson(_$LoginRequestImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'username': instance.username,
|
||||||
|
};
|
14
lib/auth/client/refresh_token_request.dart
Normal file
14
lib/auth/client/refresh_token_request.dart
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'refresh_token_request.freezed.dart';
|
||||||
|
part 'refresh_token_request.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class RefreshTokenRequest with _$RefreshTokenRequest {
|
||||||
|
const factory RefreshTokenRequest({
|
||||||
|
required String token,
|
||||||
|
}) = _RefreshTokenRequest;
|
||||||
|
|
||||||
|
factory RefreshTokenRequest.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$RefreshTokenRequestFromJson(json);
|
||||||
|
}
|
166
lib/auth/client/refresh_token_request.freezed.dart
Normal file
166
lib/auth/client/refresh_token_request.freezed.dart
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'refresh_token_request.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||||
|
|
||||||
|
RefreshTokenRequest _$RefreshTokenRequestFromJson(Map<String, dynamic> json) {
|
||||||
|
return _RefreshTokenRequest.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$RefreshTokenRequest {
|
||||||
|
String get token => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this RefreshTokenRequest to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of RefreshTokenRequest
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$RefreshTokenRequestCopyWith<RefreshTokenRequest> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $RefreshTokenRequestCopyWith<$Res> {
|
||||||
|
factory $RefreshTokenRequestCopyWith(
|
||||||
|
RefreshTokenRequest value, $Res Function(RefreshTokenRequest) then) =
|
||||||
|
_$RefreshTokenRequestCopyWithImpl<$Res, RefreshTokenRequest>;
|
||||||
|
@useResult
|
||||||
|
$Res call({String token});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$RefreshTokenRequestCopyWithImpl<$Res, $Val extends RefreshTokenRequest>
|
||||||
|
implements $RefreshTokenRequestCopyWith<$Res> {
|
||||||
|
_$RefreshTokenRequestCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of RefreshTokenRequest
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? token = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
token: null == token
|
||||||
|
? _value.token
|
||||||
|
: token // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$RefreshTokenRequestImplCopyWith<$Res>
|
||||||
|
implements $RefreshTokenRequestCopyWith<$Res> {
|
||||||
|
factory _$$RefreshTokenRequestImplCopyWith(_$RefreshTokenRequestImpl value,
|
||||||
|
$Res Function(_$RefreshTokenRequestImpl) then) =
|
||||||
|
__$$RefreshTokenRequestImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({String token});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$RefreshTokenRequestImplCopyWithImpl<$Res>
|
||||||
|
extends _$RefreshTokenRequestCopyWithImpl<$Res, _$RefreshTokenRequestImpl>
|
||||||
|
implements _$$RefreshTokenRequestImplCopyWith<$Res> {
|
||||||
|
__$$RefreshTokenRequestImplCopyWithImpl(_$RefreshTokenRequestImpl _value,
|
||||||
|
$Res Function(_$RefreshTokenRequestImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of RefreshTokenRequest
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? token = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$RefreshTokenRequestImpl(
|
||||||
|
token: null == token
|
||||||
|
? _value.token
|
||||||
|
: token // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$RefreshTokenRequestImpl implements _RefreshTokenRequest {
|
||||||
|
const _$RefreshTokenRequestImpl({required this.token});
|
||||||
|
|
||||||
|
factory _$RefreshTokenRequestImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$RefreshTokenRequestImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String token;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'RefreshTokenRequest(token: $token)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$RefreshTokenRequestImpl &&
|
||||||
|
(identical(other.token, token) || other.token == token));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, token);
|
||||||
|
|
||||||
|
/// Create a copy of RefreshTokenRequest
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$RefreshTokenRequestImplCopyWith<_$RefreshTokenRequestImpl> get copyWith =>
|
||||||
|
__$$RefreshTokenRequestImplCopyWithImpl<_$RefreshTokenRequestImpl>(
|
||||||
|
this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$RefreshTokenRequestImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _RefreshTokenRequest implements RefreshTokenRequest {
|
||||||
|
const factory _RefreshTokenRequest({required final String token}) =
|
||||||
|
_$RefreshTokenRequestImpl;
|
||||||
|
|
||||||
|
factory _RefreshTokenRequest.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$RefreshTokenRequestImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get token;
|
||||||
|
|
||||||
|
/// Create a copy of RefreshTokenRequest
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$RefreshTokenRequestImplCopyWith<_$RefreshTokenRequestImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
19
lib/auth/client/refresh_token_request.g.dart
Normal file
19
lib/auth/client/refresh_token_request.g.dart
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'refresh_token_request.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$RefreshTokenRequestImpl _$$RefreshTokenRequestImplFromJson(
|
||||||
|
Map<String, dynamic> json) =>
|
||||||
|
_$RefreshTokenRequestImpl(
|
||||||
|
token: json['token'] as String,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$RefreshTokenRequestImplToJson(
|
||||||
|
_$RefreshTokenRequestImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'token': instance.token,
|
||||||
|
};
|
54
lib/auth/interceptor/auth_interceptor.dart
Normal file
54
lib/auth/interceptor/auth_interceptor.dart
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/state/auth_controller.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
class AuthInterceptor extends Interceptor {
|
||||||
|
final Ref ref;
|
||||||
|
final Dio dio;
|
||||||
|
|
||||||
|
const AuthInterceptor(this.ref, this.dio);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onRequest(
|
||||||
|
RequestOptions options, RequestInterceptorHandler handler) async {
|
||||||
|
final authData = await ref.read(authControllerProvider.future);
|
||||||
|
final token = authData?.token;
|
||||||
|
if (token != null) {
|
||||||
|
options.headers['Authorization'] = 'Bearer $token';
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onRequest(options, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onError(DioException err, ErrorInterceptorHandler handler) async {
|
||||||
|
final isRetry = err.requestOptions.extra['isRetry'] == true;
|
||||||
|
|
||||||
|
// if response is unauthorized
|
||||||
|
if (err.response?.statusCode == 401 && !isRetry) {
|
||||||
|
try {
|
||||||
|
final authData = await ref.read(authControllerProvider.future);
|
||||||
|
final refreshToken = authData?.refreshToken;
|
||||||
|
|
||||||
|
if (refreshToken != null) {
|
||||||
|
await ref.read(authControllerProvider.notifier).refreshToken();
|
||||||
|
|
||||||
|
final options = err.requestOptions;
|
||||||
|
options.extra['isRetry'] = true;
|
||||||
|
final response = await dio.fetch(options);
|
||||||
|
|
||||||
|
handler.resolve(response);
|
||||||
|
} else {
|
||||||
|
super.onError(err, handler);
|
||||||
|
}
|
||||||
|
} on DioException catch (error, trace) {
|
||||||
|
log('cannot refresh', error: error, stackTrace: trace);
|
||||||
|
super.onError(error, handler);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.onError(err, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
lib/auth/model/auth_data.dart
Normal file
16
lib/auth/model/auth_data.dart
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'auth_data.freezed.dart';
|
||||||
|
part 'auth_data.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class AuthData with _$AuthData {
|
||||||
|
const factory AuthData({
|
||||||
|
required String token,
|
||||||
|
required String refreshToken,
|
||||||
|
}) = _AuthData;
|
||||||
|
|
||||||
|
factory AuthData.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$AuthDataFromJson(json);
|
||||||
|
}
|
191
lib/auth/model/auth_data.freezed.dart
Normal file
191
lib/auth/model/auth_data.freezed.dart
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'auth_data.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||||
|
|
||||||
|
AuthData _$AuthDataFromJson(Map<String, dynamic> json) {
|
||||||
|
return _AuthData.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$AuthData {
|
||||||
|
String get token => throw _privateConstructorUsedError;
|
||||||
|
String get refreshToken => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this AuthData to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of AuthData
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$AuthDataCopyWith<AuthData> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $AuthDataCopyWith<$Res> {
|
||||||
|
factory $AuthDataCopyWith(AuthData value, $Res Function(AuthData) then) =
|
||||||
|
_$AuthDataCopyWithImpl<$Res, AuthData>;
|
||||||
|
@useResult
|
||||||
|
$Res call({String token, String refreshToken});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$AuthDataCopyWithImpl<$Res, $Val extends AuthData>
|
||||||
|
implements $AuthDataCopyWith<$Res> {
|
||||||
|
_$AuthDataCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of AuthData
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? token = null,
|
||||||
|
Object? refreshToken = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
token: null == token
|
||||||
|
? _value.token
|
||||||
|
: token // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
refreshToken: null == refreshToken
|
||||||
|
? _value.refreshToken
|
||||||
|
: refreshToken // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$AuthDataImplCopyWith<$Res>
|
||||||
|
implements $AuthDataCopyWith<$Res> {
|
||||||
|
factory _$$AuthDataImplCopyWith(
|
||||||
|
_$AuthDataImpl value, $Res Function(_$AuthDataImpl) then) =
|
||||||
|
__$$AuthDataImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({String token, String refreshToken});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$AuthDataImplCopyWithImpl<$Res>
|
||||||
|
extends _$AuthDataCopyWithImpl<$Res, _$AuthDataImpl>
|
||||||
|
implements _$$AuthDataImplCopyWith<$Res> {
|
||||||
|
__$$AuthDataImplCopyWithImpl(
|
||||||
|
_$AuthDataImpl _value, $Res Function(_$AuthDataImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of AuthData
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? token = null,
|
||||||
|
Object? refreshToken = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$AuthDataImpl(
|
||||||
|
token: null == token
|
||||||
|
? _value.token
|
||||||
|
: token // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
refreshToken: null == refreshToken
|
||||||
|
? _value.refreshToken
|
||||||
|
: refreshToken // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$AuthDataImpl with DiagnosticableTreeMixin implements _AuthData {
|
||||||
|
const _$AuthDataImpl({required this.token, required this.refreshToken});
|
||||||
|
|
||||||
|
factory _$AuthDataImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$AuthDataImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String token;
|
||||||
|
@override
|
||||||
|
final String refreshToken;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
|
||||||
|
return 'AuthData(token: $token, refreshToken: $refreshToken)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||||
|
super.debugFillProperties(properties);
|
||||||
|
properties
|
||||||
|
..add(DiagnosticsProperty('type', 'AuthData'))
|
||||||
|
..add(DiagnosticsProperty('token', token))
|
||||||
|
..add(DiagnosticsProperty('refreshToken', refreshToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$AuthDataImpl &&
|
||||||
|
(identical(other.token, token) || other.token == token) &&
|
||||||
|
(identical(other.refreshToken, refreshToken) ||
|
||||||
|
other.refreshToken == refreshToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, token, refreshToken);
|
||||||
|
|
||||||
|
/// Create a copy of AuthData
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$AuthDataImplCopyWith<_$AuthDataImpl> get copyWith =>
|
||||||
|
__$$AuthDataImplCopyWithImpl<_$AuthDataImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$AuthDataImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _AuthData implements AuthData {
|
||||||
|
const factory _AuthData(
|
||||||
|
{required final String token,
|
||||||
|
required final String refreshToken}) = _$AuthDataImpl;
|
||||||
|
|
||||||
|
factory _AuthData.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$AuthDataImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get token;
|
||||||
|
@override
|
||||||
|
String get refreshToken;
|
||||||
|
|
||||||
|
/// Create a copy of AuthData
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$AuthDataImplCopyWith<_$AuthDataImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
19
lib/auth/model/auth_data.g.dart
Normal file
19
lib/auth/model/auth_data.g.dart
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'auth_data.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$AuthDataImpl _$$AuthDataImplFromJson(Map<String, dynamic> json) =>
|
||||||
|
_$AuthDataImpl(
|
||||||
|
token: json['token'] as String,
|
||||||
|
refreshToken: json['refreshToken'] as String,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$AuthDataImplToJson(_$AuthDataImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'token': instance.token,
|
||||||
|
'refreshToken': instance.refreshToken,
|
||||||
|
};
|
23
lib/auth/repository/api_auth_repository.dart
Normal file
23
lib/auth/repository/api_auth_repository.dart
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:flutter_jwt_auth/auth/client/auth_client.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/client/login_request.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/client/refresh_token_request.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/model/auth_data.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/repository/auth_repository.dart';
|
||||||
|
|
||||||
|
class ApiAuthRepository implements AuthRepository {
|
||||||
|
final AuthClient authClient;
|
||||||
|
|
||||||
|
const ApiAuthRepository(this.authClient);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<AuthData> login(String username) {
|
||||||
|
final request = LoginRequest(username: username);
|
||||||
|
return authClient.login(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<AuthData> refreshToken(String token) {
|
||||||
|
final request = RefreshTokenRequest(token: token);
|
||||||
|
return authClient.refresh(request);
|
||||||
|
}
|
||||||
|
}
|
17
lib/auth/repository/auth_repository.dart
Normal file
17
lib/auth/repository/auth_repository.dart
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/client/auth_client.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/model/auth_data.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/repository/api_auth_repository.dart';
|
||||||
|
|
||||||
|
part 'auth_repository.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
AuthRepository authRepository(AuthRepositoryRef ref) => ApiAuthRepository(
|
||||||
|
ref.watch(authClientProvider),
|
||||||
|
);
|
||||||
|
|
||||||
|
abstract interface class AuthRepository {
|
||||||
|
Future<AuthData> login(String username);
|
||||||
|
|
||||||
|
Future<AuthData> refreshToken(String token);
|
||||||
|
}
|
25
lib/auth/repository/auth_repository.g.dart
Normal file
25
lib/auth/repository/auth_repository.g.dart
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'auth_repository.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$authRepositoryHash() => r'0eb6db9e8bb6c8d101d6d31065b02e0d53114782';
|
||||||
|
|
||||||
|
/// See also [authRepository].
|
||||||
|
@ProviderFor(authRepository)
|
||||||
|
final authRepositoryProvider = AutoDisposeProvider<AuthRepository>.internal(
|
||||||
|
authRepository,
|
||||||
|
name: r'authRepositoryProvider',
|
||||||
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$authRepositoryHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef AuthRepositoryRef = AutoDisposeProviderRef<AuthRepository>;
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
63
lib/auth/state/auth_controller.dart
Normal file
63
lib/auth/state/auth_controller.dart
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/model/auth_data.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/repository/auth_repository.dart';
|
||||||
|
import 'package:flutter_jwt_auth/common/repository/storage_repository.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
|
part 'auth_controller.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
class AuthController extends _$AuthController {
|
||||||
|
@override
|
||||||
|
Future<AuthData?> build() async {
|
||||||
|
final storageRepository = ref.watch(storageRepositoryProvider);
|
||||||
|
|
||||||
|
final token = await storageRepository.getToken();
|
||||||
|
final refreshToken = await storageRepository.getRefreshToken();
|
||||||
|
|
||||||
|
if (token != null && refreshToken != null) {
|
||||||
|
return AuthData(token: token, refreshToken: refreshToken);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> login(String username) async {
|
||||||
|
final authRepository = ref.read(authRepositoryProvider);
|
||||||
|
final storageRepository = ref.read(storageRepositoryProvider);
|
||||||
|
|
||||||
|
state = await AsyncValue.guard(() async {
|
||||||
|
final authData = await authRepository.login(username);
|
||||||
|
await storageRepository.storeToken(authData.token);
|
||||||
|
await storageRepository.storeRefreshToken(authData.refreshToken);
|
||||||
|
return authData;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> refreshToken() async {
|
||||||
|
final authRepository = ref.read(authRepositoryProvider);
|
||||||
|
final storageRepository = ref.read(storageRepositoryProvider);
|
||||||
|
final authData = state.valueOrNull;
|
||||||
|
if (authData != null) {
|
||||||
|
try {
|
||||||
|
final newTokens =
|
||||||
|
await authRepository.refreshToken(authData.refreshToken);
|
||||||
|
storageRepository.storeToken(newTokens.token);
|
||||||
|
storageRepository.storeRefreshToken(newTokens.refreshToken);
|
||||||
|
state = AsyncData(newTokens);
|
||||||
|
} on DioException {
|
||||||
|
await logout();
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> logout() async {
|
||||||
|
state = await AsyncValue.guard(() async {
|
||||||
|
final storageRepository = ref.read(storageRepositoryProvider);
|
||||||
|
await storageRepository.deleteToken();
|
||||||
|
await storageRepository.deleteRefreshToken();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
26
lib/auth/state/auth_controller.g.dart
Normal file
26
lib/auth/state/auth_controller.g.dart
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'auth_controller.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$authControllerHash() => r'413fe66c0b164847c772c71ea7dfd1270ffe7672';
|
||||||
|
|
||||||
|
/// See also [AuthController].
|
||||||
|
@ProviderFor(AuthController)
|
||||||
|
final authControllerProvider =
|
||||||
|
AutoDisposeAsyncNotifierProvider<AuthController, AuthData?>.internal(
|
||||||
|
AuthController.new,
|
||||||
|
name: r'authControllerProvider',
|
||||||
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$authControllerHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef _$AuthController = AutoDisposeAsyncNotifier<AuthData?>;
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
33
lib/common/repository/secure_storage_repository.dart
Normal file
33
lib/common/repository/secure_storage_repository.dart
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
|
import 'package:flutter_jwt_auth/common/repository/storage_repository.dart';
|
||||||
|
|
||||||
|
class SecureStorageRepository implements StorageRepository {
|
||||||
|
static const String _keyToken = 'token';
|
||||||
|
static const String _keyRefreshToken = 'refresh_token';
|
||||||
|
|
||||||
|
final FlutterSecureStorage storage;
|
||||||
|
|
||||||
|
const SecureStorageRepository({required this.storage});
|
||||||
|
|
||||||
|
// Token
|
||||||
|
@override
|
||||||
|
Future<String?> getToken() => storage.read(key: _keyToken);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> storeToken(String token) =>
|
||||||
|
storage.write(key: _keyToken, value: token);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> deleteToken() => storage.delete(key: _keyToken);
|
||||||
|
|
||||||
|
// Refresh Token
|
||||||
|
@override
|
||||||
|
Future<String?> getRefreshToken() => storage.read(key: _keyRefreshToken);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> storeRefreshToken(String token) =>
|
||||||
|
storage.write(key: _keyRefreshToken, value: token);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> deleteRefreshToken() => storage.delete(key: _keyRefreshToken);
|
||||||
|
}
|
25
lib/common/repository/storage_repository.dart
Normal file
25
lib/common/repository/storage_repository.dart
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:flutter_jwt_auth/common/repository/secure_storage_repository.dart';
|
||||||
|
import 'package:flutter_jwt_auth/global_providers.dart';
|
||||||
|
|
||||||
|
part 'storage_repository.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
StorageRepository storageRepository(StorageRepositoryRef ref) =>
|
||||||
|
SecureStorageRepository(
|
||||||
|
storage: ref.watch(flutterSecureStorageProvider),
|
||||||
|
);
|
||||||
|
|
||||||
|
abstract interface class StorageRepository {
|
||||||
|
Future<void> storeToken(String token);
|
||||||
|
|
||||||
|
Future<void> storeRefreshToken(String token);
|
||||||
|
|
||||||
|
Future<String?> getToken();
|
||||||
|
|
||||||
|
Future<String?> getRefreshToken();
|
||||||
|
|
||||||
|
Future<void> deleteToken();
|
||||||
|
|
||||||
|
Future<void> deleteRefreshToken();
|
||||||
|
}
|
26
lib/common/repository/storage_repository.g.dart
Normal file
26
lib/common/repository/storage_repository.g.dart
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'storage_repository.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$storageRepositoryHash() => r'aa1e363c047d2b2ebca478ea1408adff6b8095e6';
|
||||||
|
|
||||||
|
/// See also [storageRepository].
|
||||||
|
@ProviderFor(storageRepository)
|
||||||
|
final storageRepositoryProvider =
|
||||||
|
AutoDisposeProvider<StorageRepository>.internal(
|
||||||
|
storageRepository,
|
||||||
|
name: r'storageRepositoryProvider',
|
||||||
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$storageRepositoryHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef StorageRepositoryRef = AutoDisposeProviderRef<StorageRepository>;
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
33
lib/common/ui/error_view.dart
Normal file
33
lib/common/ui/error_view.dart
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ErrorView extends StatelessWidget {
|
||||||
|
final Object? error;
|
||||||
|
|
||||||
|
const ErrorView({
|
||||||
|
super.key,
|
||||||
|
required this.error,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final error = this.error;
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Error',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
if (error is DioException) ...[
|
||||||
|
Text('Status Code: ${error.response?.statusCode}'),
|
||||||
|
Text(error.response?.statusMessage ?? '')
|
||||||
|
] else
|
||||||
|
Text(error.toString())
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
12
lib/common/ui/loading_view.dart
Normal file
12
lib/common/ui/loading_view.dart
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class LoadingView extends StatelessWidget {
|
||||||
|
const LoadingView({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
26
lib/global_providers.dart
Normal file
26
lib/global_providers.dart
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/interceptor/auth_interceptor.dart';
|
||||||
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
|
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
|
part 'global_providers.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Dio dio(DioRef ref) {
|
||||||
|
final dio = Dio(
|
||||||
|
BaseOptions(
|
||||||
|
baseUrl: 'http://localhost:8080',
|
||||||
|
contentType: Headers.jsonContentType,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
dio.interceptors.add(PrettyDioLogger());
|
||||||
|
dio.interceptors.add(AuthInterceptor(ref, dio));
|
||||||
|
|
||||||
|
return dio;
|
||||||
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
FlutterSecureStorage flutterSecureStorage(FlutterSecureStorageRef ref) =>
|
||||||
|
const FlutterSecureStorage();
|
41
lib/global_providers.g.dart
Normal file
41
lib/global_providers.g.dart
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'global_providers.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$dioHash() => r'9347067b2b996a62b03e4531bcbd98f9fa468a91';
|
||||||
|
|
||||||
|
/// See also [dio].
|
||||||
|
@ProviderFor(dio)
|
||||||
|
final dioProvider = AutoDisposeProvider<Dio>.internal(
|
||||||
|
dio,
|
||||||
|
name: r'dioProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product') ? null : _$dioHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef DioRef = AutoDisposeProviderRef<Dio>;
|
||||||
|
String _$flutterSecureStorageHash() =>
|
||||||
|
r'f573db2722d185024bf535e0b496b1442ddf2db7';
|
||||||
|
|
||||||
|
/// See also [flutterSecureStorage].
|
||||||
|
@ProviderFor(flutterSecureStorage)
|
||||||
|
final flutterSecureStorageProvider =
|
||||||
|
AutoDisposeProvider<FlutterSecureStorage>.internal(
|
||||||
|
flutterSecureStorage,
|
||||||
|
name: r'flutterSecureStorageProvider',
|
||||||
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$flutterSecureStorageHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef FlutterSecureStorageRef = AutoDisposeProviderRef<FlutterSecureStorage>;
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
@ -1,7 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_jwt_auth/time/ui/time_page.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(const MainApp());
|
runApp(const ProviderScope(child: MainApp()));
|
||||||
}
|
}
|
||||||
|
|
||||||
class MainApp extends StatelessWidget {
|
class MainApp extends StatelessWidget {
|
||||||
@ -10,11 +12,8 @@ class MainApp extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return const MaterialApp(
|
return const MaterialApp(
|
||||||
home: Scaffold(
|
debugShowCheckedModeBanner: false,
|
||||||
body: Center(
|
home: TimePage(),
|
||||||
child: Text('Hello World!'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
20
lib/time/client/time_client.dart
Normal file
20
lib/time/client/time_client.dart
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:retrofit/retrofit.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:flutter_jwt_auth/global_providers.dart';
|
||||||
|
import 'package:flutter_jwt_auth/time/client/time_response.dart';
|
||||||
|
|
||||||
|
part 'time_client.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
TimeClient timeClient(TimeClientRef ref) => TimeClient(
|
||||||
|
ref.watch(dioProvider),
|
||||||
|
);
|
||||||
|
|
||||||
|
@RestApi()
|
||||||
|
abstract class TimeClient {
|
||||||
|
factory TimeClient(Dio dio) = _TimeClient;
|
||||||
|
|
||||||
|
@GET('/time')
|
||||||
|
Future<TimeResponse> getServerTime();
|
||||||
|
}
|
107
lib/time/client/time_client.g.dart
Normal file
107
lib/time/client/time_client.g.dart
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'time_client.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RetrofitGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element
|
||||||
|
|
||||||
|
class _TimeClient implements TimeClient {
|
||||||
|
_TimeClient(
|
||||||
|
this._dio, {
|
||||||
|
this.baseUrl,
|
||||||
|
this.errorLogger,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Dio _dio;
|
||||||
|
|
||||||
|
String? baseUrl;
|
||||||
|
|
||||||
|
final ParseErrorLogger? errorLogger;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<TimeResponse> getServerTime() async {
|
||||||
|
final _extra = <String, dynamic>{};
|
||||||
|
final queryParameters = <String, dynamic>{};
|
||||||
|
final _headers = <String, dynamic>{};
|
||||||
|
const Map<String, dynamic>? _data = null;
|
||||||
|
final _options = _setStreamType<TimeResponse>(Options(
|
||||||
|
method: 'GET',
|
||||||
|
headers: _headers,
|
||||||
|
extra: _extra,
|
||||||
|
)
|
||||||
|
.compose(
|
||||||
|
_dio.options,
|
||||||
|
'/time',
|
||||||
|
queryParameters: queryParameters,
|
||||||
|
data: _data,
|
||||||
|
)
|
||||||
|
.copyWith(
|
||||||
|
baseUrl: _combineBaseUrls(
|
||||||
|
_dio.options.baseUrl,
|
||||||
|
baseUrl,
|
||||||
|
)));
|
||||||
|
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
|
||||||
|
late TimeResponse _value;
|
||||||
|
try {
|
||||||
|
_value = TimeResponse.fromJson(_result.data!);
|
||||||
|
} on Object catch (e, s) {
|
||||||
|
errorLogger?.logError(e, s, _options);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
|
||||||
|
if (T != dynamic &&
|
||||||
|
!(requestOptions.responseType == ResponseType.bytes ||
|
||||||
|
requestOptions.responseType == ResponseType.stream)) {
|
||||||
|
if (T == String) {
|
||||||
|
requestOptions.responseType = ResponseType.plain;
|
||||||
|
} else {
|
||||||
|
requestOptions.responseType = ResponseType.json;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return requestOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
String _combineBaseUrls(
|
||||||
|
String dioBaseUrl,
|
||||||
|
String? baseUrl,
|
||||||
|
) {
|
||||||
|
if (baseUrl == null || baseUrl.trim().isEmpty) {
|
||||||
|
return dioBaseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
final url = Uri.parse(baseUrl);
|
||||||
|
|
||||||
|
if (url.isAbsolute) {
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Uri.parse(dioBaseUrl).resolveUri(url).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$timeClientHash() => r'6b646e6d22b33365b77143253c69787fea6889b3';
|
||||||
|
|
||||||
|
/// See also [timeClient].
|
||||||
|
@ProviderFor(timeClient)
|
||||||
|
final timeClientProvider = AutoDisposeProvider<TimeClient>.internal(
|
||||||
|
timeClient,
|
||||||
|
name: r'timeClientProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product') ? null : _$timeClientHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef TimeClientRef = AutoDisposeProviderRef<TimeClient>;
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
15
lib/time/client/time_response.dart
Normal file
15
lib/time/client/time_response.dart
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'time_response.freezed.dart';
|
||||||
|
part 'time_response.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class TimeResponse with _$TimeResponse {
|
||||||
|
const factory TimeResponse({
|
||||||
|
required DateTime time,
|
||||||
|
}) = _TimeResponse;
|
||||||
|
|
||||||
|
factory TimeResponse.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$TimeResponseFromJson(json);
|
||||||
|
}
|
173
lib/time/client/time_response.freezed.dart
Normal file
173
lib/time/client/time_response.freezed.dart
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'time_response.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||||
|
|
||||||
|
TimeResponse _$TimeResponseFromJson(Map<String, dynamic> json) {
|
||||||
|
return _TimeResponse.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$TimeResponse {
|
||||||
|
DateTime get time => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this TimeResponse to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of TimeResponse
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$TimeResponseCopyWith<TimeResponse> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $TimeResponseCopyWith<$Res> {
|
||||||
|
factory $TimeResponseCopyWith(
|
||||||
|
TimeResponse value, $Res Function(TimeResponse) then) =
|
||||||
|
_$TimeResponseCopyWithImpl<$Res, TimeResponse>;
|
||||||
|
@useResult
|
||||||
|
$Res call({DateTime time});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$TimeResponseCopyWithImpl<$Res, $Val extends TimeResponse>
|
||||||
|
implements $TimeResponseCopyWith<$Res> {
|
||||||
|
_$TimeResponseCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of TimeResponse
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? time = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
time: null == time
|
||||||
|
? _value.time
|
||||||
|
: time // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$TimeResponseImplCopyWith<$Res>
|
||||||
|
implements $TimeResponseCopyWith<$Res> {
|
||||||
|
factory _$$TimeResponseImplCopyWith(
|
||||||
|
_$TimeResponseImpl value, $Res Function(_$TimeResponseImpl) then) =
|
||||||
|
__$$TimeResponseImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({DateTime time});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$TimeResponseImplCopyWithImpl<$Res>
|
||||||
|
extends _$TimeResponseCopyWithImpl<$Res, _$TimeResponseImpl>
|
||||||
|
implements _$$TimeResponseImplCopyWith<$Res> {
|
||||||
|
__$$TimeResponseImplCopyWithImpl(
|
||||||
|
_$TimeResponseImpl _value, $Res Function(_$TimeResponseImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of TimeResponse
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? time = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$TimeResponseImpl(
|
||||||
|
time: null == time
|
||||||
|
? _value.time
|
||||||
|
: time // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$TimeResponseImpl with DiagnosticableTreeMixin implements _TimeResponse {
|
||||||
|
const _$TimeResponseImpl({required this.time});
|
||||||
|
|
||||||
|
factory _$TimeResponseImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$TimeResponseImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final DateTime time;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
|
||||||
|
return 'TimeResponse(time: $time)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||||
|
super.debugFillProperties(properties);
|
||||||
|
properties
|
||||||
|
..add(DiagnosticsProperty('type', 'TimeResponse'))
|
||||||
|
..add(DiagnosticsProperty('time', time));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$TimeResponseImpl &&
|
||||||
|
(identical(other.time, time) || other.time == time));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, time);
|
||||||
|
|
||||||
|
/// Create a copy of TimeResponse
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$TimeResponseImplCopyWith<_$TimeResponseImpl> get copyWith =>
|
||||||
|
__$$TimeResponseImplCopyWithImpl<_$TimeResponseImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$TimeResponseImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _TimeResponse implements TimeResponse {
|
||||||
|
const factory _TimeResponse({required final DateTime time}) =
|
||||||
|
_$TimeResponseImpl;
|
||||||
|
|
||||||
|
factory _TimeResponse.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$TimeResponseImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
DateTime get time;
|
||||||
|
|
||||||
|
/// Create a copy of TimeResponse
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$TimeResponseImplCopyWith<_$TimeResponseImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
17
lib/time/client/time_response.g.dart
Normal file
17
lib/time/client/time_response.g.dart
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'time_response.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$TimeResponseImpl _$$TimeResponseImplFromJson(Map<String, dynamic> json) =>
|
||||||
|
_$TimeResponseImpl(
|
||||||
|
time: DateTime.parse(json['time'] as String),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$TimeResponseImplToJson(_$TimeResponseImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'time': instance.time.toIso8601String(),
|
||||||
|
};
|
19
lib/time/repository/api_time_repository.dart
Normal file
19
lib/time/repository/api_time_repository.dart
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:flutter_jwt_auth/time/client/time_client.dart';
|
||||||
|
import 'package:flutter_jwt_auth/time/repository/time_repository.dart';
|
||||||
|
|
||||||
|
class ApiTimeRepository implements TimeRepository {
|
||||||
|
final TimeClient timeClient;
|
||||||
|
|
||||||
|
const ApiTimeRepository(this.timeClient);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<DateTime> getServerTime() async {
|
||||||
|
try {
|
||||||
|
final response = await timeClient.getServerTime();
|
||||||
|
return response.time;
|
||||||
|
} on DioException {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
lib/time/repository/mock_time_repository.dart
Normal file
10
lib/time/repository/mock_time_repository.dart
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import 'package:flutter_jwt_auth/time/repository/time_repository.dart';
|
||||||
|
|
||||||
|
class MockTimeRepository implements TimeRepository {
|
||||||
|
@override
|
||||||
|
Future<DateTime> getServerTime() async {
|
||||||
|
// simulate api delay
|
||||||
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
return DateTime.now();
|
||||||
|
}
|
||||||
|
}
|
13
lib/time/repository/time_repository.dart
Normal file
13
lib/time/repository/time_repository.dart
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import 'package:flutter_jwt_auth/time/client/time_client.dart';
|
||||||
|
import 'package:flutter_jwt_auth/time/repository/api_time_repository.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
|
part 'time_repository.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
TimeRepository timeRepository(TimeRepositoryRef ref) =>
|
||||||
|
ApiTimeRepository(ref.watch(timeClientProvider));
|
||||||
|
|
||||||
|
abstract interface class TimeRepository {
|
||||||
|
Future<DateTime> getServerTime();
|
||||||
|
}
|
25
lib/time/repository/time_repository.g.dart
Normal file
25
lib/time/repository/time_repository.g.dart
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'time_repository.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$timeRepositoryHash() => r'cbbdb501669190c470f58ab771d36c8fb5fccdd7';
|
||||||
|
|
||||||
|
/// See also [timeRepository].
|
||||||
|
@ProviderFor(timeRepository)
|
||||||
|
final timeRepositoryProvider = AutoDisposeProvider<TimeRepository>.internal(
|
||||||
|
timeRepository,
|
||||||
|
name: r'timeRepositoryProvider',
|
||||||
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$timeRepositoryHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef TimeRepositoryRef = AutoDisposeProviderRef<TimeRepository>;
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
13
lib/time/state/time_controller.dart
Normal file
13
lib/time/state/time_controller.dart
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:flutter_jwt_auth/time/repository/time_repository.dart';
|
||||||
|
|
||||||
|
part 'time_controller.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
class TimeController extends _$TimeController {
|
||||||
|
@override
|
||||||
|
Future<DateTime> build() {
|
||||||
|
final repository = ref.watch(timeRepositoryProvider);
|
||||||
|
return repository.getServerTime();
|
||||||
|
}
|
||||||
|
}
|
26
lib/time/state/time_controller.g.dart
Normal file
26
lib/time/state/time_controller.g.dart
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'time_controller.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$timeControllerHash() => r'f9d6f7e9fd0adcfde0b8efa7da793670b7a0ddae';
|
||||||
|
|
||||||
|
/// See also [TimeController].
|
||||||
|
@ProviderFor(TimeController)
|
||||||
|
final timeControllerProvider =
|
||||||
|
AutoDisposeAsyncNotifierProvider<TimeController, DateTime>.internal(
|
||||||
|
TimeController.new,
|
||||||
|
name: r'timeControllerProvider',
|
||||||
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$timeControllerHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef _$TimeController = AutoDisposeAsyncNotifier<DateTime>;
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
29
lib/time/ui/login_button.dart
Normal file
29
lib/time/ui/login_button.dart
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/state/auth_controller.dart';
|
||||||
|
|
||||||
|
class LoginButton extends ConsumerWidget {
|
||||||
|
const LoginButton({super.key});
|
||||||
|
|
||||||
|
_login(WidgetRef ref) {
|
||||||
|
ref.read(authControllerProvider.notifier).login('MyUsername');
|
||||||
|
}
|
||||||
|
|
||||||
|
_logout(WidgetRef ref) {
|
||||||
|
ref.read(authControllerProvider.notifier).logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final authState = ref.watch(authControllerProvider);
|
||||||
|
|
||||||
|
final isAuthenticated = authState.valueOrNull != null;
|
||||||
|
|
||||||
|
return TextButton(
|
||||||
|
onPressed: () => isAuthenticated ? _logout(ref) : _login(ref),
|
||||||
|
child: Text(
|
||||||
|
isAuthenticated ? 'Log out' : 'Log in',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1,102 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_jwt_auth/auth/state/auth_controller.dart';
|
||||||
|
import 'package:flutter_jwt_auth/common/ui/error_view.dart';
|
||||||
|
import 'package:flutter_jwt_auth/common/ui/loading_view.dart';
|
||||||
|
import 'package:flutter_jwt_auth/time/state/time_controller.dart';
|
||||||
|
import 'package:flutter_jwt_auth/time/ui/login_button.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
class TimePage extends ConsumerWidget {
|
||||||
|
const TimePage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
ref.listen(authControllerProvider, (prev, state) {
|
||||||
|
if (state.hasError) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
content: Text('Login error occurred'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('JWT Auth Tutorial'),
|
||||||
|
actions: const [
|
||||||
|
LoginButton(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: const Column(
|
||||||
|
children: [
|
||||||
|
_AuthContent(),
|
||||||
|
_TimeContent(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AuthContent extends ConsumerWidget {
|
||||||
|
const _AuthContent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final authState = ref.watch(authControllerProvider);
|
||||||
|
|
||||||
|
return authState.when(
|
||||||
|
data: (authData) => Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
subtitle: const Text('Token'),
|
||||||
|
title: Text(authData?.token ?? '–'),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
subtitle: const Text('Refresh Token'),
|
||||||
|
title: Text(authData?.refreshToken ?? '–'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
error: (error, trace) => Center(
|
||||||
|
child: Text(error.toString()),
|
||||||
|
),
|
||||||
|
loading: () => const LoadingView(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TimeContent extends ConsumerWidget {
|
||||||
|
const _TimeContent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final isAuthorized = ref.watch(authControllerProvider).valueOrNull != null;
|
||||||
|
|
||||||
|
if (isAuthorized) {
|
||||||
|
final timeState = ref.watch(timeControllerProvider);
|
||||||
|
return timeState.when(
|
||||||
|
data: (time) => Column(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
subtitle: const Text('Current Server Time'),
|
||||||
|
title: Text(time.toString()),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () => ref.refresh(timeControllerProvider.future),
|
||||||
|
child: const Text('Refresh'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
error: (error, trace) => ErrorView(error: error),
|
||||||
|
loading: () => const LoadingView(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return const Center(
|
||||||
|
child: Text('Unauthorized'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
581
pubspec.lock
581
pubspec.lock
@ -1,6 +1,43 @@
|
|||||||
# Generated by pub
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
packages:
|
||||||
|
_fe_analyzer_shared:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: _fe_analyzer_shared
|
||||||
|
sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "72.0.0"
|
||||||
|
_macros:
|
||||||
|
dependency: transitive
|
||||||
|
description: dart
|
||||||
|
source: sdk
|
||||||
|
version: "0.3.2"
|
||||||
|
analyzer:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: analyzer
|
||||||
|
sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.7.0"
|
||||||
|
analyzer_plugin:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: analyzer_plugin
|
||||||
|
sha256: "9661b30b13a685efaee9f02e5d01ed9f2b423bd889d28a304d02d704aee69161"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.11.3"
|
||||||
|
args:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: args
|
||||||
|
sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.0"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -17,6 +54,70 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.1"
|
||||||
|
build:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: build
|
||||||
|
sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
|
build_config:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: build_config
|
||||||
|
sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.1"
|
||||||
|
build_daemon:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: build_daemon
|
||||||
|
sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.2"
|
||||||
|
build_resolvers:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: build_resolvers
|
||||||
|
sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.2"
|
||||||
|
build_runner:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: build_runner
|
||||||
|
sha256: dd09dd4e2b078992f42aac7f1a622f01882a8492fef08486b27ddde929c19f04
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.12"
|
||||||
|
build_runner_core:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: build_runner_core
|
||||||
|
sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.3.2"
|
||||||
|
built_collection:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: built_collection
|
||||||
|
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.1.1"
|
||||||
|
built_value:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: built_value
|
||||||
|
sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "8.9.2"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -25,6 +126,30 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.0"
|
||||||
|
checked_yaml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: checked_yaml
|
||||||
|
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.3"
|
||||||
|
ci:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: ci
|
||||||
|
sha256: "145d095ce05cddac4d797a158bc4cf3b6016d1fe63d8c3d2fbd7212590adca13"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.0"
|
||||||
|
cli_util:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cli_util
|
||||||
|
sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.1"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -33,6 +158,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.1"
|
||||||
|
code_builder:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: code_builder
|
||||||
|
sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.10.0"
|
||||||
collection:
|
collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -41,6 +174,70 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.18.0"
|
version: "1.18.0"
|
||||||
|
convert:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: convert
|
||||||
|
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.1"
|
||||||
|
crypto:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: crypto
|
||||||
|
sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.5"
|
||||||
|
custom_lint:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: custom_lint
|
||||||
|
sha256: "6e1ec47427ca968f22bce734d00028ae7084361999b41673291138945c5baca0"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.7"
|
||||||
|
custom_lint_builder:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: custom_lint_builder
|
||||||
|
sha256: ba2f90fff4eff71d202d097eb14b14f87087eaaef742e956208c0eb9d3a40a21
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.7"
|
||||||
|
custom_lint_core:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: custom_lint_core
|
||||||
|
sha256: "4ddbbdaa774265de44c97054dcec058a83d9081d071785ece601e348c18c267d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.5"
|
||||||
|
dart_style:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: dart_style
|
||||||
|
sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.7"
|
||||||
|
dio:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: dio
|
||||||
|
sha256: "5598aa796bbf4699afd5c67c0f5f6e2ed542afc956884b9cd58c306966efc260"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.7.0"
|
||||||
|
dio_web_adapter:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: dio_web_adapter
|
||||||
|
sha256: "33259a9276d6cea88774a0000cfae0d861003497755969c92faa223108620dc8"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -49,6 +246,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.1"
|
version: "1.3.1"
|
||||||
|
file:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file
|
||||||
|
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.0"
|
||||||
|
fixnum:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: fixnum
|
||||||
|
sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -62,11 +275,123 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.0.0"
|
||||||
|
flutter_riverpod:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_riverpod
|
||||||
|
sha256: "0f1974eff5bbe774bf1d870e406fc6f29e3d6f1c46bd9c58e7172ff68a785d7d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.1"
|
||||||
|
flutter_secure_storage:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_secure_storage
|
||||||
|
sha256: "9f3dd2ac3b6875b0fde5b04734789c3ef35ba3965c18e99dd564a7a2f8056df6"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.2.1"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
freezed:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: freezed
|
||||||
|
sha256: "44c19278dd9d89292cf46e97dc0c1e52ce03275f40a97c5a348e802a924bf40e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.7"
|
||||||
|
freezed_annotation:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: freezed_annotation
|
||||||
|
sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.4"
|
||||||
|
frontend_server_client:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: frontend_server_client
|
||||||
|
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.0"
|
||||||
|
glob:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: glob
|
||||||
|
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
graphs:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: graphs
|
||||||
|
sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.2"
|
||||||
|
hotreloader:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: hotreloader
|
||||||
|
sha256: ed56fdc1f3a8ac924e717257621d09e9ec20e308ab6352a73a50a1d7a4d9158e
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.2.0"
|
||||||
|
http_multi_server:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_multi_server
|
||||||
|
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.1"
|
||||||
|
http_parser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_parser
|
||||||
|
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.2"
|
||||||
|
io:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: io
|
||||||
|
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.4"
|
||||||
|
js:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: js
|
||||||
|
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.7.1"
|
||||||
|
json_annotation:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: json_annotation
|
||||||
|
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.9.0"
|
||||||
|
json_serializable:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: json_serializable
|
||||||
|
sha256: ea1432d167339ea9b5bb153f0571d0039607a873d6e04e0117af043f14a1fd4b
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.8.0"
|
||||||
leak_tracker:
|
leak_tracker:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -99,6 +424,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.0.0"
|
||||||
|
logging:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: logging
|
||||||
|
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
|
macros:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: macros
|
||||||
|
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.2-main.4"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -123,6 +464,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.15.0"
|
version: "1.15.0"
|
||||||
|
mime:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: mime
|
||||||
|
sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.6"
|
||||||
|
package_config:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: package_config
|
||||||
|
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -131,11 +488,147 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.0"
|
version: "1.9.0"
|
||||||
|
pool:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pool
|
||||||
|
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.5.1"
|
||||||
|
pretty_dio_logger:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: pretty_dio_logger
|
||||||
|
sha256: "36f2101299786d567869493e2f5731de61ce130faa14679473b26905a92b6407"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.0"
|
||||||
|
protobuf:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: protobuf
|
||||||
|
sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.0"
|
||||||
|
pub_semver:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pub_semver
|
||||||
|
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.4"
|
||||||
|
pubspec_parse:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pubspec_parse
|
||||||
|
sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.0"
|
||||||
|
retrofit:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: retrofit
|
||||||
|
sha256: "3c9885ef3dbc5dc4b3fb0a40c972ab52e4dad04d52dac9bba24dfa76cf100451"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.4.1"
|
||||||
|
retrofit_generator:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: retrofit_generator
|
||||||
|
sha256: f20982392512587b1cce6cd34e3cf953a01a3fe8f82e4c34e10afe65e70c3556
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "9.1.2"
|
||||||
|
riverpod:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: riverpod
|
||||||
|
sha256: f21b32ffd26a36555e501b04f4a5dca43ed59e16343f1a30c13632b2351dfa4d
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.1"
|
||||||
|
riverpod_analyzer_utils:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: riverpod_analyzer_utils
|
||||||
|
sha256: ac28d7bc678471ec986b42d88e5a0893513382ff7542c7ac9634463b044ac72c
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.4"
|
||||||
|
riverpod_annotation:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: riverpod_annotation
|
||||||
|
sha256: e5e796c0eba4030c704e9dae1b834a6541814963292839dcf9638d53eba84f5c
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.5"
|
||||||
|
riverpod_generator:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: riverpod_generator
|
||||||
|
sha256: "63311e361ffc578d655dfc31b48dfa4ed3bc76fd06f9be845e9bf97c5c11a429"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.3"
|
||||||
|
riverpod_lint:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: riverpod_lint
|
||||||
|
sha256: a35a92f2c2a4b7a5d95671c96c5432b42c20f26bb3e985e83d0b186471b61a85
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.13"
|
||||||
|
rxdart:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: rxdart
|
||||||
|
sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.28.0"
|
||||||
|
shelf:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf
|
||||||
|
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.1"
|
||||||
|
shelf_web_socket:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf_web_socket
|
||||||
|
sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.99"
|
version: "0.0.99"
|
||||||
|
source_gen:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_gen
|
||||||
|
sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.5.0"
|
||||||
|
source_helper:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_helper
|
||||||
|
sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.4"
|
||||||
source_span:
|
source_span:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -144,6 +637,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.0"
|
version: "1.10.0"
|
||||||
|
sprintf:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sprintf
|
||||||
|
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -152,6 +653,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.11.1"
|
version: "1.11.1"
|
||||||
|
state_notifier:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: state_notifier
|
||||||
|
sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
stream_channel:
|
stream_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -160,6 +669,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.2"
|
||||||
|
stream_transform:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stream_transform
|
||||||
|
sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
string_scanner:
|
string_scanner:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -184,6 +701,30 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.2"
|
version: "0.7.2"
|
||||||
|
timing:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: timing
|
||||||
|
sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.1"
|
||||||
|
typed_data:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: typed_data
|
||||||
|
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.2"
|
||||||
|
uuid:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: uuid
|
||||||
|
sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.5.1"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -200,6 +741,46 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "14.2.5"
|
version: "14.2.5"
|
||||||
|
watcher:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: watcher
|
||||||
|
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
|
web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web
|
||||||
|
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
|
web_socket:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web_socket
|
||||||
|
sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.6"
|
||||||
|
web_socket_channel:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web_socket_channel
|
||||||
|
sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.1"
|
||||||
|
yaml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: yaml
|
||||||
|
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.5.3 <4.0.0"
|
dart: ">=3.5.3 <4.0.0"
|
||||||
flutter: ">=3.18.0-18.0.pre.54"
|
flutter: ">=3.18.0-18.0.pre.54"
|
||||||
|
17
pubspec.yaml
17
pubspec.yaml
@ -1,4 +1,4 @@
|
|||||||
name: src
|
name: flutter_jwt_auth
|
||||||
description: "A new Flutter project."
|
description: "A new Flutter project."
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
version: 0.1.0
|
version: 0.1.0
|
||||||
@ -7,14 +7,29 @@ environment:
|
|||||||
sdk: ^3.5.3
|
sdk: ^3.5.3
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
dio: ^5.7.0
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_riverpod: ^2.5.1
|
||||||
|
flutter_secure_storage: ^4.2.1
|
||||||
|
freezed_annotation: ^2.4.4
|
||||||
|
json_annotation: ^4.9.0
|
||||||
|
pretty_dio_logger: ^1.4.0
|
||||||
|
retrofit: ^4.4.1
|
||||||
|
riverpod_annotation: ^2.3.5
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_lints: ^4.0.0
|
flutter_lints: ^4.0.0
|
||||||
|
riverpod_generator: ^2.4.3
|
||||||
|
build_runner: ^2.4.12
|
||||||
|
custom_lint: ^0.6.7
|
||||||
|
riverpod_lint: ^2.3.13
|
||||||
|
freezed: ^2.5.7
|
||||||
|
json_serializable: ^6.8.0
|
||||||
|
retrofit_generator: ^9.1.2
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
1
server/shelf-jwt-test-server
Submodule
1
server/shelf-jwt-test-server
Submodule
Submodule server/shelf-jwt-test-server added at f1368334e8
Reference in New Issue
Block a user