Skip to content

Commit 149be6b

Browse files
Merge branch 'main' into opt-in-email-provider
2 parents 2d8ce09 + bf922dd commit 149be6b

File tree

9 files changed

+120
-69
lines changed

9 files changed

+120
-69
lines changed

FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Services/AuthConfiguration.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ public struct AuthConfiguration {
66
let interactiveDismissEnabled: Bool
77
let shouldAutoUpgradeAnonymousUsers: Bool
88
let customStringsBundle: Bundle?
9-
let tosUrl: URL
10-
let privacyPolicyUrl: URL
9+
let tosUrl: URL?
10+
let privacyPolicyUrl: URL?
1111
let emailLinkSignInActionCodeSettings: ActionCodeSettings?
1212
let verifyEmailActionCodeSettings: ActionCodeSettings?
1313

1414
public init(shouldHideCancelButton: Bool = false,
1515
interactiveDismissEnabled: Bool = true,
1616
shouldAutoUpgradeAnonymousUsers: Bool = false,
1717
customStringsBundle: Bundle? = nil,
18-
tosUrl: URL = URL(string: "https://example.com/tos")!,
19-
privacyPolicyUrl: URL = URL(string: "https://example.com/privacy")!,
18+
tosUrl: URL? = nil,
19+
privacyPolicyUrl: URL? = nil,
2020
emailLinkSignInActionCodeSettings: ActionCodeSettings? = nil,
2121
verifyEmailActionCodeSettings: ActionCodeSettings? = nil) {
2222
self.shouldHideCancelButton = shouldHideCancelButton

FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/StringUtils.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,4 +329,25 @@ public class StringUtils {
329329
public var verifyPhoneNumberAndSignInLabel: String {
330330
return localizedString(for: "Verify phone number and sign-in")
331331
}
332+
333+
/// Terms of Service label
334+
/// found in:
335+
/// - PrivacyTOCsView
336+
public var termsOfServiceLabel: String {
337+
return localizedString(for: "TermsOfService")
338+
}
339+
340+
/// Terms of Service message
341+
/// found in:
342+
/// - PrivacyTOCsView
343+
public var termsOfServiceMessage: String {
344+
return localizedString(for: "TermsOfServiceMessage")
345+
}
346+
347+
/// Privacy Policy
348+
/// found in:
349+
/// - PrivacyTOCsView
350+
public var privacyPolicyLabel: String {
351+
return localizedString(for: "PrivacyPolicy")
352+
}
332353
}

FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/AuthPickerView.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ extension AuthPickerView: View {
3232
VStack { Divider() }
3333
EmailAuthView()
3434
}
35-
authService.renderButtons()
35+
VStack {
36+
authService.renderButtons()
37+
}.padding(.horizontal)
3638
if authService.emailSignInEnabled {
3739
VStack { Divider() }
3840
HStack {
@@ -50,6 +52,7 @@ extension AuthPickerView: View {
5052
.foregroundColor(.blue)
5153
}
5254
}
55+
PrivacyTOCsView(displayMode: .footer)
5356
Text(authService.errorMessage).foregroundColor(.red)
5457
}
5558
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//
2+
// PrivacyTOCsView.swift
3+
// FirebaseUI
4+
//
5+
// Created by Russell Wheatley on 12/05/2025.
6+
//
7+
import FirebaseCore
8+
import SwiftUI
9+
10+
@MainActor
11+
struct PrivacyTOCsView {
12+
@Environment(AuthService.self) private var authService
13+
enum DisplayMode {
14+
case full, footer
15+
}
16+
17+
let displayMode: DisplayMode
18+
19+
public init(displayMode: DisplayMode = .full) {
20+
self.displayMode = displayMode
21+
}
22+
23+
private func attributedMessage(tosURL: URL, privacyURL: URL) -> AttributedString {
24+
let tosText = authService.string.termsOfServiceLabel
25+
let privacyText = authService.string.privacyPolicyLabel
26+
27+
let format: String = displayMode == .full
28+
? authService.string.termsOfServiceMessage
29+
: "%@ %@"
30+
31+
let fullText = String(format: format, tosText, privacyText)
32+
33+
var attributed = AttributedString(fullText)
34+
35+
if let tosRange = attributed.range(of: tosText) {
36+
attributed[tosRange].link = tosURL
37+
attributed[tosRange].foregroundColor = .blue
38+
}
39+
40+
if let privacyRange = attributed.range(of: privacyText) {
41+
attributed[privacyRange].link = privacyURL
42+
attributed[privacyRange].foregroundColor = .blue
43+
}
44+
45+
return attributed
46+
}
47+
}
48+
49+
extension PrivacyTOCsView: View {
50+
public var body: some View {
51+
Group {
52+
if let tosURL = authService.configuration.tosUrl,
53+
let privacyURL = authService.configuration.privacyPolicyUrl {
54+
Text(attributedMessage(tosURL: tosURL, privacyURL: privacyURL))
55+
.multilineTextAlignment(displayMode == .full ? .leading : .trailing)
56+
.font(.footnote)
57+
.foregroundColor(.primary)
58+
.padding()
59+
} else {
60+
EmptyView()
61+
}
62+
}
63+
}
64+
}
65+
66+
#Preview {
67+
FirebaseOptions.dummyConfigurationForPreview()
68+
let configuration = AuthConfiguration(
69+
tosUrl: URL(string: "https://example.com/tos"),
70+
privacyPolicyUrl: URL(string: "https://example.com/privacy")
71+
)
72+
let authService = AuthService(configuration: configuration)
73+
return PrivacyTOCsView(displayMode: .footer)
74+
.environment(authService)
75+
}

FirebaseSwiftUI/FirebaseFacebookSwiftUI/Sources/Views/SignInWithFacebookButton.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,13 @@ extension SignInWithFacebookButton: View {
6464
}) {
6565
HStack {
6666
Image(systemName: "f.circle.fill")
67-
.font(.title)
67+
.font(.title2)
6868
.foregroundColor(.white)
6969
Text(authService.string.facebookLoginButtonLabel)
7070
.fontWeight(.semibold)
7171
.foregroundColor(.white)
7272
}
73+
.frame(maxWidth: .infinity, alignment: .leading)
7374
.padding()
7475
.frame(maxWidth: .infinity)
7576
.background(Color.blue)

FirebaseSwiftUI/FirebaseGoogleSwiftUI/Sources/Services/GoogleProviderAuthUI.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@ public class GoogleProviderAuthUI: @preconcurrency GoogleProviderAuthUIProtocol
2727
}
2828

