136 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
import SwiftUI
 | 
						||
 | 
						||
struct MainView: View {
 | 
						||
    @ObservedObject var viewModel: LoginViewModel
 | 
						||
    @State private var selectedTab: Int = 0
 | 
						||
    @StateObject private var newHomeTabViewModel = NewHomeTabViewModel()
 | 
						||
    
 | 
						||
    // Состояния для TopBarView
 | 
						||
    @State private var selectedAccount = "@user1"
 | 
						||
    @State private var accounts = ["@user1", "@user2", "@user3"]
 | 
						||
    @State private var sheetType: ProfileTab.SheetType? = nil
 | 
						||
    
 | 
						||
    // Состояния для бокового меню
 | 
						||
    @State private var isSideMenuPresented = false
 | 
						||
    @State private var menuOffset: CGFloat = 0
 | 
						||
    
 | 
						||
    private var tabTitle: String {
 | 
						||
        switch selectedTab {
 | 
						||
        case 0: return "Home"
 | 
						||
        case 1: return "Search"
 | 
						||
        case 2: return "Chats"
 | 
						||
        case 3: return "Profile"
 | 
						||
        default: return "Home"
 | 
						||
        }
 | 
						||
    }
 | 
						||
    
 | 
						||
    private var menuWidth: CGFloat {
 | 
						||
        UIScreen.main.bounds.width * 0.8
 | 
						||
    }
 | 
						||
 | 
						||
    var body: some View {
 | 
						||
        NavigationView {
 | 
						||
            ZStack(alignment: .leading) { // Выравниваем ZStack по левому краю
 | 
						||
                // Основной контент
 | 
						||
                VStack(spacing: 0) {
 | 
						||
                    TopBarView(
 | 
						||
                        title: tabTitle,
 | 
						||
                        selectedAccount: $selectedAccount,
 | 
						||
                        sheetType: $sheetType,
 | 
						||
                        accounts: accounts,
 | 
						||
                        viewModel: viewModel,
 | 
						||
                        isSideMenuPresented: $isSideMenuPresented
 | 
						||
                    )
 | 
						||
                    
 | 
						||
                    ZStack {
 | 
						||
                        NewHomeTab(viewModel: newHomeTabViewModel)
 | 
						||
                            .opacity(selectedTab == 0 ? 1 : 0)
 | 
						||
                        
 | 
						||
                        SearchTab()
 | 
						||
                            .opacity(selectedTab == 1 ? 1 : 0)
 | 
						||
                        
 | 
						||
                        ChatsTab()
 | 
						||
                            .opacity(selectedTab == 2 ? 1 : 0)
 | 
						||
                        
 | 
						||
                        ProfileTab(viewModel: viewModel, sheetType: $sheetType, selectedAccount: $selectedAccount, accounts: $accounts, onScroll: { _ in })
 | 
						||
                            .opacity(selectedTab == 3 ? 1 : 0)
 | 
						||
                    }
 | 
						||
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
 | 
						||
                    
 | 
						||
                    CustomTabBar(selectedTab: $selectedTab) {
 | 
						||
                        print("Create button tapped")
 | 
						||
                    }
 | 
						||
                }
 | 
						||
                .frame(maxWidth: .infinity, maxHeight: .infinity) // Убедимся, что основной контент занимает все пространство
 | 
						||
                .ignoresSafeArea(edges: .bottom)
 | 
						||
                .navigationBarHidden(true)
 | 
						||
                .sheet(item: $sheetType) { type in
 | 
						||
                    // ... sheet presentation logic
 | 
						||
                }
 | 
						||
                
 | 
						||
                // Затемнение и закрытие по тапу
 | 
						||
                if isSideMenuPresented {
 | 
						||
                    Color.black.opacity(0.4 * Double(((menuWidth + menuOffset) / menuWidth)))
 | 
						||
                        .ignoresSafeArea()
 | 
						||
                        .onTapGesture {
 | 
						||
                            withAnimation(.easeInOut) {
 | 
						||
                                isSideMenuPresented = false
 | 
						||
                            }
 | 
						||
                        }
 | 
						||
                }
 | 
						||
 | 
						||
                // Боковое меню
 | 
						||
                SideMenuView(isPresented: $isSideMenuPresented)
 | 
						||
                    .frame(width: menuWidth)
 | 
						||
                    .offset(x: -menuWidth + menuOffset) // Новая логика смещения
 | 
						||
                    .ignoresSafeArea(edges: .vertical)
 | 
						||
            }
 | 
						||
            .gesture(
 | 
						||
                DragGesture()
 | 
						||
                    .onChanged { gesture in
 | 
						||
                        if !isSideMenuPresented && gesture.startLocation.x > 60 { return }
 | 
						||
 | 
						||
                        let translation = gesture.translation.width
 | 
						||
                        
 | 
						||
                        if isSideMenuPresented {
 | 
						||
                            // При закрытии двигаем от 0 до -menuWidth
 | 
						||
                            self.menuOffset = max(0, menuWidth + translation)
 | 
						||
                        } else {
 | 
						||
                            // При открытии двигаем от 0 до menuWidth
 | 
						||
                            self.menuOffset = min(menuWidth, translation)
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
                    .onEnded { gesture in
 | 
						||
                        if !isSideMenuPresented && gesture.startLocation.x > 60 { return }
 | 
						||
                        
 | 
						||
                        let threshold = menuWidth * 0.4
 | 
						||
                        
 | 
						||
                        withAnimation(.easeInOut) {
 | 
						||
                            if self.menuOffset > threshold {
 | 
						||
                                isSideMenuPresented = true
 | 
						||
                            } else {
 | 
						||
                                isSideMenuPresented = false
 | 
						||
                            }
 | 
						||
                            // Сбрасываем menuOffset, так как isSideMenuPresented теперь главный источник истины
 | 
						||
                            self.menuOffset = isSideMenuPresented ? menuWidth : 0
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
            )
 | 
						||
        }
 | 
						||
        .navigationViewStyle(StackNavigationViewStyle())
 | 
						||
        .onChange(of: isSideMenuPresented) { presented in
 | 
						||
            // Плавная анимация при нажатии на кнопку, а не только при жесте
 | 
						||
            withAnimation(.easeInOut) {
 | 
						||
                menuOffset = presented ? menuWidth : 0
 | 
						||
            }
 | 
						||
        }
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
struct MainView_Previews: PreviewProvider {
 | 
						||
    static var previews: some View {
 | 
						||
        let mockViewModel = LoginViewModel()
 | 
						||
        MainView(viewModel: mockViewModel)
 | 
						||
    }
 | 
						||
}
 |