Skip to content

Commit fc6858d

Browse files
Require accepting terms and privacy policy
1 parent 6820c22 commit fc6858d

13 files changed

+81
-71
lines changed

Fyreplace/Fakes/FakeClient.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,9 @@ extension FakeClient {
270270
static let passwordUsername = "password-username"
271271
static let goodUsername = "good-username"
272272

273-
static let badEmail = "bad-email"
274-
static let usedEmail = "used-email"
275-
static let goodEmail = "good-email"
273+
static let badEmail = "bad@email"
274+
static let usedEmail = "used@email"
275+
static let goodEmail = "good@email"
276276

277277
static let notImageBody = HTTPBody(stringLiteral: "Not")
278278
static let largeImageBody = HTTPBody(stringLiteral: "Large")

Fyreplace/Resources/Localizable.xcstrings

+10
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,16 @@
584584
}
585585
}
586586
},
587+
"Register.TermsAcceptance" : {
588+
"localizations" : {
589+
"en" : {
590+
"stringUnit" : {
591+
"state" : "translated",
592+
"value" : "I accept the terms of service and the privacy policy"
593+
}
594+
}
595+
}
596+
},
587597
"Register.Username" : {
588598
"localizations" : {
589599
"en" : {

Fyreplace/Views/Forms/DynamicForm.swift

+2-4
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@ struct DynamicForm<Content>: View where Content: View {
88
#if os(macOS)
99
Form(content: content)
1010
.formStyle(.grouped)
11-
.frame(minWidth: 360, maxWidth: 600)
12-
.fixedSize()
13-
.padding()
11+
.frame(minWidth: 360)
1412
#else
15-
HStack {
13+
ZStack {
1614
Form(content: content)
1715
.frame(maxWidth: UIDevice.current.userInterfaceIdiom == .pad ? 600 : nil)
1816
}

Fyreplace/Views/Forms/EnvironmentPicker.swift

-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import SwiftUI
22

33
struct EnvironmentPicker: View {
4-
let namespace: Namespace.ID
5-
64
@AppStorage("connection.environment")
75
private var selectedEnvironment = ServerEnvironment.default
86

@@ -19,6 +17,5 @@ struct EnvironmentPicker: View {
1917
}
2018
}
2119
.help("Environment.Help")
22-
.matchedGeometryEffect(id: "environment-picker", in: namespace)
2320
}
2421
}

Fyreplace/Views/Forms/LogoHeader.swift

+1-10
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import SwiftUI
22

33
struct LogoHeader<ImageContent, TextContent>: View where ImageContent: View, TextContent: View {
4-
let namespace: Namespace.ID
5-
64
@ViewBuilder
75
let imageContent: () -> ImageContent
86

@@ -40,18 +38,11 @@ struct LogoHeader<ImageContent, TextContent>: View where ImageContent: View, Tex
4038
Spacer()
4139
}
4240
}
43-
.matchedGeometryEffect(id: "header", in: namespace)
4441
}
4542
}
4643

