import SwiftUI struct TopBarView: View { var title: String // Состояния для ProfileTab @Binding var selectedAccount: String // @Binding var sheetType: ProfileTab.SheetType? var accounts: [String] // var viewModel: LoginViewModel @ObservedObject var viewModel: LoginViewModel // Привязка для управления боковым меню @Binding var isSideMenuPresented: Bool @Binding var chatSearchRevealProgress: CGFloat @State private var searchText: String = "" var isHomeTab: Bool { return title == "Home" } var isChatsTab: Bool { return title == "Chats" } var isProfileTab: Bool { return title == "Profile" } var body: some View { VStack(spacing: 0) { HStack { // Кнопка "Гамбургер" для открытия меню Button(action: { withAnimation { isSideMenuPresented.toggle() } }) { Image(systemName: "line.horizontal.3") .imageScale(.large) .foregroundColor(.primary) } // Spacer() if isHomeTab{ Text("Yobble") .font(.largeTitle) .fontWeight(.bold) Spacer() } else if isProfileTab { Spacer() Button(action: { }) { HStack(spacing: 4) { Text("@\(viewModel.username)") .font(.headline) .foregroundColor(.primary) Image(systemName: "chevron.down") .font(.subheadline) .foregroundColor(.gray) } } Spacer() } else { Text(title) .font(.largeTitle) .fontWeight(.bold) Spacer() } if isHomeTab{ HStack(spacing: 20) { // Кнопка поиска Button(action: { // пока ничего не делаем }) { Image(systemName: "magnifyingglass") .imageScale(.large) .foregroundColor(.primary) } // Кнопка уведомлений Button(action: { // пока ничего не делаем }) { Image(systemName: "bell") .imageScale(.large) .foregroundColor(.primary) } } } else if isChatsTab { Button(action: { NotificationCenter.default.post(name: .debugRefreshChats, object: nil) }) { Text(NSLocalizedString("DEBUG UPDATE", comment: "")) .foregroundColor(.primary) } } else if isProfileTab { NavigationLink(destination: SettingsView(viewModel: viewModel)) { Image(systemName: "wrench") .imageScale(.large) .foregroundColor(.primary) } } } .padding() .frame(height: 50) // Стандартная высота для нав. бара if isChatsTab { revealableSearchBar } Divider() } .background(Color(UIColor.systemBackground)) .onChange(of: isChatsTab) { isChats in if !isChats { withAnimation(.spring(response: 0.35, dampingFraction: 0.75)) { chatSearchRevealProgress = 0 } } } } } private extension TopBarView { private var normalizedRevealProgress: CGFloat { guard isChatsTab else { return 0 } return max(0, min(chatSearchRevealProgress, 1)) } private var revealableSearchBar: some View { let progress = normalizedRevealProgress return VStack(spacing: 0) { Spacer(minLength: 0) searchBar .padding(.horizontal) .padding(.bottom, 8) } .frame(height: searchBarRevealHeight) .clipped() .scaleEffect(y: max(progress, 0.0001), anchor: .top) .opacity(progress) .allowsHitTesting(progress > 0.9) .accessibilityHidden(progress < 0.9) } private var searchBarRevealHeight: CGFloat { 56 } var searchBar: some View { HStack(spacing: 8) { Image(systemName: "magnifyingglass") .foregroundColor(.secondary) TextField(NSLocalizedString("Поиск", comment: ""), text: $searchText) .textFieldStyle(.plain) .textInputAutocapitalization(.never) .autocorrectionDisabled() if !searchText.isEmpty { Button(action: { searchText = "" }) { Image(systemName: "xmark.circle.fill") .foregroundColor(.secondary) } .buttonStyle(.plain) } } .padding(.horizontal, 12) .padding(.vertical, 6) .frame(minHeight: 36) .background( RoundedRectangle(cornerRadius: 12, style: .continuous) .fill(Color(UIColor.secondarySystemBackground)) ) } } struct TopBarView_Previews: PreviewProvider { struct Wrapper: View { @State private var selectedAccount = "@user" @State private var isSideMenuPresented = false @State private var revealProgress: CGFloat = 1 @StateObject private var viewModel = LoginViewModel() var body: some View { TopBarView( title: "Chats", selectedAccount: $selectedAccount, accounts: [selectedAccount], viewModel: viewModel, isSideMenuPresented: $isSideMenuPresented, chatSearchRevealProgress: $revealProgress ) } } static var previews: some View { Wrapper() .environmentObject(ThemeManager()) } }