ios_app_v2/yobble/Views/Tab/Settings/SettingsView.swift
2025-10-24 11:03:27 +03:00

185 lines
7.4 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import SwiftUI
struct SettingsView: View {
@ObservedObject var viewModel: LoginViewModel
@EnvironmentObject private var themeManager: ThemeManager
@State private var isThemeExpanded = false
@State private var isTwoFactorActive = false
private let themeOptions = ThemeOption.ordered
private var selectedThemeOption: ThemeOption {
ThemeOption.option(for: themeManager.theme)
}
var body: some View {
Form {
// MARK: - Профиль
Section(header: Text(NSLocalizedString("Профиль", comment: ""))) {
// NavigationLink(destination: EditProfileView()) {
// Label("Мой профиль", systemImage: "person.crop.circle")
// }
NavigationLink(destination: EditPrivacyView()) {
Label(NSLocalizedString("Конфиденциальность", comment: ""), systemImage: "lock.fill")
}
NavigationLink(destination: BlockedUsersView()) {
Label(NSLocalizedString("Заблокированные пользователи", comment: ""), systemImage: "hand.raised.fill")
}
}
// MARK: - Безопасность
Section(header: Text(NSLocalizedString("Безопасность", comment: ""))) {
NavigationLink(destination: ChangePasswordView()) {
Label(NSLocalizedString("Сменить пароль", comment: ""), systemImage: "key")
}
NavigationLink(isActive: $isTwoFactorActive) {
TwoFactorAuthView()
} label: {
Label(NSLocalizedString("Двухфакторная аутентификация", comment: ""), systemImage: "lock.shield")
}
NavigationLink(destination: ActiveSessionsView()) {
Label(NSLocalizedString("Активные сессии", comment: ""), systemImage: "iphone")
}
}
// MARK: - Приложение
Section(header: Text("Приложение")) {
Button(action: openLanguageSettings) {
Label("Язык", systemImage: "globe")
}
DisclosureGroup(isExpanded: $isThemeExpanded) {
VStack(alignment: .leading, spacing: 12) {
ForEach(Array(themeOptions.enumerated()), id: \.element.id) { index, option in
themeRow(for: option)
if index < themeOptions.count - 1 {
Divider()
}
}
}
.padding(.vertical, 4)
} label: {
Label("Темы", systemImage: "moon.fill")
}
NavigationLink(destination: Text("Заглушка: Хранилище данных")) {
Label("Данные", systemImage: "externaldrive")
}
NavigationLink(destination: OtherSettingsView()) {
Label("Другое", systemImage: "ellipsis.circle")
}
}
// MARK: - Уведомления
Section(header: Text("Уведомления")) {
NavigationLink(destination: Text("Заглушка: Push-уведомления")) {
Label("Push-уведомления", systemImage: "bell")
}
}
// MARK: - Поддержка
Section(header: Text("Поддержка")) {
NavigationLink(destination: FAQView()) {
Label("Частые вопросы", systemImage: "questionmark.circle")
}
NavigationLink(destination: FeedbackView()) {
Label("Обратная связь", systemImage: "paperplane")
}
}
// MARK: - О приложении
// Section(header: Text("О приложении")) {
// VStack(alignment: .leading, spacing: 6) {
// Text(AppInfo.text_1)
// Text(AppInfo.text_2)
// Text(AppInfo.text_3)
// }
// .font(.footnote)
// .foregroundColor(.gray)
// .padding(.vertical, 4)
// }
Section(header: Text(NSLocalizedString("О приложении", comment: ""))) {
VStack(alignment: .leading, spacing: 6) {
Text(
"\(NSLocalizedString("Версия:", comment: "")) \(Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "")")
Text(
"\(NSLocalizedString("Сборка:", comment: "")) \(Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "")")
Text("© 2025 Yobble Org. \(NSLocalizedString("Все права защищены.", comment: ""))")
}
.font(.footnote)
.foregroundColor(.gray)
.padding(.vertical, 4)
}
// MARK: - Выход
Section {
Button(action: {
viewModel.logoutCurrentUser()
}) {
HStack {
Image(systemName: "arrow.backward.square")
Text("Выйти из аккаунта")
}
.foregroundColor(.red)
}
}
}
.navigationTitle("Настройки")
.onAppear {
handleTwoFactorOnboardingIfNeeded()
}
.onChange(of: viewModel.onboardingDestination) { _ in
handleTwoFactorOnboardingIfNeeded()
}
}
private func openLanguageSettings() {
guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
UIApplication.shared.open(url)
}
private func themeRow(for option: ThemeOption) -> some View {
let isSelected = option == selectedThemeOption
return Button(action: {
selectTheme(option)
}) {
HStack(spacing: 12) {
Image(systemName: isSelected ? "checkmark.circle.fill" : "circle")
.foregroundColor(isSelected ? .accentColor : .secondary)
VStack(alignment: .leading, spacing: 2) {
Text(option.title)
.foregroundColor(.primary)
if let note = option.note {
Text(note)
.font(.caption)
.foregroundColor(.secondary)
}
}
Spacer()
}
.contentShape(Rectangle())
}
.disabled(!option.isEnabled)
.opacity(option.isEnabled ? 1.0 : 0.5)
.buttonStyle(.plain)
}
private func selectTheme(_ option: ThemeOption) {
guard let mappedTheme = option.mappedTheme else { return }
themeManager.setTheme(mappedTheme)
}
}
private extension SettingsView {
func handleTwoFactorOnboardingIfNeeded() {
guard viewModel.onboardingDestination == .twoFactor else { return }
isTwoFactorActive = true
viewModel.onboardingDestination = nil
}
}