add switch theme
This commit is contained in:
parent
dee0e7444d
commit
d502a059b9
@ -577,7 +577,7 @@
|
|||||||
"Спасибо!" : {
|
"Спасибо!" : {
|
||||||
|
|
||||||
},
|
},
|
||||||
"Тёмная тема" : {
|
"Темы" : {
|
||||||
|
|
||||||
},
|
},
|
||||||
"Уведомления" : {
|
"Уведомления" : {
|
||||||
|
|||||||
@ -4,7 +4,8 @@ import SwiftUI
|
|||||||
enum Theme: String, CaseIterable {
|
enum Theme: String, CaseIterable {
|
||||||
case system = "System"
|
case system = "System"
|
||||||
case light = "Light"
|
case light = "Light"
|
||||||
case dark = "Dark"
|
case oledDark = "Oled"
|
||||||
|
// case dark = "Dark" // TODO
|
||||||
|
|
||||||
var colorScheme: ColorScheme? {
|
var colorScheme: ColorScheme? {
|
||||||
switch self {
|
switch self {
|
||||||
@ -12,7 +13,7 @@ enum Theme: String, CaseIterable {
|
|||||||
return nil
|
return nil
|
||||||
case .light:
|
case .light:
|
||||||
return .light
|
return .light
|
||||||
case .dark:
|
case .oledDark:
|
||||||
return .dark
|
return .dark
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,10 +43,10 @@ class ThemeManager: ObservableObject {
|
|||||||
switch theme {
|
switch theme {
|
||||||
case .system:
|
case .system:
|
||||||
// If system is active, toggle to the opposite of the current system theme
|
// 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:
|
case .light:
|
||||||
newTheme = .dark
|
newTheme = .oledDark
|
||||||
case .dark:
|
case .oledDark:
|
||||||
newTheme = .light
|
newTheme = .light
|
||||||
}
|
}
|
||||||
setTheme(newTheme)
|
setTheme(newTheme)
|
||||||
|
|||||||
@ -163,7 +163,7 @@ struct LoginView: View {
|
|||||||
return colorScheme == .dark ? "moon.fill" : "sun.max.fill"
|
return colorScheme == .dark ? "moon.fill" : "sun.max.fill"
|
||||||
case .light:
|
case .light:
|
||||||
return "sun.max.fill"
|
return "sun.max.fill"
|
||||||
case .dark:
|
case .oledDark:
|
||||||
return "moon.fill"
|
return "moon.fill"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,79 @@ import SwiftUI
|
|||||||
|
|
||||||
struct SettingsView: View {
|
struct SettingsView: View {
|
||||||
@ObservedObject var viewModel: LoginViewModel
|
@ObservedObject var viewModel: LoginViewModel
|
||||||
|
@EnvironmentObject private var themeManager: ThemeManager
|
||||||
@AppStorage("isDarkMode") private var isDarkMode: Bool = true
|
@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 {
|
var body: some View {
|
||||||
Form {
|
Form {
|
||||||
@ -32,8 +104,18 @@ struct SettingsView: View {
|
|||||||
Label("Язык", systemImage: "globe")
|
Label("Язык", systemImage: "globe")
|
||||||
}
|
}
|
||||||
|
|
||||||
Toggle(isOn: $isDarkMode) {
|
DisclosureGroup(isExpanded: $isThemeExpanded) {
|
||||||
Label("Тёмная тема", systemImage: "moon.fill")
|
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("Заглушка: Хранилище данных")) {
|
NavigationLink(destination: Text("Заглушка: Хранилище данных")) {
|
||||||
@ -95,4 +177,37 @@ struct SettingsView: View {
|
|||||||
UIApplication.shared.open(url)
|
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
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,7 +93,7 @@ struct SideMenuView: View {
|
|||||||
effectiveScheme = colorScheme
|
effectiveScheme = colorScheme
|
||||||
case .light:
|
case .light:
|
||||||
effectiveScheme = .light
|
effectiveScheme = .light
|
||||||
case .dark:
|
case .oledDark:
|
||||||
effectiveScheme = .dark
|
effectiveScheme = .dark
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user