diff --git a/yobble/Resources/Localizable.xcstrings b/yobble/Resources/Localizable.xcstrings index aee8888..7a2af57 100644 --- a/yobble/Resources/Localizable.xcstrings +++ b/yobble/Resources/Localizable.xcstrings @@ -577,7 +577,7 @@ "Спасибо!" : { }, - "Тёмная тема" : { + "Темы" : { }, "Уведомления" : { diff --git a/yobble/Services/ThemeManager.swift b/yobble/Services/ThemeManager.swift index 1152117..4f0ac8d 100644 --- a/yobble/Services/ThemeManager.swift +++ b/yobble/Services/ThemeManager.swift @@ -4,7 +4,8 @@ import SwiftUI enum Theme: String, CaseIterable { case system = "System" case light = "Light" - case dark = "Dark" + case oledDark = "Oled" +// case dark = "Dark" // TODO var colorScheme: ColorScheme? { switch self { @@ -12,7 +13,7 @@ enum Theme: String, CaseIterable { return nil case .light: return .light - case .dark: + case .oledDark: return .dark } } @@ -42,10 +43,10 @@ class ThemeManager: ObservableObject { switch theme { case .system: // If system is active, toggle to the opposite of the current system theme - newTheme = currentSystemScheme == .dark ? .light : .dark + newTheme = currentSystemScheme == .dark ? .light : .oledDark case .light: - newTheme = .dark - case .dark: + newTheme = .oledDark + case .oledDark: newTheme = .light } setTheme(newTheme) diff --git a/yobble/Views/Login/LoginView.swift b/yobble/Views/Login/LoginView.swift index 616fb8d..6152854 100644 --- a/yobble/Views/Login/LoginView.swift +++ b/yobble/Views/Login/LoginView.swift @@ -163,7 +163,7 @@ struct LoginView: View { return colorScheme == .dark ? "moon.fill" : "sun.max.fill" case .light: return "sun.max.fill" - case .dark: + case .oledDark: return "moon.fill" } } diff --git a/yobble/Views/Tab/Settings/SettingsView.swift b/yobble/Views/Tab/Settings/SettingsView.swift index 681eaf5..cdab14e 100644 --- a/yobble/Views/Tab/Settings/SettingsView.swift +++ b/yobble/Views/Tab/Settings/SettingsView.swift @@ -2,7 +2,79 @@ 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 { @@ -32,8 +104,18 @@ struct SettingsView: View { Label("Язык", systemImage: "globe") } - Toggle(isOn: $isDarkMode) { - Label("Тёмная тема", systemImage: "moon.fill") + 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("Заглушка: Хранилище данных")) { @@ -95,4 +177,37 @@ struct SettingsView: View { 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 + } + } diff --git a/yobble/Views/Tab/SideMenuView.swift b/yobble/Views/Tab/SideMenuView.swift index 57e9e5b..07c8a40 100644 --- a/yobble/Views/Tab/SideMenuView.swift +++ b/yobble/Views/Tab/SideMenuView.swift @@ -93,7 +93,7 @@ struct SideMenuView: View { effectiveScheme = colorScheme case .light: effectiveScheme = .light - case .dark: + case .oledDark: effectiveScheme = .dark }