214 lines
7.3 KiB
Swift
214 lines
7.3 KiB
Swift
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
|
||
}
|
||
|
||
}
|