Compare commits

..

No commits in common. "359b51627228b1b84f4102c0c69da771bc4d2285" and "6583ce38bb2bbdb7babbc036103786ab0eae601b" have entirely different histories.

3 changed files with 10 additions and 116 deletions

View File

@ -12,7 +12,6 @@ struct TopBarView: View {
// Привязка для управления боковым меню // Привязка для управления боковым меню
@Binding var isSideMenuPresented: Bool @Binding var isSideMenuPresented: Bool
@Binding var chatSearchRevealProgress: CGFloat
@State private var searchText: String = "" @State private var searchText: String = ""
@ -107,49 +106,18 @@ struct TopBarView: View {
.frame(height: 50) // Стандартная высота для нав. бара .frame(height: 50) // Стандартная высота для нав. бара
if isChatsTab { if isChatsTab {
revealableSearchBar searchBar
.padding(.horizontal)
.padding(.bottom, 8)
} }
Divider() Divider()
} }
.background(Color(UIColor.systemBackground)) .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 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) {
searchBar
.padding(.horizontal)
.padding(.bottom, searchBarBottomSpacing)
.opacity(progress)
}
.frame(height: searchBarRevealHeight * progress, alignment: .top)
.clipped()
.allowsHitTesting(progress > 0.9)
.accessibilityHidden(progress < 0.9)
}
private var searchBarRevealHeight: CGFloat { searchBarBaseHeight + searchBarBottomSpacing }
// 36 min height + 6 * 2 vertical padding inside searchBar
private var searchBarBaseHeight: CGFloat { 48 }
private var searchBarBottomSpacing: CGFloat { 0 }
var searchBar: some View { var searchBar: some View {
HStack(spacing: 8) { HStack(spacing: 8) {
Image(systemName: "magnifyingglass") Image(systemName: "magnifyingglass")
@ -177,26 +145,7 @@ private extension TopBarView {
} }
struct TopBarView_Previews: PreviewProvider { 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 { static var previews: some View {
Wrapper() /*@START_MENU_TOKEN@*/Text("Hello, World!")/*@END_MENU_TOKEN@*/
.environmentObject(ThemeManager())
} }
} }

View File

@ -8,20 +8,10 @@
import SwiftUI import SwiftUI
struct ChatsTab: View { struct ChatsTab: View {
var currentUserId: String? var currentUserId: String? = nil
@Binding var searchRevealProgress: CGFloat
@StateObject private var viewModel = PrivateChatsViewModel() @StateObject private var viewModel = PrivateChatsViewModel()
@State private var selectedChatId: String? @State private var selectedChatId: String?
@State private var searchText: String = "" @State private var searchText: String = ""
@State private var searchDragStartProgress: CGFloat = 0
@State private var isSearchGestureActive: Bool = false
private let searchRevealDistance: CGFloat = 90
init(currentUserId: String? = nil, searchRevealProgress: Binding<CGFloat>) {
self.currentUserId = currentUserId
self._searchRevealProgress = searchRevealProgress
}
var body: some View { var body: some View {
content content
@ -125,7 +115,6 @@ struct ChatsTab: View {
} }
} }
.listStyle(.plain) .listStyle(.plain)
.simultaneousGesture(searchBarGesture)
// .safeAreaInset(edge: .top) { // .safeAreaInset(edge: .top) {
// VStack(spacing: 0) { // VStack(spacing: 0) {
// searchBar // searchBar
@ -163,36 +152,6 @@ struct ChatsTab: View {
) )
} }
private var searchBarGesture: some Gesture {
DragGesture(minimumDistance: 10, coordinateSpace: .local)
.onChanged { value in
let verticalTranslation = value.translation.height
let horizontalTranslation = value.translation.width
if !isSearchGestureActive {
guard abs(verticalTranslation) > abs(horizontalTranslation) else { return }
if searchRevealProgress <= 0.001 && verticalTranslation < 0 { return }
isSearchGestureActive = true
searchDragStartProgress = searchRevealProgress
}
guard isSearchGestureActive else { return }
let delta = verticalTranslation / searchRevealDistance
let newProgress = searchDragStartProgress + delta
searchRevealProgress = max(0, min(1, newProgress))
}
.onEnded { _ in
guard isSearchGestureActive else { return }
isSearchGestureActive = false
let target: CGFloat = searchRevealProgress > 0.5 ? 1 : 0
withAnimation(.spring(response: 0.35, dampingFraction: 0.75)) {
searchRevealProgress = target
}
}
}
private var isSearching: Bool { private var isSearching: Bool {
!searchText.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty !searchText.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
} }
@ -593,17 +552,9 @@ private struct ChatRowView: View {
} }
struct ChatsTab_Previews: PreviewProvider { struct ChatsTab_Previews: PreviewProvider {
struct Wrapper: View {
@State private var progress: CGFloat = 1
var body: some View {
ChatsTab(searchRevealProgress: $progress)
.environmentObject(ThemeManager())
}
}
static var previews: some View { static var previews: some View {
Wrapper() ChatsTab()
.environmentObject(ThemeManager())
} }
} }

View File

@ -13,7 +13,6 @@ struct MainView: View {
// Состояния для бокового меню // Состояния для бокового меню
@State private var isSideMenuPresented = false @State private var isSideMenuPresented = false
@State private var menuOffset: CGFloat = 0 @State private var menuOffset: CGFloat = 0
@State private var chatSearchRevealProgress: CGFloat = 0
private var tabTitle: String { private var tabTitle: String {
switch selectedTab { switch selectedTab {
@ -39,8 +38,7 @@ struct MainView: View {
selectedAccount: $selectedAccount, selectedAccount: $selectedAccount,
accounts: accounts, accounts: accounts,
viewModel: viewModel, viewModel: viewModel,
isSideMenuPresented: $isSideMenuPresented, isSideMenuPresented: $isSideMenuPresented
chatSearchRevealProgress: $chatSearchRevealProgress
) )
ZStack { ZStack {
@ -50,12 +48,8 @@ struct MainView: View {
FeedbackTab() FeedbackTab()
.opacity(selectedTab == 1 ? 1 : 0) .opacity(selectedTab == 1 ? 1 : 0)
ChatsTab( ChatsTab(currentUserId: viewModel.userId.isEmpty ? nil : viewModel.userId)
currentUserId: viewModel.userId.isEmpty ? nil : viewModel.userId,
searchRevealProgress: $chatSearchRevealProgress
)
.opacity(selectedTab == 2 ? 1 : 0) .opacity(selectedTab == 2 ? 1 : 0)
.allowsHitTesting(selectedTab == 2)
ProfileTab() ProfileTab()
.opacity(selectedTab == 3 ? 1 : 0) .opacity(selectedTab == 3 ? 1 : 0)