diff --git a/.gitignore b/.gitignore index 1a06cf8..fb8464f 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,6 @@ DerivedData/ .swiftpm/configuration/registries.json .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata .netrc + + +Secrets.swift \ No newline at end of file diff --git a/Demo/PowerSyncExample.xcodeproj/project.pbxproj b/Demo/PowerSyncExample.xcodeproj/project.pbxproj index 4f881e4..76e7d01 100644 --- a/Demo/PowerSyncExample.xcodeproj/project.pbxproj +++ b/Demo/PowerSyncExample.xcodeproj/project.pbxproj @@ -41,6 +41,7 @@ B6B3698A2C64F4B30033C307 /* Navigation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6B369892C64F4B30033C307 /* Navigation.swift */; }; B6FFD5322D06DA8000EEE60F /* PowerSync in Frameworks */ = {isa = PBXBuildFile; productRef = B6FFD5312D06DA8000EEE60F /* PowerSync */; }; BE2F26EC2DA54B2F0080F1AE /* SupabaseRemoteStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE2F26EB2DA54B2A0080F1AE /* SupabaseRemoteStorage.swift */; }; + BEE4708B2E3BBB2500140D11 /* Secrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEE4708A2E3BBB2500140D11 /* Secrets.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -108,6 +109,7 @@ B6F4213D2BC42F5B0005D0D0 /* sqlite3.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqlite3.c; path = "../powersync-kotlin/core/build/interop/sqlite/sqlite3.c"; sourceTree = ""; }; B6F421402BC430B60005D0D0 /* sqlite3.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqlite3.h; path = "../powersync-kotlin/core/build/interop/sqlite/sqlite3.h"; sourceTree = ""; }; BE2F26EB2DA54B2A0080F1AE /* SupabaseRemoteStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupabaseRemoteStorage.swift; sourceTree = ""; }; + BEE4708A2E3BBB2500140D11 /* Secrets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Secrets.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -151,6 +153,7 @@ 6A7315862B9854220004CB17 /* PowerSyncExample */ = { isa = PBXGroup; children = ( + BEE4708A2E3BBB2500140D11 /* Secrets.swift */, B65C4D6F2C60D58500176007 /* PowerSync */, B65C4D6E2C60D52E00176007 /* Components */, B65C4D6B2C60D36700176007 /* Screens */, @@ -564,6 +567,7 @@ 6ABD78672B9F2B4800558A41 /* RootView.swift in Sources */, B66658612C62179E00159A81 /* ListView.swift in Sources */, 6ABD78782B9F2D2800558A41 /* Schema.swift in Sources */, + BEE4708B2E3BBB2500140D11 /* Secrets.swift in Sources */, B65C4D6D2C60D38B00176007 /* HomeScreen.swift in Sources */, 6A7315882B9854220004CB17 /* PowerSyncExampleApp.swift in Sources */, B666585F2C62115300159A81 /* ListRow.swift in Sources */, diff --git a/Demo/PowerSyncExample/Navigation.swift b/Demo/PowerSyncExample/Navigation.swift index a8e0802..202809f 100644 --- a/Demo/PowerSyncExample/Navigation.swift +++ b/Demo/PowerSyncExample/Navigation.swift @@ -6,11 +6,6 @@ enum Route: Hashable { case signUp } -@Observable -class AuthModel { - var isAuthenticated = false -} - @Observable class NavigationModel { var path = NavigationPath() diff --git a/Demo/PowerSyncExample/PowerSync/SupabaseConnector.swift b/Demo/PowerSyncExample/PowerSync/SupabaseConnector.swift index bb27290..6024923 100644 --- a/Demo/PowerSyncExample/PowerSync/SupabaseConnector.swift +++ b/Demo/PowerSyncExample/PowerSync/SupabaseConnector.swift @@ -40,7 +40,10 @@ private enum PostgresFatalCodes { @Observable class SupabaseConnector: PowerSyncBackendConnector { let powerSyncEndpoint: String = Secrets.powerSyncEndpoint - let client: SupabaseClient = .init(supabaseURL: Secrets.supabaseURL, supabaseKey: Secrets.supabaseAnonKey) + let client: SupabaseClient = .init( + supabaseURL: Secrets.supabaseURL, + supabaseKey: Secrets.supabaseAnonKey, + ) var session: Session? private var errorCode: String? @@ -49,6 +52,7 @@ class SupabaseConnector: PowerSyncBackendConnector { override init() { super.init() + session = client.auth.currentSession observeAuthStateChangesTask = Task { [weak self] in guard let self = self else { return } diff --git a/Demo/PowerSyncExample/RootView.swift b/Demo/PowerSyncExample/RootView.swift index e4a03e1..baed264 100644 --- a/Demo/PowerSyncExample/RootView.swift +++ b/Demo/PowerSyncExample/RootView.swift @@ -3,14 +3,13 @@ import SwiftUI struct RootView: View { @Environment(SystemManager.self) var system - - @State private var authModel = AuthModel() + @State private var navigationModel = NavigationModel() var body: some View { NavigationStack(path: $navigationModel.path) { Group { - if authModel.isAuthenticated { + if system.connector.session != nil { HomeScreen() } else { SignInScreen() @@ -27,7 +26,6 @@ struct RootView: View { } } } - .environment(authModel) .environment(navigationModel) } } diff --git a/Demo/PowerSyncExample/Screens/HomeScreen.swift b/Demo/PowerSyncExample/Screens/HomeScreen.swift index 6a4da2f..8ad4437 100644 --- a/Demo/PowerSyncExample/Screens/HomeScreen.swift +++ b/Demo/PowerSyncExample/Screens/HomeScreen.swift @@ -4,7 +4,6 @@ import SwiftUI struct HomeScreen: View { @Environment(SystemManager.self) private var system - @Environment(AuthModel.self) private var authModel @Environment(NavigationModel.self) private var navigationModel @@ -16,7 +15,6 @@ struct HomeScreen: View { Button("Sign out") { Task { try await system.signOut() - authModel.isAuthenticated = false navigationModel.path = NavigationPath() } } diff --git a/Demo/PowerSyncExample/Screens/SignInScreen.swift b/Demo/PowerSyncExample/Screens/SignInScreen.swift index ce9d67e..4102f2e 100644 --- a/Demo/PowerSyncExample/Screens/SignInScreen.swift +++ b/Demo/PowerSyncExample/Screens/SignInScreen.swift @@ -8,7 +8,6 @@ private enum ActionState { struct SignInScreen: View { @Environment(SystemManager.self) private var system - @Environment(AuthModel.self) private var authModel @Environment(NavigationModel.self) private var navigationModel @State private var email = "" @@ -66,7 +65,6 @@ struct SignInScreen: View { actionState = .inFlight try await system.connector.client.auth.signIn(email: email, password: password) actionState = .result(.success(())) - authModel.isAuthenticated = true navigationModel.path = NavigationPath() } catch { withAnimation { diff --git a/Demo/PowerSyncExample/Screens/SignUpScreen.swift b/Demo/PowerSyncExample/Screens/SignUpScreen.swift index 0d2693a..4d039f1 100644 --- a/Demo/PowerSyncExample/Screens/SignUpScreen.swift +++ b/Demo/PowerSyncExample/Screens/SignUpScreen.swift @@ -8,7 +8,6 @@ private enum ActionState { struct SignUpScreen: View { @Environment(SystemManager.self) private var system - @Environment(AuthModel.self) private var authModel @Environment(NavigationModel.self) private var navigationModel @State private var email = "" @@ -66,7 +65,6 @@ struct SignUpScreen: View { redirectTo: Constants.redirectToURL ) actionState = .result(.success(())) - authModel.isAuthenticated = true navigationModel.path = NavigationPath() } catch { withAnimation { diff --git a/Demo/PowerSyncExample/Secrets.template.swift b/Demo/PowerSyncExample/Secrets.template.swift new file mode 100644 index 0000000..d7b3677 --- /dev/null +++ b/Demo/PowerSyncExample/Secrets.template.swift @@ -0,0 +1,20 @@ +import Foundation + +extension Secrets { + static var powerSyncEndpoint: String { + return "https://todo.powersync.com" + } + + static var supabaseURL: URL { + return URL(string: "https://todo.supabase.co")! + } + + static var supabaseAnonKey: String { + return "TODO" + } + + // Optional storage bucket name. Set to nil if you don't want to use storage. + static var supabaseStorageBucket: String? { + return nil + } +} \ No newline at end of file diff --git a/Demo/PowerSyncExample/_Secrets.swift b/Demo/PowerSyncExample/_Secrets.swift index 5959dc8..871ddf2 100644 --- a/Demo/PowerSyncExample/_Secrets.swift +++ b/Demo/PowerSyncExample/_Secrets.swift @@ -1,10 +1,12 @@ import Foundation -// Enter your Supabase and PowerSync project details. -enum Secrets { - static let powerSyncEndpoint = "https://your-id.powersync.journeyapps.com" - static let supabaseURL = URL(string: "https://your-id.supabase.co")! - static let supabaseAnonKey = "anon-key" - // Optional storage bucket name. Set to nil if you don't want to use storage. - static let supabaseStorageBucket: String? = nil -} \ No newline at end of file +/// A protocol which specified the base structure for secrets +protocol SecretsProvider { + static var powerSyncEndpoint: String { get } + static var supabaseURL: URL { get } + static var supabaseAnonKey: String { get } + static var supabaseStorageBucket: String? { get } +} + +// Default conforming type +enum Secrets: SecretsProvider {} diff --git a/Demo/README.md b/Demo/README.md index e3369d1..6616639 100644 --- a/Demo/README.md +++ b/Demo/README.md @@ -16,7 +16,11 @@ Follow this guide to: 1. Open this directory in XCode. -2. Open the “_Secrets” file and insert the credentials of your Supabase and PowerSync projects (more info can be found [here](https://docs.powersync.com/integration-guides/supabase-+-powersync#test-everything-using-our-demo-app)). +2. Copy the `Secrets.template.swift` file to a new `Secrets.swift` file and insert the credentials of your Supabase and PowerSync projects (more info can be found [here](https://docs.powersync.com/integration-guides/supabase-+-powersync#test-everything-using-our-demo-app)). + +```bash +cp Secrets.template.swift Secrets.swift +``` 3. You will need to enable `CasePathMacros` for SwiftUI Navigation. You can do this in settings, or just build the app and a dialog will be shown to enable `CasePathMacros`. @@ -36,7 +40,6 @@ rm -rf ~/Library/org.swift.swiftpm - Reset Packages: File -> Packages -> Reset Package Caches - Clean Build: Product -> Clean Build Folder. - ## Run project Build the project, launch the app and sign in or register a new user.