diff --git a/OAuthSample.xcodeproj/project.pbxproj b/OAuthSample.xcodeproj/project.pbxproj index 2db54aa..df8c44a 100644 --- a/OAuthSample.xcodeproj/project.pbxproj +++ b/OAuthSample.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ CE1FE0C22BF66AC500078EB1 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CE1FE0C12BF66AC500078EB1 /* Preview Assets.xcassets */; }; CE1FE0CA2BF66B6E00078EB1 /* OAuthKit in Frameworks */ = {isa = PBXBuildFile; productRef = CE1FE0C92BF66B6E00078EB1 /* OAuthKit */; }; CE1FE0CD2BF6F73000078EB1 /* oauth.json in Resources */ = {isa = PBXBuildFile; fileRef = CE1FE0CC2BF6F73000078EB1 /* oauth.json */; }; + CE38E0ED2E0719EB0065319C /* OAuth+Window.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE38E0EC2E0719EB0065319C /* OAuth+Window.swift */; }; CE65D4F52DEB6C4A00A24D2A /* OAuthKit in Frameworks */ = {isa = PBXBuildFile; productRef = CE65D4F42DEB6C4A00A24D2A /* OAuthKit */; }; CEC9CBB62DE946EF00F181DF /* OAuthKit in Frameworks */ = {isa = PBXBuildFile; productRef = CEC9CBB52DE946EF00F181DF /* OAuthKit */; }; /* End PBXBuildFile section */ @@ -26,6 +27,7 @@ CE1FE0C12BF66AC500078EB1 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; CE1FE0CB2BF66CC500078EB1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; CE1FE0CC2BF6F73000078EB1 /* oauth.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = oauth.json; sourceTree = ""; }; + CE38E0EC2E0719EB0065319C /* OAuth+Window.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OAuth+Window.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -61,12 +63,11 @@ CE1FE0B82BF66AC400078EB1 /* OAuthSample */ = { isa = PBXGroup; children = ( - CE1FE0CB2BF66CC500078EB1 /* Info.plist */, - CE1FE0B92BF66AC400078EB1 /* OAuthSampleApp.swift */, - CE1FE0BB2BF66AC400078EB1 /* ContentView.swift */, + CE38E0EB2E0719990065319C /* Classes */, + CE1FE0C02BF66AC500078EB1 /* Preview Content */, CE1FE0BD2BF66AC500078EB1 /* Assets.xcassets */, + CE1FE0CB2BF66CC500078EB1 /* Info.plist */, CE1FE0BF2BF66AC500078EB1 /* OAuthSample.entitlements */, - CE1FE0C02BF66AC500078EB1 /* Preview Content */, ); path = OAuthSample; sourceTree = ""; @@ -80,6 +81,24 @@ path = "Preview Content"; sourceTree = ""; }; + CE38E0EB2E0719990065319C /* Classes */ = { + isa = PBXGroup; + children = ( + CE38E0EE2E071A360065319C /* Extensions */, + CE1FE0B92BF66AC400078EB1 /* OAuthSampleApp.swift */, + CE1FE0BB2BF66AC400078EB1 /* ContentView.swift */, + ); + path = Classes; + sourceTree = ""; + }; + CE38E0EE2E071A360065319C /* Extensions */ = { + isa = PBXGroup; + children = ( + CE38E0EC2E0719EB0065319C /* OAuth+Window.swift */, + ); + path = Extensions; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -160,6 +179,7 @@ buildActionMask = 2147483647; files = ( CE1FE0BC2BF66AC400078EB1 /* ContentView.swift in Sources */, + CE38E0ED2E0719EB0065319C /* OAuth+Window.swift in Sources */, CE1FE0BA2BF66AC400078EB1 /* OAuthSampleApp.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/OAuthSample/ContentView.swift b/OAuthSample/Classes/ContentView.swift similarity index 97% rename from OAuthSample/ContentView.swift rename to OAuthSample/Classes/ContentView.swift index 1728a08..26e9e8b 100644 --- a/OAuthSample/ContentView.swift +++ b/OAuthSample/Classes/ContentView.swift @@ -92,13 +92,13 @@ struct ContentView: View { private func openWebView() { #if !os(tvOS) - openWindow(id: "oauth") + openWindow(id: .oauth) #endif } private func dismissWebView() { #if !os(tvOS) - dismissWindow(id: "oauth") + dismissWindow(id: .oauth) #endif } diff --git a/OAuthSample/Classes/Extensions/OAuth+Window.swift b/OAuthSample/Classes/Extensions/OAuth+Window.swift new file mode 100644 index 0000000..1ea4c80 --- /dev/null +++ b/OAuthSample/Classes/Extensions/OAuth+Window.swift @@ -0,0 +1,49 @@ +// +// OAuth+Window.swift +// OAuthSample +// +// Created by Kevin McKee +// + +import OAuthKit +import SwiftUI + +extension OAuth { + + /// Provides a convenience enum that identifies application scene windows that can be opened or dismissed. + public enum Window: String { + /// Identifies the OAWebView window wrapper that coordinates oauth authorization flows inside a WKWebView. + case oauth + } +} + +public extension WindowGroup { + + /// Convenience initializer that accepts a `OAuth.Window` as the identifier. + /// - Parameters: + /// - id: the oauth window group + /// - makeContent: the make content closure + nonisolated init(id: OAuth.Window, @ViewBuilder makeContent: @escaping () -> Content) { + self.init(id: id.rawValue, makeContent: makeContent) + } +} + +public extension OpenWindowAction { + + /// Convenience function that allows the application to open a window with an `OAuth.Window` + /// - Parameters: + /// - id: the oauth window group + @MainActor @preconcurrency func callAsFunction(id: OAuth.Window) { + callAsFunction(id: id.rawValue) + } +} + +public extension DismissWindowAction { + + /// Convenience function that allows the application to dismiss a window with an `OAuth.Window` + /// - Parameters: + /// - id: the oauth window group + @MainActor @preconcurrency func callAsFunction(id: OAuth.Window) { + callAsFunction(id: id.rawValue) + } +} diff --git a/OAuthSample/OAuthSampleApp.swift b/OAuthSample/Classes/OAuthSampleApp.swift similarity index 91% rename from OAuthSample/OAuthSampleApp.swift rename to OAuthSample/Classes/OAuthSampleApp.swift index 1b4c79f..6a55e9f 100644 --- a/OAuthSample/OAuthSampleApp.swift +++ b/OAuthSample/Classes/OAuthSampleApp.swift @@ -21,7 +21,7 @@ struct OAuthSampleApp: App { } #if !os(tvOS) - WindowGroup(id: "oauth") { + WindowGroup(id: .oauth) { OAWebView(oauth: oauth) } #endif diff --git a/README.md b/README.md index d6903a0..f0c3852 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,9 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-indigo.svg)](https://opensource.org/licenses/MIT) # OAuthKit Sample -Sample Swift Application for using the [OAuthKit](https://github.com/codefiesta/OAuthKit) Library. +Sample Swift Application for using the [OAuthKit](https://github.com/codefiesta/OAuthKit) Library. This sample application demonstrates how to get up and running quickly with [OAuthKit](https://github.com/codefiesta/OAuthKit) and supports iOS, macOS, tvOS, and visionOS. + +![Vision_Pro_Screenshot](https://github.com/user-attachments/assets/692da254-e4db-4d65-a26f-1d2212975504) ## Configuration This sample application provides a number of pre-configured OAuth 2.0 providers listed in the [outh.json](https://github.com/codefiesta/OAuthSample/blob/main/OAuthSample/Preview%20Content/oauth.json) file. You'll need to replace the clientID and clientSecret values with your own to run the sample application.