2929
@MainActor public func authButton() -> AnyView {
30-
AnyView(GoogleSignInButton {
30+
let customViewModel = GoogleSignInButtonViewModel(
31+
scheme: .light,
32+
style: .wide,
33+
state: .normal
34+
)
35+
return AnyView(GoogleSignInButton(viewModel: customViewModel) {
3136
Task {
3237
try await self.signInWithGoogle(clientID: self.clientID)
3338
}

FirebaseSwiftUI/FirebaseGoogleSwiftUI/Sources/Views/SignInWithGoogleButton.swift

Lines changed: 0 additions & 58 deletions
This file was deleted.

FirebaseSwiftUI/README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ public struct AuthConfiguration {
7575
// custom string bundle for string localizations
7676
let customStringsBundle: Bundle?
7777
// terms of service URL
78-
let tosUrl: URL
78+
let tosUrl: URL?
7979
// privacy policy URL
80-
let privacyPolicyUrl: URL
80+
let privacyPolicyUrl: URL?
8181
// action code settings for email sign in link
8282
let emailLinkSignInActionCodeSettings: ActionCodeSettings?
8383
// action code settings verifying email address
@@ -87,13 +87,15 @@ public struct AuthConfiguration {
8787
interactiveDismissEnabled: Bool = true,
8888
shouldAutoUpgradeAnonymousUsers: Bool = false,
8989
customStringsBundle: Bundle? = nil,
90-
tosUrl: URL = URL(string: "https://example.com/tos")!,
91-
privacyPolicyUrl: URL = URL(string: "https://example.com/privacy")!,
90+
tosUrl: URL? = nil,
91+
privacyPolicyUrl: URL? = nil,
9292
emailLinkSignInActionCodeSettings: ActionCodeSettings? = nil,
9393
verifyEmailActionCodeSettings: ActionCodeSettings? = nil)
9494
}
9595
```
9696

97+
> Note: Both `tosUrl` and `privacyPolicyUrl` have to be set for them to be rendered in the UI.
98+
9799
## Configuring providers
98100

99101
1. Ensure the provider is installed from step 1 (e.g. if configuring Google provider, you need to install `FirebaseGoogleSwiftUI` package).

samples/swiftui/FirebaseSwiftUIExample/FirebaseSwiftUIExample/ContentView.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ struct ContentView: View {
2626
actionCodeSettings.setIOSBundleID(Bundle.main.bundleIdentifier!)
2727
let configuration = AuthConfiguration(
2828
shouldAutoUpgradeAnonymousUsers: true,
29+
tosUrl: URL(string: "https://example.com/tos"),
30+
privacyPolicyUrl: URL(string: "https://example.com/privacy"),
2931
emailLinkSignInActionCodeSettings: actionCodeSettings
3032
)
3133
authService = AuthService(

0 commit comments

Comments
 (0)