burger menu
This commit is contained in:
		
							parent
							
								
									5d74af5597
								
							
						
					
					
						commit
						102826ac8a
					
				@ -7,7 +7,8 @@ struct TopBarView: View {
 | 
			
		||||
    @Binding var selectedAccount: String
 | 
			
		||||
//    @Binding var sheetType: ProfileTab.SheetType?
 | 
			
		||||
    var accounts: [String]
 | 
			
		||||
    var viewModel: LoginViewModel
 | 
			
		||||
//    var viewModel: LoginViewModel
 | 
			
		||||
    @ObservedObject var viewModel: LoginViewModel
 | 
			
		||||
    
 | 
			
		||||
    // Привязка для управления боковым меню
 | 
			
		||||
    @Binding var isSideMenuPresented: Bool
 | 
			
		||||
@ -45,7 +46,7 @@ struct TopBarView: View {
 | 
			
		||||
                    Spacer()
 | 
			
		||||
                    Button(action: { }) {
 | 
			
		||||
                        HStack(spacing: 4) {
 | 
			
		||||
                            Text(selectedAccount)
 | 
			
		||||
                            Text("@\(viewModel.username)")
 | 
			
		||||
                                .font(.headline)
 | 
			
		||||
                                .foregroundColor(.primary)
 | 
			
		||||
                            Image(systemName: "chevron.down")
 | 
			
		||||
 | 
			
		||||
@ -104,7 +104,6 @@ class AuthService {
 | 
			
		||||
                    // Сохраняем токены в Keychain
 | 
			
		||||
                    KeychainService.shared.save(loginResponse.access_token, forKey: "access_token", service: username)
 | 
			
		||||
                    KeychainService.shared.save(loginResponse.refresh_token, forKey: "refresh_token", service: username)
 | 
			
		||||
                    print("loginResponse.user_id \(loginResponse.user_id)")
 | 
			
		||||
                    KeychainService.shared.save(loginResponse.user_id, forKey: "userId", service: username)
 | 
			
		||||
                    UserDefaults.standard.set(username, forKey: "currentUser")
 | 
			
		||||
                    
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "sourceLanguage" : "en",
 | 
			
		||||
  "strings" : {
 | 
			
		||||
    "@%@" : {
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    "@yourusername" : {
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@ class LoginViewModel: ObservableObject {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    init() {
 | 
			
		||||
        loadStoredUser()
 | 
			
		||||
//        loadStoredUser()
 | 
			
		||||
 | 
			
		||||
        // Запускаем автологин
 | 
			
		||||
        autoLogin()
 | 
			
		||||
@ -113,6 +113,6 @@ class LoginViewModel: ObservableObject {
 | 
			
		||||
        username = defaults.string(forKey: DefaultsKeys.currentUser) ?? ""
 | 
			
		||||
        userId = KeychainService.shared.get(forKey: DefaultsKeys.userId, service: username) ?? ""
 | 
			
		||||
        
 | 
			
		||||
        print("username: \(username) | userId: \(userId)")
 | 
			
		||||
        if AppConfig.DEBUG{ print("username: \(username) | userId: \(userId)")}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,12 @@ struct LoginView: View {
 | 
			
		||||
    @Environment(\.colorScheme) private var colorScheme
 | 
			
		||||
    
 | 
			
		||||
    @State private var isShowingRegistration = false
 | 
			
		||||
    @FocusState private var focusedField: Field?
 | 
			
		||||
 | 
			
		||||
    private enum Field: Hashable {
 | 
			
		||||
        case username
 | 
			
		||||
        case password
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private var isUsernameValid: Bool {
 | 
			
		||||
        let pattern = "^[A-Za-z0-9_]{3,32}$"
 | 
			
		||||
@ -29,7 +35,7 @@ struct LoginView: View {
 | 
			
		||||
            Color.clear // чтобы поймать тап
 | 
			
		||||
                .contentShape(Rectangle())
 | 
			
		||||
                .onTapGesture {
 | 
			
		||||
                    hideKeyboard()
 | 
			
		||||
                    focusedField = nil
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            VStack {
 | 
			
		||||
@ -46,8 +52,8 @@ struct LoginView: View {
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                .onTapGesture {
 | 
			
		||||
                hideKeyboard()
 | 
			
		||||
            }
 | 
			
		||||
                    focusedField = nil
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Spacer()
 | 
			
		||||
 | 
			
		||||
@ -57,6 +63,7 @@ struct LoginView: View {
 | 
			
		||||
                    .cornerRadius(8)
 | 
			
		||||
                    .autocapitalization(.none)
 | 
			
		||||
                    .disableAutocorrection(true)
 | 
			
		||||
                    .focused($focusedField, equals: .username)
 | 
			
		||||
                    .onChange(of: viewModel.username) { newValue in
 | 
			
		||||
                        if newValue.count > 32 {
 | 
			
		||||
                            viewModel.username = String(newValue.prefix(32))
 | 
			
		||||
@ -76,6 +83,7 @@ struct LoginView: View {
 | 
			
		||||
                    .background(Color(.secondarySystemBackground))
 | 
			
		||||
                    .cornerRadius(8)
 | 
			
		||||
                    .autocapitalization(.none)
 | 
			
		||||
                    .focused($focusedField, equals: .password)
 | 
			
		||||
                    .onChange(of: viewModel.password) { newValue in
 | 
			
		||||
                        if newValue.count > 32 {
 | 
			
		||||
                            viewModel.password = String(newValue.prefix(32))
 | 
			
		||||
@ -140,8 +148,8 @@ struct LoginView: View {
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            .onTapGesture {
 | 
			
		||||
            hideKeyboard()
 | 
			
		||||
        }
 | 
			
		||||
                focusedField = nil
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
@ -169,10 +177,6 @@ struct LoginView: View {
 | 
			
		||||
        UIApplication.shared.open(url)
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private func hideKeyboard() {
 | 
			
		||||
        UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct LoginView_Previews: PreviewProvider {
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,15 @@ struct RegistrationView: View {
 | 
			
		||||
    @State private var showError: Bool = false
 | 
			
		||||
    @State private var errorMessage: String = ""
 | 
			
		||||
 | 
			
		||||
    @FocusState private var focusedField: Field?
 | 
			
		||||
 | 
			
		||||
    private enum Field: Hashable {
 | 
			
		||||
        case username
 | 
			
		||||
        case password
 | 
			
		||||
        case confirmPassword
 | 
			
		||||
        case invite
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private var isUsernameValid: Bool {
 | 
			
		||||
        let pattern = "^[A-Za-z0-9_]{3,32}$"
 | 
			
		||||
        return username.range(of: pattern, options: .regularExpression) != nil
 | 
			
		||||
@ -45,7 +54,7 @@ struct RegistrationView: View {
 | 
			
		||||
                ZStack(alignment: .top) {
 | 
			
		||||
                    Color.clear
 | 
			
		||||
                        .contentShape(Rectangle())
 | 
			
		||||
                        .onTapGesture { hideKeyboard() }
 | 
			
		||||
                        .onTapGesture { focusedField = nil }
 | 
			
		||||
 | 
			
		||||
                    VStack(alignment: .leading, spacing: 16) {
 | 
			
		||||
                        Group {
 | 
			
		||||
@ -53,6 +62,7 @@ struct RegistrationView: View {
 | 
			
		||||
                                TextField(NSLocalizedString("Логин", comment: "Логин"), text: $username)
 | 
			
		||||
                                    .autocapitalization(.none)
 | 
			
		||||
                                    .disableAutocorrection(true)
 | 
			
		||||
                                    .focused($focusedField, equals: .username)
 | 
			
		||||
                                Spacer()
 | 
			
		||||
                                if !username.isEmpty {
 | 
			
		||||
                                    Image(systemName: isUsernameValid ? "checkmark.circle" : "xmark.circle")
 | 
			
		||||
@ -79,6 +89,7 @@ struct RegistrationView: View {
 | 
			
		||||
                            HStack {
 | 
			
		||||
                                SecureField(NSLocalizedString("Пароль", comment: "Пароль"), text: $password)
 | 
			
		||||
                                    .autocapitalization(.none)
 | 
			
		||||
                                    .focused($focusedField, equals: .password)
 | 
			
		||||
                                Spacer()
 | 
			
		||||
                                if !password.isEmpty {
 | 
			
		||||
                                    Image(systemName: isPasswordValid ? "checkmark.circle" : "xmark.circle")
 | 
			
		||||
@ -104,6 +115,7 @@ struct RegistrationView: View {
 | 
			
		||||
                            HStack {
 | 
			
		||||
                                SecureField(NSLocalizedString("Подтверждение пароля", comment: "Подтверждение пароля"), text: $confirmPassword)
 | 
			
		||||
                                    .autocapitalization(.none)
 | 
			
		||||
                                    .focused($focusedField, equals: .confirmPassword)
 | 
			
		||||
                                Spacer()
 | 
			
		||||
                                if !confirmPassword.isEmpty {
 | 
			
		||||
                                    Image(systemName: isConfirmPasswordValid ? "checkmark.circle" : "xmark.circle")
 | 
			
		||||
@ -132,6 +144,7 @@ struct RegistrationView: View {
 | 
			
		||||
                                .cornerRadius(8)
 | 
			
		||||
                                .autocapitalization(.none)
 | 
			
		||||
                                .disableAutocorrection(true)
 | 
			
		||||
                                .focused($focusedField, equals: .invite)
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        Button(action: registerUser) {
 | 
			
		||||
@ -189,14 +202,10 @@ struct RegistrationView: View {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private func dismissSheet() {
 | 
			
		||||
        hideKeyboard()
 | 
			
		||||
        focusedField = nil
 | 
			
		||||
        isPresented = false
 | 
			
		||||
        presentationMode.wrappedValue.dismiss()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private func hideKeyboard() {
 | 
			
		||||
        UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -79,7 +79,7 @@ struct MainView: View {
 | 
			
		||||
                    .allowsHitTesting(menuOffset > 0)
 | 
			
		||||
 | 
			
		||||
                // Боковое меню
 | 
			
		||||
                SideMenuView(isPresented: $isSideMenuPresented)
 | 
			
		||||
                SideMenuView(viewModel: viewModel, isPresented: $isSideMenuPresented)
 | 
			
		||||
                    .frame(width: menuWidth)
 | 
			
		||||
                    .offset(x: -menuWidth + menuOffset) // Новая логика смещения
 | 
			
		||||
                    .ignoresSafeArea(edges: .vertical)
 | 
			
		||||
 | 
			
		||||
@ -62,6 +62,7 @@ struct SideMenuFooterButton: View {
 | 
			
		||||
// --- MAIN VIEW ---
 | 
			
		||||
 | 
			
		||||
struct SideMenuView: View {
 | 
			
		||||
    @ObservedObject var viewModel: LoginViewModel
 | 
			
		||||
    @EnvironmentObject var themeManager: ThemeManager
 | 
			
		||||
    @Environment(\.colorScheme) var colorScheme
 | 
			
		||||
    @Binding var isPresented: Bool
 | 
			
		||||
@ -132,10 +133,10 @@ struct SideMenuView: View {
 | 
			
		||||
                    }) {
 | 
			
		||||
                        HStack {
 | 
			
		||||
                            VStack(alignment: .leading) {
 | 
			
		||||
                                Text("Your Name")
 | 
			
		||||
                                Text("@\(viewModel.username)")
 | 
			
		||||
                                    .font(.title3).bold()
 | 
			
		||||
                                Text("@yourusername")
 | 
			
		||||
                                    .font(.footnote)
 | 
			
		||||
//                                Text("@yourusername")
 | 
			
		||||
//                                    .font(.footnote)
 | 
			
		||||
                            }
 | 
			
		||||
                            .foregroundColor(.primary)
 | 
			
		||||
                            
 | 
			
		||||
@ -172,8 +173,9 @@ struct SideMenuView: View {
 | 
			
		||||
                                            }
 | 
			
		||||
                                            
 | 
			
		||||
                                            VStack(alignment: .leading) {
 | 
			
		||||
                                                Text(account.name).font(.footnote).bold() // Smaller text
 | 
			
		||||
                                                Text(account.username).font(.caption2)      // Smaller text
 | 
			
		||||
                                                Text(account.username).font(.footnote).bold() // Smaller text
 | 
			
		||||
//                                                Text(account.name).font(.footnote).bold() // Smaller text
 | 
			
		||||
//                                                Text(account.username).font(.caption2)      // Smaller text
 | 
			
		||||
                                            }
 | 
			
		||||
                                            .foregroundColor(.primary)
 | 
			
		||||
                                        }
 | 
			
		||||
@ -253,7 +255,8 @@ struct SideMenuView: View {
 | 
			
		||||
 | 
			
		||||
struct SideMenuView_Previews: PreviewProvider {
 | 
			
		||||
    static var previews: some View {
 | 
			
		||||
        SideMenuView(isPresented: .constant(true))
 | 
			
		||||
        let mockViewModel = LoginViewModel()
 | 
			
		||||
        SideMenuView(viewModel: mockViewModel, isPresented: .constant(true))
 | 
			
		||||
            .environmentObject(ThemeManager())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user