ios_app_v2/yobble/Views/Tab/Settings/SettingsView.swift
2025-10-06 23:06:23 +03:00

214 lines
7.3 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
@AppStorage("isDarkMode") private var isDarkMode: Bool = true
@State private var isThemeExpanded = false
private let themeOptions: [ThemeOption] = [.system, .dark, .oledDark, .lightTest, .custom]
private enum ThemeOption: String, CaseIterable, Identifiable {
case system
case dark
case oledDark
case lightTest
case custom
var id: String { rawValue }
var title: String {
switch self {
case .system:
return "Системная"
case .oledDark:
return "OLED тёмная"
case .lightTest:
return "Светлая"
case .custom:
return "Кастомная"
case .dark:
return "Тёмная"
}
}
var note: String? {
switch self {
case .lightTest:
return "Тестовая версия"
case .custom, .dark:
return "Недоступна"
default:
return nil
}
}
var isEnabled: Bool {
switch self {
case .custom, .dark:
return false
default:
return true
}
}
var mappedTheme: Theme? {
switch self {
case .system:
return .system
case .lightTest:
return .light
case .oledDark:
return .oledDark
case .custom, .dark:
return nil
}
}
}
private var selectedThemeOption: ThemeOption {
switch themeManager.theme {
case .system:
return .system
case .light:
return .lightTest
case .oledDark:
return .oledDark
}
}
var body: some View {
Form {
// MARK: - Профиль
Section(header: Text("Профиль")) {
NavigationLink(destination: EditProfileView()) {
Label("Мой профиль", systemImage: "person.crop.circle")
}
}
// MARK: - Безопасность
Section(header: Text("Безопасность")) {
NavigationLink(destination: Text("Заглушка: Сменить пароль")) {
Label("Сменить пароль", systemImage: "key")
}
NavigationLink(destination: Text("Заглушка: Двухфакторная аутентификация")) {
Label("Двухфакторная аутентификация", systemImage: "lock.shield")
}
NavigationLink(destination: Text("Заглушка: Активные сессии")) {
Label("Активные сессии", 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: Text("Заглушка: Другие настройки")) {
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: Text("Заглушка: Обратная связь")) {
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)
}
// MARK: - Выход
Section {
Button(action: {
viewModel.logoutCurrentUser()
}) {
HStack {
Image(systemName: "arrow.backward.square")
Text("Выйти из аккаунта")
}
.foregroundColor(.red)
}
}
}
.navigationTitle("Настройки")
}
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)
isDarkMode = mappedTheme == .oledDark
}
}