fix theme

This commit is contained in:
cheykrym 2025-10-07 00:28:48 +03:00
parent d502a059b9
commit 8cc44b06cf
7 changed files with 209 additions and 97 deletions

View File

@ -173,9 +173,6 @@
},
"Заглушка: Обратная связь" : {
},
"Заглушка: Сменить пароль" : {
},
"Заглушка: Хранилище данных" : {
@ -354,9 +351,6 @@
}
}
}
},
"Мой профиль" : {
},
"Мы планируем заменить вкладку. Поделитесь, что бы вы хотели видеть здесь чаще всего." : {
@ -431,6 +425,9 @@
},
"Нет сообщений" : {
},
"Новый пароль" : {
"comment" : "Новый пароль"
},
"О приложении" : {
@ -523,9 +520,6 @@
},
"Произошла ошибка." : {
},
"Профиль" : {
},
"Публичная информация" : {
@ -576,6 +570,9 @@
},
"Спасибо!" : {
},
"Старый пароль" : {
"comment" : "Старый пароль"
},
"Темы" : {

View File

@ -4,7 +4,7 @@ import SwiftUI
enum Theme: String, CaseIterable {
case system = "System"
case light = "Light"
case oledDark = "Oled"
case oledDark = "Oleg"
// case dark = "Dark" // TODO
var colorScheme: ColorScheme? {

View File

@ -0,0 +1,74 @@
import Foundation
enum ThemeOption: String, CaseIterable, Identifiable {
case system
case oledDark
case lightTest
case dark
case custom
var id: String { rawValue }
var title: String {
switch self {
case .system:
return "Системная"
case .oledDark:
return "OLEG тёмный"
case .dark:
return "Тёмная"
case .lightTest:
return "Светлая"
case .custom:
return "Кастомная"
}
}
var note: String? {
switch self {
case .lightTest:
return "Тестовая версия"
case .dark, .custom:
return "Недоступна"
default:
return nil
}
}
var isEnabled: Bool {
switch self {
case .dark, .custom:
return false
default:
return true
}
}
var mappedTheme: Theme? {
switch self {
case .system:
return .system
case .oledDark:
return .oledDark
case .lightTest:
return .light
case .dark, .custom:
return nil
}
}
static var ordered: [ThemeOption] {
[.system, .oledDark, .lightTest, .dark, .custom]
}
static func option(for theme: Theme) -> ThemeOption {
switch theme {
case .system:
return .system
case .light:
return .lightTest
case .oledDark:
return .oledDark
}
}
}

View File

@ -11,6 +11,7 @@ struct LoginView: View {
@ObservedObject var viewModel: LoginViewModel
@EnvironmentObject private var themeManager: ThemeManager
@Environment(\.colorScheme) private var colorScheme
private let themeOptions = ThemeOption.ordered
@State private var isShowingRegistration = false
@FocusState private var focusedField: Field?
@ -46,7 +47,15 @@ struct LoginView: View {
.padding()
}
Spacer()
Button(action: toggleTheme) {
Menu {
ForEach(themeOptions) { option in
Button(action: { selectTheme(option) }) {
themeMenuContent(for: option)
.opacity(option.isEnabled ? 1.0 : 0.5)
}
.disabled(!option.isEnabled)
}
} label: {
Image(systemName: themeIconName)
.padding()
}
@ -152,11 +161,6 @@ struct LoginView: View {
}
}
}
private var themeIconName: String {
switch themeManager.theme {
case .system:
@ -168,15 +172,37 @@ struct LoginView: View {
}
}
private func toggleTheme() {
themeManager.toggleTheme(from: colorScheme)
}
private func openLanguageSettings() {
guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
UIApplication.shared.open(url)
}
private var selectedThemeOption: ThemeOption {
ThemeOption.option(for: themeManager.theme)
}
private func themeMenuContent(for option: ThemeOption) -> some View {
let isSelected = option == selectedThemeOption
return HStack(spacing: 8) {
Image(systemName: isSelected ? "checkmark.circle.fill" : "circle")
.foregroundColor(isSelected ? .accentColor : .secondary)
VStack(alignment: .leading, spacing: 2) {
Text(option.title)
if let note = option.note {
Text(note)
.font(.caption)
.foregroundColor(.secondary)
}
}
}
}
private func selectTheme(_ option: ThemeOption) {
guard let mappedTheme = option.mappedTheme else { return }
themeManager.setTheme(mappedTheme)
}
}
struct LoginView_Previews: PreviewProvider {

View File

@ -101,8 +101,8 @@ struct RegistrationView: View {
.cornerRadius(8)
.autocapitalization(.none)
.onChange(of: password) { newValue in
if newValue.count > 32 {
password = String(newValue.prefix(32))
if newValue.count > 128 {
password = String(newValue.prefix(128))
}
}

View File

@ -0,0 +1,80 @@
import SwiftUI
struct ChangePasswordView: View {
@State private var oldPassword = ""
@State private var newPassword = ""
@State private var confirmPassword = ""
private var isOldPasswordValid: Bool {
return oldPassword.count >= 8 && oldPassword.count <= 128
}
private var isOldPasswordSame: Bool {
return oldPassword == newPassword
}
private var isNewPasswordValid: Bool {
return newPassword.count >= 8 && newPassword.count <= 128
}
private var isPasswordConfirmValid: Bool {
return newPassword == confirmPassword
}
var body: some View {
Form {
Section {
HStack {
SecureField(NSLocalizedString("Старый пароль", comment: "Старый пароль"), text: $oldPassword)
.autocapitalization(.none)
if !oldPassword.isEmpty {
Image(systemName: isOldPasswordValid ? "checkmark.circle" : "xmark.circle")
.foregroundColor(isOldPasswordValid ? .green : .red)
}
}
HStack {
SecureField(NSLocalizedString("Новый пароль", comment: "Новый пароль"), text: $newPassword)
.autocapitalization(.none)
if !newPassword.isEmpty {
let isAllValid = isNewPasswordValid && !isOldPasswordSame
Image(systemName: isAllValid ? "checkmark.circle" : "xmark.circle")
.foregroundColor(isAllValid ? .green : .red)
}
}
HStack {
SecureField(NSLocalizedString("Подтверждение пароля", comment: "Подтверждение пароля"), text: $confirmPassword)
.autocapitalization(.none)
if !confirmPassword.isEmpty {
Image(systemName: isPasswordConfirmValid ? "checkmark.circle" : "xmark.circle")
.foregroundColor(isPasswordConfirmValid ? .green : .red)
}
}
}
var isButtonEnabled: Bool {
isPasswordConfirmValid && !isOldPasswordSame && isNewPasswordValid && isOldPasswordValid
}
Button(action: {
// Действие для сохранения профиля
print("oldPassword: \(oldPassword)")
print("newPassword: \(newPassword)")
print("confirmPassword: \(confirmPassword)")
}) {
Text(NSLocalizedString("Применить", comment: ""))
.background(isButtonEnabled ? Color.blue : Color.gray)
}
.disabled(!isButtonEnabled)
}
.navigationTitle(NSLocalizedString("Изменение пароля", comment: ""))
}
}

View File

@ -5,89 +5,24 @@ struct SettingsView: View {
@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 let themeOptions = ThemeOption.ordered
private var selectedThemeOption: ThemeOption {
switch themeManager.theme {
case .system:
return .system
case .light:
return .lightTest
case .oledDark:
return .oledDark
}
ThemeOption.option(for: themeManager.theme)
}
var body: some View {
Form {
// MARK: - Профиль
Section(header: Text("Профиль")) {
NavigationLink(destination: EditProfileView()) {
Label("Мой профиль", systemImage: "person.crop.circle")
}
}
// // MARK: - Профиль
// Section(header: Text("Профиль")) {
// NavigationLink(destination: EditProfileView()) {
// Label("Мой профиль", systemImage: "person.crop.circle")
// }
// }
// MARK: - Безопасность
Section(header: Text("Безопасность")) {
NavigationLink(destination: Text("Заглушка: Сменить пароль")) {
NavigationLink(destination: ChangePasswordView()) {
Label("Сменить пароль", systemImage: "key")
}
NavigationLink(destination: Text("Заглушка: Двухфакторная аутентификация")) {