diff --git a/yobble/Resources/Localizable.xcstrings b/yobble/Resources/Localizable.xcstrings index 4165506..9450950 100644 --- a/yobble/Resources/Localizable.xcstrings +++ b/yobble/Resources/Localizable.xcstrings @@ -400,6 +400,9 @@ }, "Вход по коду пока недоступен. Заглушка." : { + }, + "Вход по паролю" : { + }, "Вы" : { "localizations" : { @@ -540,6 +543,9 @@ } } } + }, + "Если предпочитаете классический вход, используйте логин и пароль." : { + }, "Заблокированные" : { diff --git a/yobble/Views/Login/LoginView.swift b/yobble/Views/Login/LoginView.swift index dbc5c78..8697876 100644 --- a/yobble/Views/Login/LoginView.swift +++ b/yobble/Views/Login/LoginView.swift @@ -103,38 +103,9 @@ struct PasswordLoginView: View { } var body: some View { - - ZStack { - Color.clear // чтобы поймать тап - .contentShape(Rectangle()) - .onTapGesture { - focusedField = nil - } - - VStack { - HStack { - - Button(action: openLanguageSettings) { - Text("🌍") - .padding() - } - Spacer() - Menu { - ForEach(themeOptions) { option in - Button(action: { selectTheme(option) }) { - themeMenuContent(for: option) - .opacity(option.isEnabled ? 1.0 : 0.5) - } - .disabled(!option.isEnabled) - } - } label: { - Image(systemName: themeIconName) - .padding() - } - } - .onTapGesture { - focusedField = nil - } + ScrollView(showsIndicators: false) { + VStack(alignment: .leading, spacing: 24) { + LoginTopBar(openLanguageSettings: openLanguageSettings) Button { focusedField = nil @@ -142,66 +113,59 @@ struct PasswordLoginView: View { viewModel.showPasswordlessRequest() } } label: { - HStack(spacing: 4) { + HStack(spacing: 6) { Image(systemName: "arrow.left") Text(NSLocalizedString("Войти по коду", comment: "")) } .font(.footnote) .foregroundColor(.blue) - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.top, 4) } - Spacer() + VStack(alignment: .leading, spacing: 8) { + Text(NSLocalizedString("Вход по паролю", comment: "")) + .font(.largeTitle).bold() + Text(NSLocalizedString("Если предпочитаете классический вход, используйте логин и пароль.", comment: "")) + .foregroundColor(.secondary) + } - TextField(NSLocalizedString("Логин", comment: ""), text: $viewModel.username) - .padding() - .background(Color(.secondarySystemBackground)) - .cornerRadius(8) - .autocapitalization(.none) - .disableAutocorrection(true) - .focused($focusedField, equals: .username) - .onChange(of: viewModel.username) { newValue in - if newValue.count > 32 { - viewModel.username = String(newValue.prefix(32)) + VStack(alignment: .leading, spacing: 12) { + TextField(NSLocalizedString("Логин", comment: ""), text: $viewModel.username) + .padding() + .background(Color(.secondarySystemBackground)) + .cornerRadius(12) + .autocapitalization(.none) + .disableAutocorrection(true) + .focused($focusedField, equals: .username) + .onChange(of: viewModel.username) { newValue in + if newValue.count > 32 { + viewModel.username = String(newValue.prefix(32)) + } } + + if !isUsernameValid && !viewModel.username.isEmpty { + Text(NSLocalizedString("Неверный логин", comment: "Неверный логин")) + .foregroundColor(.red) + .font(.caption) } - // Показываем ошибку для логина - if !isUsernameValid && !viewModel.username.isEmpty { - Text(NSLocalizedString("Неверный логин", comment: "Неверный логин")) - .foregroundColor(.red) - .font(.caption) - } - - // Показываем поле пароля - SecureField(NSLocalizedString("Пароль", comment: ""), text: $viewModel.password) - .padding() - .background(Color(.secondarySystemBackground)) - .cornerRadius(8) - .autocapitalization(.none) - .focused($focusedField, equals: .password) - .onChange(of: viewModel.password) { newValue in - if newValue.count > 32 { - viewModel.password = String(newValue.prefix(32)) + SecureField(NSLocalizedString("Пароль", comment: ""), text: $viewModel.password) + .padding() + .background(Color(.secondarySystemBackground)) + .cornerRadius(12) + .autocapitalization(.none) + .focused($focusedField, equals: .password) + .onChange(of: viewModel.password) { newValue in + if newValue.count > 32 { + viewModel.password = String(newValue.prefix(32)) + } } - } - - // Показываем ошибку для пароля - if !isPasswordValid && !viewModel.password.isEmpty { - Text(NSLocalizedString("Неверный пароль", comment: "Неверный пароль")) - .foregroundColor(.red) - .font(.caption) - } -// TermsAgreementCard( -// isAccepted: $viewModel.hasAcceptedTerms, -// openTerms: { -// viewModel.loadTermsIfNeeded() -// isShowingTerms = true -// } -// ) -// .padding(.vertical, 12) + if !isPasswordValid && !viewModel.password.isEmpty { + Text(NSLocalizedString("Неверный пароль", comment: "Неверный пароль")) + .foregroundColor(.red) + .font(.caption) + } + } VStack(alignment: .leading, spacing: 4) { Toggle(NSLocalizedString("Режим мессенжера", comment: ""), isOn: $isMessengerModeEnabled) @@ -212,65 +176,57 @@ struct PasswordLoginView: View { .font(.footnote) .foregroundColor(.secondary) } - .padding(.vertical, 8) - + Button(action: { viewModel.login() }) { if viewModel.isLoading { ProgressView() .progressViewStyle(CircularProgressViewStyle()) - .padding() .frame(maxWidth: .infinity) - .background(Color.gray.opacity(0.6)) - .cornerRadius(8) + .padding() } else { Text(NSLocalizedString("Войти", comment: "")) .foregroundColor(.white) - .padding() .frame(maxWidth: .infinity) - .background(isLoginButtonEnabled ? Color.blue : Color.gray) - .cornerRadius(8) + .padding() } } + .background(isLoginButtonEnabled ? Color.blue : Color.gray) + .cornerRadius(12) .disabled(!isLoginButtonEnabled) -// Spacer() - - // Кнопка регистрации Button(action: { isShowingRegistration = true viewModel.hasAcceptedTerms = false }) { Text(NSLocalizedString("Нет аккаунта? Регистрация", comment: "Регистрация")) .foregroundColor(.blue) + .frame(maxWidth: .infinity) } - .padding(.top, 10) + .padding(.top, 4) .sheet(isPresented: $isShowingRegistration) { RegistrationView(viewModel: viewModel, isPresented: $isShowingRegistration) } - - Spacer() - + + Spacer(minLength: 0) } - .padding() - .loginErrorAlert(viewModel: viewModel) - .onAppear { - if !hasResetTermsOnAppear { - viewModel.hasAcceptedTerms = false - hasResetTermsOnAppear = true - } - if shouldShowLegacySupportNotice { - showLegacySupportNotice = true - } + .padding(.vertical, 32) + } + .padding(.horizontal, 24) + .background(Color(.systemBackground).ignoresSafeArea()) + .contentShape(Rectangle()) + .onTapGesture { + focusedField = nil + } + .loginErrorAlert(viewModel: viewModel) + .onAppear { + if !hasResetTermsOnAppear { + viewModel.hasAcceptedTerms = false + hasResetTermsOnAppear = true } - .onTapGesture { - focusedField = nil - } - if showLegacySupportNotice { - LegacySupportNoticeView(isPresented: $showLegacySupportNotice) - .transition(.opacity) - .zIndex(1) + if shouldShowLegacySupportNotice { + showLegacySupportNotice = true } } .fullScreenCover(isPresented: $isShowingTerms) { @@ -290,6 +246,12 @@ struct PasswordLoginView: View { } } } + .overlay(alignment: .center) { + if showLegacySupportNotice { + LegacySupportNoticeView(isPresented: $showLegacySupportNotice) + .transition(.opacity) + } + } } private var themeIconName: String { switch themeManager.theme {