fix theme
This commit is contained in:
		
							parent
							
								
									d502a059b9
								
							
						
					
					
						commit
						8cc44b06cf
					
				@ -173,9 +173,6 @@
 | 
			
		||||
    },
 | 
			
		||||
    "Заглушка: Обратная связь" : {
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    "Заглушка: Сменить пароль" : {
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    "Заглушка: Хранилище данных" : {
 | 
			
		||||
 | 
			
		||||
@ -354,9 +351,6 @@
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "Мой профиль" : {
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    "Мы планируем заменить вкладку. Поделитесь, что бы вы хотели видеть здесь чаще всего." : {
 | 
			
		||||
 | 
			
		||||
@ -431,6 +425,9 @@
 | 
			
		||||
    },
 | 
			
		||||
    "Нет сообщений" : {
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    "Новый пароль" : {
 | 
			
		||||
      "comment" : "Новый пароль"
 | 
			
		||||
    },
 | 
			
		||||
    "О приложении" : {
 | 
			
		||||
 | 
			
		||||
@ -523,9 +520,6 @@
 | 
			
		||||
    },
 | 
			
		||||
    "Произошла ошибка." : {
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    "Профиль" : {
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    "Публичная информация" : {
 | 
			
		||||
 | 
			
		||||
@ -576,6 +570,9 @@
 | 
			
		||||
    },
 | 
			
		||||
    "Спасибо!" : {
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    "Старый пароль" : {
 | 
			
		||||
      "comment" : "Старый пароль"
 | 
			
		||||
    },
 | 
			
		||||
    "Темы" : {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,9 +4,9 @@ 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? {
 | 
			
		||||
        switch self {
 | 
			
		||||
        case .system:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										74
									
								
								yobble/Services/ThemeOption.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								yobble/Services/ThemeOption.swift
									
									
									
									
									
										Normal 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
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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,14 +172,36 @@ 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)
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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))
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										80
									
								
								yobble/Views/Tab/Settings/ChangePasswordView.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								yobble/Views/Tab/Settings/ChangePasswordView.swift
									
									
									
									
									
										Normal 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: ""))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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("Заглушка: Двухфакторная аутентификация")) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user