Skip to content

Commit

Permalink
Require accepting terms and privacy policy
Browse files Browse the repository at this point in the history
  • Loading branch information
LaurentTreguier committed Oct 4, 2024
1 parent 6820c22 commit fc6858d
Show file tree
Hide file tree
Showing 13 changed files with 81 additions and 71 deletions.
6 changes: 3 additions & 3 deletions Fyreplace/Fakes/FakeClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,9 @@ extension FakeClient {
static let passwordUsername = "password-username"
static let goodUsername = "good-username"

static let badEmail = "bad-email"
static let usedEmail = "used-email"
static let goodEmail = "good-email"
static let badEmail = "bad@email"
static let usedEmail = "used@email"
static let goodEmail = "good@email"

static let notImageBody = HTTPBody(stringLiteral: "Not")
static let largeImageBody = HTTPBody(stringLiteral: "Large")
Expand Down
10 changes: 10 additions & 0 deletions Fyreplace/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,16 @@
}
}
},
"Register.TermsAcceptance" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "I accept the terms of service and the privacy policy"
}
}
}
},
"Register.Username" : {
"localizations" : {
"en" : {
Expand Down
6 changes: 2 additions & 4 deletions Fyreplace/Views/Forms/DynamicForm.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ struct DynamicForm<Content>: View where Content: View {
#if os(macOS)
Form(content: content)
.formStyle(.grouped)
.frame(minWidth: 360, maxWidth: 600)
.fixedSize()
.padding()
.frame(minWidth: 360)
#else
HStack {
ZStack {
Form(content: content)
.frame(maxWidth: UIDevice.current.userInterfaceIdiom == .pad ? 600 : nil)
}
Expand Down
3 changes: 0 additions & 3 deletions Fyreplace/Views/Forms/EnvironmentPicker.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import SwiftUI

struct EnvironmentPicker: View {
let namespace: Namespace.ID

@AppStorage("connection.environment")
private var selectedEnvironment = ServerEnvironment.default

Expand All @@ -19,6 +17,5 @@ struct EnvironmentPicker: View {
}
}
.help("Environment.Help")
.matchedGeometryEffect(id: "environment-picker", in: namespace)
}
}
11 changes: 1 addition & 10 deletions Fyreplace/Views/Forms/LogoHeader.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import SwiftUI

struct LogoHeader<ImageContent, TextContent>: View where ImageContent: View, TextContent: View {
let namespace: Namespace.ID

@ViewBuilder
let imageContent: () -> ImageContent

Expand Down Expand Up @@ -40,18 +38,11 @@ struct LogoHeader<ImageContent, TextContent>: View where ImageContent: View, Tex
Spacer()
}
}
.matchedGeometryEffect(id: "header", in: namespace)
}
}

@available(macOS 14.0, *)
@available(iOS 17.0, *)
#Preview {
@Previewable
@Namespace
var namespace

