Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
@preconcurrency import FirebaseAuth
import SwiftUI

public protocol ExternalAuthProvider {
public protocol ExternalAuthProvider: Identifiable {
var id: String { get }
associatedtype ButtonType: View
@MainActor @ViewBuilder func authButtonView() -> ButtonType
@MainActor func authButton() -> AnyView
@MainActor var authButtonView: Self.ButtonType { get }
}

public protocol GoogleProviderProtocol: ExternalAuthProvider {
Expand Down Expand Up @@ -97,35 +97,10 @@ public final class AuthService {
providers.append(provider)
}

public func renderButtons(spacing: CGFloat = 16) -> AnyView {
AnyView(
VStack(spacing: spacing) {
ForEach(providers, id: \.id) { provider in
provider.authButton()
}
}
)
}

@ViewBuilder
public var googleButton: some View {
if googleProvider != nil {
// For purpose of demonstration
// This produces "Type 'any View' cannot conform to 'View'"
googleProvider!.authButtonView()
} else {
EmptyView()
}
var availableProviders: [any ExternalAuthProvider] {
return providers
}

// public func renderButtonViews(spacing: CGFloat = 16) -> some View {
// VStack(spacing: spacing) {
// ForEach(providers, id: \.id) { provider in
// provider.authButtonView()
// }
// }
// }

private var safeGoogleProvider: any GoogleProviderProtocol {
get throws {
guard let provider = googleProvider else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ extension AuthPickerView: View {
Text(authService.authenticationFlow == .login ? "Login" : "Sign up")
VStack { Divider() }
EmailAuthView()

// Xcode compiler exception: Type 'any ExternalAuthProvider' cannot conform to 'ExternalAuthProvider'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@peterfriese - Following your gist example, we get this Xcode compiler error now.

I tried to remove any ExternalAuthProvider from the types in auth service for each provider but it isn't allowed because ExternalAuthProvider uses an associated type (ButtonType), Swift requires you to explicitly acknowledge it as an existential by using any ExternalAuthProvider.

RenderButtonsView(providers: authService.availableProviders)
VStack { Divider() }
HStack {
Text(authService
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// RenderButtonsView.swift
// FirebaseUI
//
// Created by Russell Wheatley on 08/05/2025.
//
import SwiftUI

struct RenderButtonsView<Provider: ExternalAuthProvider>: View {
var providers: [Provider] = []

public func renderButtonViews(spacing: CGFloat = 16) -> some View {
VStack(spacing: spacing) {
ForEach(providers, id: \.id) { provider in
provider.authButtonView
}
}
}

var body: some View {
VStack {
renderButtonViews()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public extension AuthService {
@discardableResult
func withFacebookSignIn(scopes scopes: [String]? = nil) -> AuthService {
facebookProvider = FacebookProviderSwift(scopes: scopes)
register(provider: facebookProvider!)
return self
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class FacebookProviderSwift: FacebookProviderProtocol {
AnyView(SignInWithFacebookButton())
}

@MainActor @ViewBuilder public func authButtonView() -> some View {
@MainActor public var authButtonView: some View {
SignInWithFacebookButton()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class GoogleProviderSwift: @preconcurrency GoogleProviderProtocol {
})
}

@MainActor @ViewBuilder public func authButtonView() -> some View {
@MainActor public var authButtonView: some View {
GoogleSignInButton {
Task {
try await self.signInWithGoogle(clientID: self.clientID)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class PhoneAuthProviderSwift: @preconcurrency PhoneAuthProviderProtocol {
AnyView(Text("phone button TODO"))
}

@MainActor @ViewBuilder public func authButtonView() -> some View {
@MainActor public var authButtonView: some View {
Text("phone button TODO")
}

Expand Down