diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9c651c35..93e1de4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,3 +23,14 @@ jobs: run: sudo xcode-select -s /Applications/Xcode_14.3.app - name: Run tests run: make test-library + + examples: + runs-on: macos-13 + name: Build Examples + steps: + - uses: actions/checkout@v3 + - name: Select Xcode 14.3 + run: sudo xcode-select -s /Applications/Xcode_14.3.app + - name: Build examples + run: make build-examples + diff --git a/Examples/Examples.xcodeproj/project.pbxproj b/Examples/Examples.xcodeproj/project.pbxproj index 04fc7429..dc1ec8b5 100644 --- a/Examples/Examples.xcodeproj/project.pbxproj +++ b/Examples/Examples.xcodeproj/project.pbxproj @@ -29,6 +29,16 @@ 796298992AEBBA77000AA957 /* MFAFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 796298982AEBBA77000AA957 /* MFAFlow.swift */; }; 7962989D2AEBC6F9000AA957 /* SVGView in Frameworks */ = {isa = PBXBuildFile; productRef = 7962989C2AEBC6F9000AA957 /* SVGView */; }; 79719ECE2ADF26C400737804 /* Supabase in Frameworks */ = {isa = PBXBuildFile; productRef = 79719ECD2ADF26C400737804 /* Supabase */; }; + 79FEFFAF2B07873600D36347 /* UserManagementApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79FEFFAE2B07873600D36347 /* UserManagementApp.swift */; }; + 79FEFFB12B07873600D36347 /* AppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79FEFFB02B07873600D36347 /* AppView.swift */; }; + 79FEFFB32B07873700D36347 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 79FEFFB22B07873700D36347 /* Assets.xcassets */; }; + 79FEFFB72B07873700D36347 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 79FEFFB62B07873700D36347 /* Preview Assets.xcassets */; }; + 79FEFFBC2B07874000D36347 /* Supabase in Frameworks */ = {isa = PBXBuildFile; productRef = 79FEFFBB2B07874000D36347 /* Supabase */; }; + 79FEFFBE2B07894700D36347 /* Supabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79FEFFBD2B07894700D36347 /* Supabase.swift */; }; + 79FEFFC02B07895900D36347 /* AuthView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79FEFFBF2B07895900D36347 /* AuthView.swift */; }; + 79FEFFC32B078CD800D36347 /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79FEFFC22B078CD800D36347 /* ProfileView.swift */; }; + 79FEFFC52B078D7900D36347 /* Models.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79FEFFC42B078D7900D36347 /* Models.swift */; }; + 79FEFFC72B078FB000D36347 /* SwiftUIHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79FEFFC62B078FB000D36347 /* SwiftUIHelpers.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -54,6 +64,18 @@ 795640692955AFBD0088A06F /* ErrorText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorText.swift; sourceTree = ""; }; 796298982AEBBA77000AA957 /* MFAFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MFAFlow.swift; sourceTree = ""; }; 7962989A2AEBBD9F000AA957 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 79FEFFAC2B07873600D36347 /* UserManagement.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UserManagement.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 79FEFFAE2B07873600D36347 /* UserManagementApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserManagementApp.swift; sourceTree = ""; }; + 79FEFFB02B07873600D36347 /* AppView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppView.swift; sourceTree = ""; }; + 79FEFFB22B07873700D36347 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 79FEFFB42B07873700D36347 /* UserManagement.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = UserManagement.entitlements; sourceTree = ""; }; + 79FEFFB62B07873700D36347 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 79FEFFBD2B07894700D36347 /* Supabase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Supabase.swift; sourceTree = ""; }; + 79FEFFBF2B07895900D36347 /* AuthView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthView.swift; sourceTree = ""; }; + 79FEFFC12B078B6100D36347 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 79FEFFC22B078CD800D36347 /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = ""; }; + 79FEFFC42B078D7900D36347 /* Models.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Models.swift; sourceTree = ""; }; + 79FEFFC62B078FB000D36347 /* SwiftUIHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIHelpers.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -76,6 +98,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 79FEFFA92B07873600D36347 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 79FEFFBC2B07874000D36347 /* Supabase in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -104,6 +134,7 @@ children = ( 793895C82954ABFF0044F2B8 /* Examples */, 790308E72AEE7B4D003C4A98 /* RealtimeSample */, + 79FEFFAD2B07873600D36347 /* UserManagement */, 793895C72954ABFF0044F2B8 /* Products */, 7956405A2954AC3E0088A06F /* Frameworks */, ); @@ -114,6 +145,7 @@ children = ( 793895C62954ABFF0044F2B8 /* Examples.app */, 790308E62AEE7B4D003C4A98 /* RealtimeSample.app */, + 79FEFFAC2B07873600D36347 /* UserManagement.app */, ); name = Products; sourceTree = ""; @@ -155,6 +187,32 @@ name = Frameworks; sourceTree = ""; }; + 79FEFFAD2B07873600D36347 /* UserManagement */ = { + isa = PBXGroup; + children = ( + 79FEFFC12B078B6100D36347 /* Info.plist */, + 79FEFFAE2B07873600D36347 /* UserManagementApp.swift */, + 79FEFFB02B07873600D36347 /* AppView.swift */, + 79FEFFB22B07873700D36347 /* Assets.xcassets */, + 79FEFFB42B07873700D36347 /* UserManagement.entitlements */, + 79FEFFB52B07873700D36347 /* Preview Content */, + 79FEFFBD2B07894700D36347 /* Supabase.swift */, + 79FEFFBF2B07895900D36347 /* AuthView.swift */, + 79FEFFC22B078CD800D36347 /* ProfileView.swift */, + 79FEFFC42B078D7900D36347 /* Models.swift */, + 79FEFFC62B078FB000D36347 /* SwiftUIHelpers.swift */, + ); + path = UserManagement; + sourceTree = ""; + }; + 79FEFFB52B07873700D36347 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 79FEFFB62B07873700D36347 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -201,6 +259,26 @@ productReference = 793895C62954ABFF0044F2B8 /* Examples.app */; productType = "com.apple.product-type.application"; }; + 79FEFFAB2B07873600D36347 /* UserManagement */ = { + isa = PBXNativeTarget; + buildConfigurationList = 79FEFFB82B07873700D36347 /* Build configuration list for PBXNativeTarget "UserManagement" */; + buildPhases = ( + 79FEFFA82B07873600D36347 /* Sources */, + 79FEFFA92B07873600D36347 /* Frameworks */, + 79FEFFAA2B07873600D36347 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = UserManagement; + packageProductDependencies = ( + 79FEFFBB2B07874000D36347 /* Supabase */, + ); + productName = UserManagement; + productReference = 79FEFFAC2B07873600D36347 /* UserManagement.app */; + productType = "com.apple.product-type.application"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -217,6 +295,9 @@ 793895C52954ABFF0044F2B8 = { CreatedOnToolsVersion = 14.1; }; + 79FEFFAB2B07873600D36347 = { + CreatedOnToolsVersion = 15.0.1; + }; }; }; buildConfigurationList = 793895C12954ABFF0044F2B8 /* Build configuration list for PBXProject "Examples" */; @@ -239,6 +320,7 @@ targets = ( 793895C52954ABFF0044F2B8 /* Examples */, 790308E52AEE7B4D003C4A98 /* RealtimeSample */, + 79FEFFAB2B07873600D36347 /* UserManagement */, ); }; /* End PBXProject section */ @@ -262,6 +344,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 79FEFFAA2B07873600D36347 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 79FEFFB72B07873700D36347 /* Preview Assets.xcassets in Resources */, + 79FEFFB32B07873700D36347 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -292,6 +383,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 79FEFFA82B07873600D36347 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 79FEFFB12B07873600D36347 /* AppView.swift in Sources */, + 79FEFFBE2B07894700D36347 /* Supabase.swift in Sources */, + 79FEFFC32B078CD800D36347 /* ProfileView.swift in Sources */, + 79FEFFC52B078D7900D36347 /* Models.swift in Sources */, + 79FEFFC72B078FB000D36347 /* SwiftUIHelpers.swift in Sources */, + 79FEFFC02B07895900D36347 /* AuthView.swift in Sources */, + 79FEFFAF2B07873600D36347 /* UserManagementApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ @@ -537,6 +642,91 @@ }; name = Release; }; + 79FEFFB92B07873700D36347 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = UserManagement/UserManagement.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"UserManagement/Preview Content\""; + DEVELOPMENT_TEAM = ELTTE7K8TT; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = UserManagement/Info.plist; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.supabase.UserManagement; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = auto; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 79FEFFBA2B07873700D36347 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = UserManagement/UserManagement.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"UserManagement/Preview Content\""; + DEVELOPMENT_TEAM = ELTTE7K8TT; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = UserManagement/Info.plist; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.supabase.UserManagement; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = auto; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -567,6 +757,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 79FEFFB82B07873700D36347 /* Build configuration list for PBXNativeTarget "UserManagement" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 79FEFFB92B07873700D36347 /* Debug */, + 79FEFFBA2B07873700D36347 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ @@ -620,6 +819,10 @@ isa = XCSwiftPackageProductDependency; productName = Supabase; }; + 79FEFFBB2B07874000D36347 /* Supabase */ = { + isa = XCSwiftPackageProductDependency; + productName = Supabase; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 793895BE2954ABFF0044F2B8 /* Project object */; diff --git a/Examples/ProductSample/.ci/pre_build.sh b/Examples/ProductSample/.ci/pre_build.sh deleted file mode 100644 index eff88e52..00000000 --- a/Examples/ProductSample/.ci/pre_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -cp SupportFiles/_Config.plist SupportFiles/Config.plist \ No newline at end of file diff --git a/Examples/ProductSample/.gitignore b/Examples/ProductSample/.gitignore deleted file mode 100644 index 805ba5e2..00000000 --- a/Examples/ProductSample/.gitignore +++ /dev/null @@ -1 +0,0 @@ -Config.plist diff --git a/Examples/RealtimeSample/ContentView.swift b/Examples/RealtimeSample/ContentView.swift index 45f88b06..caf67033 100644 --- a/Examples/RealtimeSample/ContentView.swift +++ b/Examples/RealtimeSample/ContentView.swift @@ -118,6 +118,8 @@ extension Message { } } -#Preview { - ContentView() -} +#if swift(>=5.9) + #Preview { + ContentView() + } +#endif diff --git a/Examples/UserManagement/AppView.swift b/Examples/UserManagement/AppView.swift new file mode 100644 index 00000000..1cfc1757 --- /dev/null +++ b/Examples/UserManagement/AppView.swift @@ -0,0 +1,35 @@ +// +// AppView.swift +// UserManagement +// +// Created by Guilherme Souza on 17/11/23. +// + +import SwiftUI + +struct AppView: View { + @State var isAuthenticated = false + + var body: some View { + Group { + if isAuthenticated { + ProfileView() + } else { + AuthView() + } + } + .task { + for await state in await supabase.auth.onAuthStateChange() { + if [.initialSession, .signedIn, .signedOut].contains(state.event) { + isAuthenticated = state.session != nil + } + } + } + } +} + +#if swift(>=5.9) + #Preview { + AppView() + } +#endif diff --git a/Examples/UserManagement/Assets.xcassets/AccentColor.colorset/Contents.json b/Examples/UserManagement/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/Examples/UserManagement/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/UserManagement/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/UserManagement/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..532cd729 --- /dev/null +++ b/Examples/UserManagement/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,63 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/UserManagement/Assets.xcassets/Contents.json b/Examples/UserManagement/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Examples/UserManagement/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/UserManagement/AuthView.swift b/Examples/UserManagement/AuthView.swift new file mode 100644 index 00000000..da30eb63 --- /dev/null +++ b/Examples/UserManagement/AuthView.swift @@ -0,0 +1,80 @@ +// +// AuthView.swift +// UserManagement +// +// Created by Guilherme Souza on 17/11/23. +// + +import Supabase +import SwiftUI + +struct AuthView: View { + @State var email = "" + @State var isLoading = false + @State var result: Result? + + var body: some View { + Form { + Section { + TextField("Email", text: $email) + .textContentType(.emailAddress) + .autocorrectionDisabled() + #if os(iOS) + .textInputAutocapitalization(.never) + #endif + } + + Section { + Button("Sign in") { + signInButtonTapped() + } + + if isLoading { + ProgressView() + } + } + + if let result { + Section { + switch result { + case .success: Text("Check you inbox.") + case let .failure(error): Text(error.localizedDescription).foregroundStyle(.red) + } + } + } + } + .onMac { $0.padding() } + .onOpenURL(perform: { url in + Task { + do { + try await supabase.auth.session(from: url) + } catch { + result = .failure(error) + } + } + }) + } + + func signInButtonTapped() { + Task { + isLoading = true + defer { isLoading = false } + + do { + try await supabase.auth.signInWithOTP( + email: email, + redirectTo: URL(string: "io.supabase.user-management://login-callback") + ) + result = .success(()) + } catch { + result = .failure(error) + } + } + } +} + +#if swift(>=5.9) + #Preview { + AuthView() + } +#endif diff --git a/Examples/UserManagement/Info.plist b/Examples/UserManagement/Info.plist new file mode 100644 index 00000000..50c754a7 --- /dev/null +++ b/Examples/UserManagement/Info.plist @@ -0,0 +1,17 @@ + + + + + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLSchemes + + io.supabase.user-management + + + + + diff --git a/Examples/UserManagement/Models.swift b/Examples/UserManagement/Models.swift new file mode 100644 index 00000000..8d18d317 --- /dev/null +++ b/Examples/UserManagement/Models.swift @@ -0,0 +1,32 @@ +// +// Models.swift +// UserManagement +// +// Created by Guilherme Souza on 17/11/23. +// + +import Foundation + +struct Profile: Decodable { + let username: String? + let fullName: String? + let website: String? + + enum CodingKeys: String, CodingKey { + case username + case fullName = "full_name" + case website + } +} + +struct UpdateProfileParams: Encodable { + let username: String + let fullName: String + let website: String + + enum CodingKeys: String, CodingKey { + case username + case fullName = "full_name" + case website + } +} diff --git a/Examples/UserManagement/Preview Content/Preview Assets.xcassets/Contents.json b/Examples/UserManagement/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Examples/UserManagement/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/UserManagement/ProfileView.swift b/Examples/UserManagement/ProfileView.swift new file mode 100644 index 00000000..85b19673 --- /dev/null +++ b/Examples/UserManagement/ProfileView.swift @@ -0,0 +1,113 @@ +// +// ProfileView.swift +// UserManagement +// +// Created by Guilherme Souza on 17/11/23. +// + +import SwiftUI + +struct ProfileView: View { + @State var username = "" + @State var fullName = "" + @State var website = "" + + @State var isLoading = false + + var body: some View { + NavigationStack { + Form { + Section { + TextField("Username", text: $username) + .textContentType(.username) + #if os(iOS) + .textInputAutocapitalization(.never) + #endif + TextField("Full name", text: $fullName) + .textContentType(.name) + TextField("Website", text: $website) + .textContentType(.URL) + #if os(iOS) + .textInputAutocapitalization(.never) + #endif + } + + Section { + Button("Update profile") { + updateProfileButtonTapped() + } + .bold() + + if isLoading { + ProgressView() + } + } + } + .onMac { $0.padding() } + .navigationTitle("Profile") + .toolbar(content: { + ToolbarItem { + Button("Sign out", role: .destructive) { + Task { + try? await supabase.auth.signOut() + } + } + } + }) + } + .task { + await getInitialProfile() + } + } + + func getInitialProfile() async { + do { + let currentUser = try await supabase.auth.session.user + + let profile: Profile = try await supabase.database + .from("profiles") + .select() + .eq("id", value: currentUser.id) + .single() + .execute() + .value + + username = profile.username ?? "" + fullName = profile.fullName ?? "" + website = profile.website ?? "" + + } catch { + debugPrint(error) + } + } + + func updateProfileButtonTapped() { + Task { + isLoading = true + defer { isLoading = false } + do { + let currentUser = try await supabase.auth.session.user + + try await supabase.database + .from("profiles") + .update( + UpdateProfileParams( + username: username, + fullName: fullName, + website: website + ) + ) + .eq("id", value: currentUser.id) + .execute() + } catch { + debugPrint(error) + } + } + } +} + +#if swift(>=5.9) + #Preview { + ProfileView() + } +#endif diff --git a/Examples/UserManagement/Supabase.swift b/Examples/UserManagement/Supabase.swift new file mode 100644 index 00000000..c76a5509 --- /dev/null +++ b/Examples/UserManagement/Supabase.swift @@ -0,0 +1,14 @@ +// +// Supabase.swift +// UserManagement +// +// Created by Guilherme Souza on 17/11/23. +// + +import Foundation +import Supabase + +let supabase = SupabaseClient( + supabaseURL: URL(string: "https://PROJECT_ID.supabase.co")!, + supabaseKey: "YOUR_SUPABASE_ANON_KEY" +) diff --git a/Examples/UserManagement/SwiftUIHelpers.swift b/Examples/UserManagement/SwiftUIHelpers.swift new file mode 100644 index 00000000..bda5b203 --- /dev/null +++ b/Examples/UserManagement/SwiftUIHelpers.swift @@ -0,0 +1,18 @@ +// +// SwiftUIHelpers.swift +// UserManagement +// +// Created by Guilherme Souza on 17/11/23. +// + +import SwiftUI + +extension View { + func onMac(_ block: (Self) -> some View) -> some View { + #if os(macOS) + return block(self) + #else + return self + #endif + } +} diff --git a/Examples/ProductSample/SupportFiles/_Config.plist b/Examples/UserManagement/UserManagement.entitlements similarity index 51% rename from Examples/ProductSample/SupportFiles/_Config.plist rename to Examples/UserManagement/UserManagement.entitlements index b325447b..625af03d 100644 --- a/Examples/ProductSample/SupportFiles/_Config.plist +++ b/Examples/UserManagement/UserManagement.entitlements @@ -2,9 +2,11 @@ - SUPABASE_ANON_KEY - SUPABASE_ANON_KEY - SUPABASE_URL - https://PROJECT_ID.supabase.co + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + com.apple.security.network.client + diff --git a/Examples/UserManagement/UserManagementApp.swift b/Examples/UserManagement/UserManagementApp.swift new file mode 100644 index 00000000..dbbe1f33 --- /dev/null +++ b/Examples/UserManagement/UserManagementApp.swift @@ -0,0 +1,17 @@ +// +// UserManagementApp.swift +// UserManagement +// +// Created by Guilherme Souza on 17/11/23. +// + +import SwiftUI + +@main +struct UserManagementApp: App { + var body: some Scene { + WindowGroup { + AppView() + } + } +} diff --git a/Makefile b/Makefile index 5466ec94..4ac17deb 100644 --- a/Makefile +++ b/Makefile @@ -34,11 +34,13 @@ test-docs: || (echo "xcodebuild docbuild failed:\n\n$(DOC_WARNINGS)" | tr '\1' '\n' \ && exit 1) -build-example: - xcodebuild build \ - -workspace supabase-swift.xcworkspace \ - -scheme "$(EXAMPLE)" \ - -destination platform="$(PLATFORM_IOS)" || exit 1; +build-examples: + for scheme in UserManagement; do \ + xcodebuild build \ + -workspace supabase-swift.xcworkspace \ + -scheme "$$scheme" \ + -destination platform="$(PLATFORM_IOS)" || exit 1; \ + done format: @swiftformat . diff --git a/Package.resolved b/Package.resolved index 09041288..a6dbd1af 100644 --- a/Package.resolved +++ b/Package.resolved @@ -9,6 +9,15 @@ "version" : "4.2.2" } }, + { + "identity" : "swift-concurrency-extras", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-concurrency-extras", + "state" : { + "revision" : "bb5059bde9022d69ac516803f4f227d8ac967f71", + "version" : "1.1.0" + } + }, { "identity" : "swift-snapshot-testing", "kind" : "remoteSourceControl", diff --git a/Tests/FunctionsTests/FunctionsClientTests.swift b/Tests/FunctionsTests/FunctionsClientTests.swift index 4c4745fa..f105982d 100644 --- a/Tests/FunctionsTests/FunctionsClientTests.swift +++ b/Tests/FunctionsTests/FunctionsClientTests.swift @@ -1,5 +1,5 @@ -import XCTest import ConcurrencyExtras +import XCTest @_spi(Internal) import _Helpers @testable import Functions