LogoHeader(namespace: namespace) {
LogoHeader {
Image(systemName: "photo")
.resizable()
.scaledToFit()
Expand Down
2 changes: 0 additions & 2 deletions Fyreplace/Views/Forms/SubmitOrCancel.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import SwiftUI

struct SubmitOrCancel: View {
let namespace: Namespace.ID
let submitLabel: LocalizedStringKey
let canSubmit: Bool
let canCancel: Bool
Expand All @@ -16,7 +15,6 @@ struct SubmitOrCancel: View {
action: submitAction
)
.disabled(!canSubmit)
.matchedGeometryEffect(id: "submit", in: namespace)

let cancel = Button(role: .cancel, action: cancelAction) {
Text("Cancel").padding(.horizontal)
Expand Down
3 changes: 0 additions & 3 deletions Fyreplace/Views/Screens/AuthenticatingScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ struct AuthenticatingScreen<Content>: View where Content: View {
)
.navigationTitle("")
.handlesExternalEvents(preferring: ["*"], allowing: ["action=connect"])
#if os(macOS)
.animation(.snappy, value: choice)
#endif
} else {
content()
}
Expand Down
16 changes: 3 additions & 13 deletions Fyreplace/Views/Screens/LoginScreen.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import SwiftUI

struct LoginScreen: View, LoginScreenProtocol {
let namespace: Namespace.ID

@EnvironmentObject
var eventBus: EventBus

Expand Down Expand Up @@ -30,7 +28,7 @@ struct LoginScreen: View, LoginScreenProtocol {
var body: some View {
DynamicForm {
Section {
EnvironmentPicker(namespace: namespace).disabled(isWaitingForRandomCode)
EnvironmentPicker().disabled(isWaitingForRandomCode)

TextField(
"Login.Identifier",
Expand All @@ -41,7 +39,6 @@ struct LoginScreen: View, LoginScreenProtocol {
.focused($focused, equals: .identifier)
.disabled(isWaitingForRandomCode)
.onSubmit(submit)
.matchedGeometryEffect(id: "first-field", in: namespace)
#if !os(macOS)
.textInputAutocapitalization(.never)
.keyboardType(.asciiCapable)
Expand All @@ -68,7 +65,6 @@ struct LoginScreen: View, LoginScreenProtocol {
}

SubmitOrCancel(
namespace: namespace,
submitLabel: "Login.Submit",
canSubmit: canSubmit,
canCancel: isWaitingForRandomCode,
Expand All @@ -77,7 +73,7 @@ struct LoginScreen: View, LoginScreenProtocol {
cancelAction: cancel
)
} header: {
LogoHeader(namespace: namespace) {
LogoHeader {
Image("Logo", label: Text("Logo")).resizable()
} textContent: {
Text("Login.Header")
Expand Down Expand Up @@ -122,15 +118,9 @@ struct LoginScreen: View, LoginScreenProtocol {
}
}

@available(macOS 14.0, *)
@available(iOS 17.0, *)
#Preview {
@Previewable
@Namespace
var namespace

NavigationStack {
LoginScreen(namespace: namespace)
LoginScreen()
}
.environmentObject(EventBus())
}
59 changes: 37 additions & 22 deletions Fyreplace/Views/Screens/RegisterScreen.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import SwiftUI

struct RegisterScreen: View, RegisterScreenProtocol {
let namespace: Namespace.ID

@EnvironmentObject
var eventBus: EventBus

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

@AppStorage("account.hasAcceptedTerms")
var hasAcceptedTerms = false

@AppStorage("account.isRegistering")
var isRegistering = false

@KeychainStorage("connection.token")
var token

@Environment(\.config)
private var config

@FocusState
private var focused: FocusedField?

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

DynamicForm {
Section {
EnvironmentPicker(namespace: namespace).disabled(isWaitingForRandomCode)
EnvironmentPicker().disabled(isWaitingForRandomCode)

TextField(
"Register.Username",
Expand All @@ -59,7 +63,6 @@ struct RegisterScreen: View, RegisterScreenProtocol {
.disabled(isWaitingForRandomCode)
.submitLabel(.next)
.onSubmit { focused = .email }
.matchedGeometryEffect(id: "first-field", in: namespace)
#if !os(macOS)
.textInputAutocapitalization(.never)
.keyboardType(.asciiCapable)
Expand Down Expand Up @@ -100,18 +103,8 @@ struct RegisterScreen: View, RegisterScreenProtocol {
.keyboardType(.asciiCapable)
#endif
}

SubmitOrCancel(
namespace: namespace,
submitLabel: "Register.Submit",
canSubmit: canSubmit,
canCancel: isWaitingForRandomCode,
isLoading: isLoading,
submitAction: submit,
cancelAction: cancel
)
} header: {
LogoHeader(namespace: namespace) {
LogoHeader {
Image("Logo", label: Text("Logo")).resizable()
} textContent: {
Text("Register.Header")
Expand All @@ -132,6 +125,34 @@ struct RegisterScreen: View, RegisterScreenProtocol {
focused = .email
}
}

Section {
Toggle("Register.TermsAcceptance", isOn: $hasAcceptedTerms)
.disabled(isWaitingForRandomCode)

Link(destination: config.app.info.termsOfService) {
Label("App.Help.TermsOfService", systemImage: "shield")
}
.foregroundStyle(.tint)

Link(destination: config.app.info.privacyPolicy) {
Label("App.Help.PrivacyPolicy", systemImage: "lock")
}
.foregroundStyle(.tint)
} footer: {
Spacer()
}

Section {
SubmitOrCancel(
submitLabel: "Register.Submit",
canSubmit: canSubmit,
canCancel: isWaitingForRandomCode,
isLoading: isLoading,
submitAction: submit,
cancelAction: cancel
)
}
}
.disabled(isLoading)
.animation(.default, value: isWaitingForRandomCode)
Expand Down Expand Up @@ -161,15 +182,9 @@ struct RegisterScreen: View, RegisterScreenProtocol {
}
}

@available(macOS 14.0, *)
@available(iOS 17.0, *)
#Preview {
@Previewable
@Namespace
var namespace

NavigationStack {
RegisterScreen(namespace: namespace)
RegisterScreen()
}
.environmentObject(EventBus())
}
3 changes: 2 additions & 1 deletion Fyreplace/Views/Screens/RegisterScreenProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ protocol RegisterScreenProtocol: LoadingViewProtocol {
var email: String { get nonmutating set }
var randomCode: String { get nonmutating set }
var isWaitingForRandomCode: Bool { get nonmutating set }
var hasAcceptedTerms: Bool { get nonmutating set }
var isRegistering: Bool { get nonmutating set }
var token: String { get nonmutating set }
}
Expand All @@ -15,7 +16,7 @@ extension RegisterScreenProtocol {
var isUsernameValid: Bool { 3...50 ~= username.count }
var isEmailValid: Bool { 3...254 ~= email.count && email.contains("@") }
var canSubmit: Bool {
!isLoading
!isLoading && hasAcceptedTerms
&& (isWaitingForRandomCode ? randomCode.count >= 8 : isUsernameValid && isEmailValid)
}

Expand Down
7 changes: 2 additions & 5 deletions Fyreplace/Views/Screens/Screen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ import SwiftUI
struct Screen: View {
let destination: Destination

@Namespace
private var namespace

var body: some View {
switch destination {
case .feed:
Expand All @@ -21,9 +18,9 @@ struct Screen: View {
case .settings:
SettingsScreen()
case .login:
LoginScreen(namespace: namespace)
LoginScreen()
case .register:
RegisterScreen(namespace: namespace)
RegisterScreen()
}
}
}
2 changes: 1 addition & 1 deletion Fyreplace/Views/Screens/SettingsScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct SettingsScreen: View, SettingsScreenProtocol {
#endif
}
} header: {
LogoHeader(namespace: namespace) {
LogoHeader {
EditableAvatar(user: currentUser, avatarSelected: updateAvatar)
} textContent: {
Text("Settings.Header")
Expand Down
Loading

0 comments on commit fc6858d

Please sign in to comment.