diff --git a/PediFoods/ContentView.swift b/PediFoods/ContentView.swift index 254f04c..90881e0 100644 --- a/PediFoods/ContentView.swift +++ b/PediFoods/ContentView.swift @@ -32,11 +32,13 @@ struct ContentView: View { tokenStore: tokenStore, appState: $appState ) + .transition(.move(edge: .trailing)) case .main: if isBootstrappingSession { sessionBootstrapLoadingView } else { MainTabView(selectedTab: $selectedTab, tokenStore: tokenStore, appState: $appState, enterAuth: enterAuthFlow) + .transition(.move(edge: .leading)) } } } @@ -408,7 +410,9 @@ struct ContentView: View { /// decisions/2026-08-27-payment-auth-lockout-clean-intro-screen.md. @MainActor private func enterAuthFlow() { - root = .auth + withAnimation(.easeInOut(duration: 0.3)) { + root = .auth + } } @MainActor diff --git a/PediFoods/Views/Auth/LoginEmailView.swift b/PediFoods/Views/Auth/LoginEmailView.swift index a85de32..163ef38 100644 --- a/PediFoods/Views/Auth/LoginEmailView.swift +++ b/PediFoods/Views/Auth/LoginEmailView.swift @@ -1,4 +1,7 @@ import SwiftUI +#if canImport(LCEssentials) +import LCEssentials +#endif struct LoginEmailView: View { @Binding var root: RootFlow @@ -11,7 +14,6 @@ struct LoginEmailView: View { @State var isLoading = false @State var errorMessage: String? @Environment(\.dismiss) var dismiss - @Environment(\.colorScheme) var colorScheme @ViewBuilder private var logoImage: some View { SwiftUI.Image("pedifoods") @@ -19,8 +21,18 @@ struct LoginEmailView: View { } var body: some View { + LCENavigationView { + content + } + .setLeftButton(image: AnyView(AppBackButtonIcon())) { dismiss() } + .setNavigationBarBackgroundColor(AppColors.backgroundLight) + .buttonStyle(.plain) + .preferredColorScheme(.light) + } + + private var content: some View { ZStack { - (colorScheme == .dark ? Color.black : AppColors.backgroundLight).ignoresSafeArea() + AppColors.backgroundLight.ignoresSafeArea() VStack(spacing: 0) { logoImage @@ -29,7 +41,7 @@ struct LoginEmailView: View { Text("Boas-vindas!") .font(AppTypography.heading1) - .foregroundStyle(colorScheme == .dark ? Color.white : AppColors.textPrimary) + .foregroundStyle(AppColors.textPrimary) .padding(Edge.Set.top, 8) .padding(.bottom, 16) @@ -66,7 +78,7 @@ struct LoginEmailView: View { HStack(spacing: 6) { Text("Novo por aqui?") - .foregroundStyle(colorScheme == .dark ? Color.white.opacity(0.8) : Color.gray) + .foregroundStyle(Color.gray) Text("Crie sua conta") .foregroundStyle(AppColors.primary) .onTapGesture { diff --git a/PediFoods/Views/Auth/LoginView.swift b/PediFoods/Views/Auth/LoginView.swift index dfa36a3..6413d9e 100644 --- a/PediFoods/Views/Auth/LoginView.swift +++ b/PediFoods/Views/Auth/LoginView.swift @@ -16,7 +16,9 @@ struct LoginView: View { LCENavigationView { content } - .setLeftButton(image: AnyView(AppBackButtonIcon())) { root = .main } + .setLeftButton(image: AnyView(AppBackButtonIcon())) { + withAnimation(.easeInOut(duration: 0.3)) { root = .main } + } .setTitle(text: Text("Acesse sua conta").font(AppTypography.heading2).foregroundStyle(AppColors.textPrimary)) .setNavigationBarBackgroundColor(AppColors.backgroundLight) .buttonStyle(.plain) diff --git a/PediFoods/Views/Auth/OtpView.swift b/PediFoods/Views/Auth/OtpView.swift index bcf93ce..4816b37 100644 --- a/PediFoods/Views/Auth/OtpView.swift +++ b/PediFoods/Views/Auth/OtpView.swift @@ -1,5 +1,8 @@ import SwiftUI import UIKit +#if canImport(LCEssentials) +import LCEssentials +#endif struct OtpView: View { private let resendDelaySeconds = 45 @@ -21,13 +24,23 @@ struct OtpView: View { @Environment(\.dismiss) var dismiss var body: some View { + LCENavigationView { + content + } + .setLeftButton(image: AnyView(AppBackButtonIcon())) { dismiss() } + .setNavigationBarBackgroundColor(AppColors.backgroundLight) + .buttonStyle(.plain) + .preferredColorScheme(.light) + } + + private var content: some View { ScrollView { VStack(spacing: 0) { SwiftUI.Image("pedifoods") .resizable() .scaledToFit() .frame(width: 74, height: 74) - .padding(.top, 140) + .padding(.top, 48) Text("Verificação") .font(AppTypography.heading1) @@ -122,7 +135,6 @@ struct OtpView: View { } .scrollDismissesKeyboard(.interactively) .background(AppColors.backgroundLight) - .ignoresSafeArea() .onAppear { isOtpFocused = true startResendCooldown() diff --git a/PediFoods/Views/Auth/RegistrationView.swift b/PediFoods/Views/Auth/RegistrationView.swift index a03f8bb..cb2441d 100644 --- a/PediFoods/Views/Auth/RegistrationView.swift +++ b/PediFoods/Views/Auth/RegistrationView.swift @@ -1,4 +1,7 @@ import SwiftUI +#if canImport(LCEssentials) +import LCEssentials +#endif struct RegistrationView: View { @Binding var root: RootFlow @@ -12,7 +15,6 @@ struct RegistrationView: View { @State var isLoading = false @State var errorMessage: String? @Environment(\.dismiss) var dismiss - @Environment(\.colorScheme) var colorScheme let navigate: (Route) -> Void private var isFormValid: Bool { !name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && !email.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && !phone.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && acceptedTerms } @@ -23,8 +25,18 @@ struct RegistrationView: View { } var body: some View { + LCENavigationView { + content + } + .setLeftButton(image: AnyView(AppBackButtonIcon())) { dismiss() } + .setNavigationBarBackgroundColor(AppColors.backgroundLight) + .buttonStyle(.plain) + .preferredColorScheme(.light) + } + + private var content: some View { ZStack { - (colorScheme == .dark ? Color.black : AppColors.backgroundLight).ignoresSafeArea() + AppColors.backgroundLight.ignoresSafeArea() ScrollView { VStack(spacing: 0) { @@ -34,11 +46,11 @@ struct RegistrationView: View { Text("Crie sua conta") .font(AppTypography.heading1) - .foregroundStyle(colorScheme == .dark ? Color.white : AppColors.textPrimary) + .foregroundStyle(AppColors.textPrimary) Text("Preencha os dados abaixo para começar.") .font(AppTypography.body) - .foregroundStyle(colorScheme == .dark ? Color.white : AppColors.textPrimary) + .foregroundStyle(AppColors.textPrimary) .padding(.top, 8) .padding(.bottom, 20) @@ -64,7 +76,7 @@ struct RegistrationView: View { Group { Text("Ao se cadastrar, você concorda com nossos [Termos de Uso](app://terms) e [Política de Privacidade](app://policy)") - .foregroundStyle(colorScheme == .dark ? Color.white : AppColors.textPrimary) + .foregroundStyle(AppColors.textPrimary) .tint(AppColors.primary) .environment(\.openURL, OpenURLAction { url in guard url.scheme == "app" else { return .handled } @@ -98,7 +110,7 @@ struct RegistrationView: View { HStack(spacing: 6) { Text("Já tem uma conta?") - .foregroundStyle(colorScheme == .dark ? Color.white.opacity(0.8) : AppColors.textPrimary) + .foregroundStyle(AppColors.textPrimary) NavigationLink("Entrar") { LoginEmailView(root: $root, selectedTab: $selectedTab, tokenStore: tokenStore, appState: $appState, navigate: navigate) } @@ -110,7 +122,6 @@ struct RegistrationView: View { Spacer().frame(height: 12) } } - .padding(.top, -40) } } diff --git a/PediFoodsUITests/ProfileLoggedOutFlowTests.swift b/PediFoodsUITests/ProfileLoggedOutFlowTests.swift index 2445888..5a547e3 100644 --- a/PediFoodsUITests/ProfileLoggedOutFlowTests.swift +++ b/PediFoodsUITests/ProfileLoggedOutFlowTests.swift @@ -40,4 +40,29 @@ final class ProfileLoggedOutFlowTests: XCTestCase { // Back out of `.auth` lands on the main tab bar again. XCTAssertTrue(app.buttons["Home"].waitForExistence(timeout: 5), "Back button did not return to the main flow") } + + /// The pushed auth screens (Registration, LoginEmail) must carry the + /// app's standard `AppBackButtonIcon` via `LCENavigationView`, not the + /// oversized iOS 26 system glass back button. + func testPushedAuthScreensUseAppBackButton() throws { + let app = XCUIApplication() + app.launch() + XCTAssertTrue(app.reachLoggedOutProfile()) + app.buttons["Entrar ou Cadastrar"].tap() + + XCTAssertTrue(app.buttons["Criar conta"].waitForExistence(timeout: 5)) + app.buttons["Criar conta"].tap() + XCTAssertTrue(app.staticTexts["Crie sua conta"].waitForExistence(timeout: 5)) + let regBack = app.buttons.matching(NSPredicate(format: "label == %@", "Back")).firstMatch + XCTAssertTrue(regBack.exists, "Registration screen has no LCENavigationView back button") + regBack.tap() + + XCTAssertTrue(app.buttons["Entrar"].waitForExistence(timeout: 5)) + app.buttons["Entrar"].tap() + XCTAssertTrue(app.staticTexts["Boas-vindas!"].waitForExistence(timeout: 5)) + let loginBack = app.buttons.matching(NSPredicate(format: "label == %@", "Back")).firstMatch + XCTAssertTrue(loginBack.exists, "Login e-mail screen has no LCENavigationView back button") + loginBack.tap() + XCTAssertTrue(app.buttons["Criar conta"].waitForExistence(timeout: 5), "Back did not return to the auth intro") + } }