47-
@available(macOS 14.0, *)
48-
@available(iOS 17.0, *)
4944
#Preview {
50-
@Previewable
51-
@Namespace
52-
var namespace
53-
54-
LogoHeader(namespace: namespace) {
45+
LogoHeader {
5546
Image(systemName: "photo")
5647
.resizable()
5748
.scaledToFit()

Fyreplace/Views/Forms/SubmitOrCancel.swift

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import SwiftUI
22

33
struct SubmitOrCancel: View {
4-
let namespace: Namespace.ID
54
let submitLabel: LocalizedStringKey
65
let canSubmit: Bool
76
let canCancel: Bool
@@ -16,7 +15,6 @@ struct SubmitOrCancel: View {
1615
action: submitAction
1716
)
1817
.disabled(!canSubmit)
19-
.matchedGeometryEffect(id: "submit", in: namespace)
2018

2119
let cancel = Button(role: .cancel, action: cancelAction) {
2220
Text("Cancel").padding(.horizontal)

Fyreplace/Views/Screens/AuthenticatingScreen.swift

-3
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ struct AuthenticatingScreen<Content>: View where Content: View {
2727
)
2828
.navigationTitle("")
2929
.handlesExternalEvents(preferring: ["*"], allowing: ["action=connect"])
30-
#if os(macOS)
31-
.animation(.snappy, value: choice)
32-
#endif
3330
} else {
3431
content()
3532
}

Fyreplace/Views/Screens/LoginScreen.swift

+3-13
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import SwiftUI
22

33
struct LoginScreen: View, LoginScreenProtocol {
4-
let namespace: Namespace.ID
5-
64
@EnvironmentObject
75
var eventBus: EventBus
86

@@ -30,7 +28,7 @@ struct LoginScreen: View, LoginScreenProtocol {
3028
var body: some View {
3129
DynamicForm {
3230
Section {
33-
EnvironmentPicker(namespace: namespace).disabled(isWaitingForRandomCode)
31+
EnvironmentPicker().disabled(isWaitingForRandomCode)
3432

3533
TextField(
3634
"Login.Identifier",
@@ -41,7 +39,6 @@ struct LoginScreen: View, LoginScreenProtocol {
4139
.focused($focused, equals: .identifier)
4240
.disabled(isWaitingForRandomCode)
4341
.onSubmit(submit)
44-
.matchedGeometryEffect(id: "first-field", in: namespace)
4542
#if !os(macOS)
4643
.textInputAutocapitalization(.never)
4744
.keyboardType(.asciiCapable)
@@ -68,7 +65,6 @@ struct LoginScreen: View, LoginScreenProtocol {
6865
}
6966

7067
SubmitOrCancel(
71-
namespace: namespace,
7268
submitLabel: "Login.Submit",
7369
canSubmit: canSubmit,
7470
canCancel: isWaitingForRandomCode,
@@ -77,7 +73,7 @@ struct LoginScreen: View, LoginScreenProtocol {
7773
cancelAction: cancel
7874
)
7975
} header: {
80-
LogoHeader(namespace: namespace) {
76+
LogoHeader {
8177
Image("Logo", label: Text("Logo")).resizable()
8278
} textContent: {
8379
Text("Login.Header")
@@ -122,15 +118,9 @@ struct LoginScreen: View, LoginScreenProtocol {
122118
}
123119
}
124120

125-
@available(macOS 14.0, *)
126-
@available(iOS 17.0, *)
127121
#Preview {
128-
@Previewable
129-
@Namespace
130-
var namespace
131-
132122
NavigationStack {
133-
LoginScreen(namespace: namespace)
123+
LoginScreen()
134124
}
135125
.environmentObject(EventBus())
136126
}

Fyreplace/Views/Screens/RegisterScreen.swift

+37-22
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import SwiftUI
22

33
struct RegisterScreen: View, RegisterScreenProtocol {
4-
let namespace: Namespace.ID
5-
64
@EnvironmentObject
75
var eventBus: EventBus
86

@@ -24,12 +22,18 @@ struct RegisterScreen: View, RegisterScreenProtocol {
2422
@AppStorage("account.isWaitingForRandomCode")
2523
var isWaitingForRandomCode = false
2624

25+
@AppStorage("account.hasAcceptedTerms")
26+
var hasAcceptedTerms = false
27+
2728
@AppStorage("account.isRegistering")
2829
var isRegistering = false
2930

3031
@KeychainStorage("connection.token")
3132
var token
3233

34+
@Environment(\.config)
35+
private var config
36+
3337
@FocusState
3438
private var focused: FocusedField?
3539

@@ -46,7 +50,7 @@ struct RegisterScreen: View, RegisterScreenProtocol {
4650

4751
DynamicForm {
4852
Section {
49-
EnvironmentPicker(namespace: namespace).disabled(isWaitingForRandomCode)
53+
EnvironmentPicker().disabled(isWaitingForRandomCode)
5054

5155
TextField(
5256
"Register.Username",
@@ -59,7 +63,6 @@ struct RegisterScreen: View, RegisterScreenProtocol {
5963
.disabled(isWaitingForRandomCode)
6064
.submitLabel(.next)
6165
.onSubmit { focused = .email }
62-
.matchedGeometryEffect(id: "first-field", in: namespace)
6366
#if !os(macOS)
6467
.textInputAutocapitalization(.never)
6568
.keyboardType(.asciiCapable)
@@ -100,18 +103,8 @@ struct RegisterScreen: View, RegisterScreenProtocol {
100103
.keyboardType(.asciiCapable)
101104
#endif
102105
}
103-
104-
SubmitOrCancel(
105-
namespace: namespace,
106-
submitLabel: "Register.Submit",
107-
canSubmit: canSubmit,
108-
canCancel: isWaitingForRandomCode,
109-
isLoading: isLoading,
110-
submitAction: submit,
111-
cancelAction: cancel
112-
)
113106
} header: {
114-
LogoHeader(namespace: namespace) {
107+
LogoHeader {
115108
Image("Logo", label: Text("Logo")).resizable()
116109
} textContent: {
117110
Text("Register.Header")
@@ -132,6 +125,34 @@ struct RegisterScreen: View, RegisterScreenProtocol {
132125
focused = .email
133126
}
134127
}
128+
129+
Section {
130+
Toggle("Register.TermsAcceptance", isOn: $hasAcceptedTerms)
131+
.disabled(isWaitingForRandomCode)
132+
133+
Link(destination: config.app.info.termsOfService) {
134+
Label("App.Help.TermsOfService", systemImage: "shield")
135+
}
136+
.foregroundStyle(.tint)
137+
138+
Link(destination: config.app.info.privacyPolicy) {
139+
Label("App.Help.PrivacyPolicy", systemImage: "lock")
140+
}
141+
.foregroundStyle(.tint)
142+
} footer: {
143+
Spacer()
144+
}
145+
146+
Section {
147+
SubmitOrCancel(
148+
submitLabel: "Register.Submit",
149+
canSubmit: canSubmit,
150+
canCancel: isWaitingForRandomCode,
151+
isLoading: isLoading,
152+
submitAction: submit,
153+
cancelAction: cancel
154+
)
155+
}
135156
}
136157
.disabled(isLoading)
137158
.animation(.default, value: isWaitingForRandomCode)
@@ -161,15 +182,9 @@ struct RegisterScreen: View, RegisterScreenProtocol {
161182
}
162183
}
163184

164-
@available(macOS 14.0, *)
165-
@available(iOS 17.0, *)
166185
#Preview {
167-
@Previewable
168-
@Namespace
169-
var namespace
170-
171186
NavigationStack {
172-
RegisterScreen(namespace: namespace)
187+
RegisterScreen()
173188
}
174189
.environmentObject(EventBus())
175190
}

Fyreplace/Views/Screens/RegisterScreenProtocol.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ protocol RegisterScreenProtocol: LoadingViewProtocol {
66
var email: String { get nonmutating set }
77
var randomCode: String { get nonmutating set }
88
var isWaitingForRandomCode: Bool { get nonmutating set }
9+
var hasAcceptedTerms: Bool { get nonmutating set }
910
var isRegistering: Bool { get nonmutating set }
1011
var token: String { get nonmutating set }
1112
}
@@ -15,7 +16,7 @@ extension RegisterScreenProtocol {
1516
var isUsernameValid: Bool { 3...50 ~= username.count }
1617
var isEmailValid: Bool { 3...254 ~= email.count && email.contains("@") }
1718
var canSubmit: Bool {
18-
!isLoading
19+
!isLoading && hasAcceptedTerms
1920
&& (isWaitingForRandomCode ? randomCode.count >= 8 : isUsernameValid && isEmailValid)
2021
}
2122

Fyreplace/Views/Screens/Screen.swift

+2-5
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ import SwiftUI
33
struct Screen: View {
44
let destination: Destination
55

6-
@Namespace
7-
private var namespace
8-
96
var body: some View {
107
switch destination {
118
case .feed:
@@ -21,9 +18,9 @@ struct Screen: View {
2118
case .settings:
2219
SettingsScreen()
2320
case .login:
24-
LoginScreen(namespace: namespace)
21+
LoginScreen()
2522
case .register:
26-
RegisterScreen(namespace: namespace)
23+
RegisterScreen()
2724
}
2825
}
2926
}

Fyreplace/Views/Screens/SettingsScreen.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ struct SettingsScreen: View, SettingsScreenProtocol {
3535
#endif
3636
}
3737
} header: {
38-
LogoHeader(namespace: namespace) {
38+
LogoHeader {
3939
EditableAvatar(user: currentUser, avatarSelected: updateAvatar)
4040
} textContent: {
4141
Text("Settings.Header")

0 commit comments

Comments
 (0)