add 2 type chat view
This commit is contained in:
		
							parent
							
								
									86924af785
								
							
						
					
					
						commit
						cc9cc3149f
					
				@ -4,6 +4,7 @@ import Combine
 | 
			
		||||
final class IncomingMessageCenter: ObservableObject {
 | 
			
		||||
    @Published private(set) var banner: IncomingMessageBanner?
 | 
			
		||||
    @Published var presentedChat: PrivateChatListItem?
 | 
			
		||||
    @Published var pendingNavigation: ChatNavigationTarget?
 | 
			
		||||
    var currentUserId: String?
 | 
			
		||||
    var activeChatId: String?
 | 
			
		||||
 | 
			
		||||
@ -31,7 +32,14 @@ final class IncomingMessageCenter: ObservableObject {
 | 
			
		||||
    func openCurrentChat() {
 | 
			
		||||
        guard let banner else { return }
 | 
			
		||||
        activeChatId = banner.message.chatId
 | 
			
		||||
        presentedChat = makeChatItem(from: banner.message)
 | 
			
		||||
        let chatItem = makeChatItem(from: banner.message)
 | 
			
		||||
        if AppConfig.PRESENT_CHAT_AS_SHEET {
 | 
			
		||||
            presentedChat = chatItem
 | 
			
		||||
            pendingNavigation = nil
 | 
			
		||||
        } else {
 | 
			
		||||
            pendingNavigation = ChatNavigationTarget(chat: chatItem)
 | 
			
		||||
            presentedChat = nil
 | 
			
		||||
        }
 | 
			
		||||
        dismissBanner()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -44,7 +52,9 @@ final class IncomingMessageCenter: ObservableObject {
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if let presentedChat, presentedChat.chatId == message.chatId {
 | 
			
		||||
        if AppConfig.PRESENT_CHAT_AS_SHEET,
 | 
			
		||||
           let presentedChat,
 | 
			
		||||
           presentedChat.chatId == message.chatId {
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -112,4 +122,9 @@ final class IncomingMessageCenter: ObservableObject {
 | 
			
		||||
        dismissWorkItem = workItem
 | 
			
		||||
        DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: workItem)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    struct ChatNavigationTarget: Identifiable {
 | 
			
		||||
        let id = UUID()
 | 
			
		||||
        let chat: PrivateChatListItem
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -12,6 +12,7 @@ import UIKit
 | 
			
		||||
 | 
			
		||||
struct ChatsTab: View {
 | 
			
		||||
    @ObservedObject private var loginViewModel: LoginViewModel
 | 
			
		||||
    @Binding private var pendingNavigation: IncomingMessageCenter.ChatNavigationTarget?
 | 
			
		||||
    @Binding var searchRevealProgress: CGFloat
 | 
			
		||||
    @Binding var searchText: String
 | 
			
		||||
    private let searchService = SearchService()
 | 
			
		||||
@ -40,10 +41,12 @@ struct ChatsTab: View {
 | 
			
		||||
 | 
			
		||||
    init(
 | 
			
		||||
        loginViewModel: LoginViewModel,
 | 
			
		||||
        pendingNavigation: Binding<IncomingMessageCenter.ChatNavigationTarget?>,
 | 
			
		||||
        searchRevealProgress: Binding<CGFloat>,
 | 
			
		||||
        searchText: Binding<String>
 | 
			
		||||
    ) {
 | 
			
		||||
        self._loginViewModel = ObservedObject(wrappedValue: loginViewModel)
 | 
			
		||||
        self._pendingNavigation = pendingNavigation
 | 
			
		||||
        self._searchRevealProgress = searchRevealProgress
 | 
			
		||||
        self._searchText = searchText
 | 
			
		||||
    }
 | 
			
		||||
@ -97,6 +100,13 @@ struct ChatsTab: View {
 | 
			
		||||
                globalSearchTask?.cancel()
 | 
			
		||||
                globalSearchTask = nil
 | 
			
		||||
            }
 | 
			
		||||
            .onChange(of: pendingNavigation?.id) { _ in
 | 
			
		||||
                guard let target = pendingNavigation else { return }
 | 
			
		||||
                handleNavigationTarget(target.chat)
 | 
			
		||||
                DispatchQueue.main.async {
 | 
			
		||||
                    pendingNavigation = nil
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ViewBuilder
 | 
			
		||||
@ -542,6 +552,30 @@ private extension ChatsTab {
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func handleNavigationTarget(_ chatItem: PrivateChatListItem) {
 | 
			
		||||
        dismissKeyboard()
 | 
			
		||||
        if !searchText.isEmpty {
 | 
			
		||||
            searchText = ""
 | 
			
		||||
        }
 | 
			
		||||
        if searchRevealProgress > 0 {
 | 
			
		||||
            withAnimation(.spring(response: 0.35, dampingFraction: 0.75)) {
 | 
			
		||||
                searchRevealProgress = 0
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let existingChat = viewModel.chats.first(where: { $0.chatId == chatItem.chatId })
 | 
			
		||||
        pendingChatItem = existingChat ?? chatItem
 | 
			
		||||
        selectedChatId = chatItem.chatId
 | 
			
		||||
        isPendingChatActive = true
 | 
			
		||||
 | 
			
		||||
        if existingChat == nil {
 | 
			
		||||
            if loginViewModel.chatLoadingState != .loading {
 | 
			
		||||
                loginViewModel.chatLoadingState = .loading
 | 
			
		||||
            }
 | 
			
		||||
            viewModel.refresh()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func handleSearchQueryChange(_ query: String) {
 | 
			
		||||
        let trimmed = query.trimmingCharacters(in: .whitespacesAndNewlines)
 | 
			
		||||
 | 
			
		||||
@ -1161,10 +1195,12 @@ struct ChatsTab_Previews: PreviewProvider {
 | 
			
		||||
        @State private var progress: CGFloat = 1
 | 
			
		||||
        @State private var searchText: String = ""
 | 
			
		||||
        @StateObject private var loginViewModel = LoginViewModel()
 | 
			
		||||
        @State private var pendingNavigation: IncomingMessageCenter.ChatNavigationTarget?
 | 
			
		||||
 | 
			
		||||
        var body: some View {
 | 
			
		||||
            ChatsTab(
 | 
			
		||||
                loginViewModel: loginViewModel,
 | 
			
		||||
                pendingNavigation: $pendingNavigation,
 | 
			
		||||
                searchRevealProgress: $progress,
 | 
			
		||||
                searchText: $searchText
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@ import SwiftUI
 | 
			
		||||
 | 
			
		||||
struct MainView: View {
 | 
			
		||||
    @ObservedObject var viewModel: LoginViewModel
 | 
			
		||||
    @EnvironmentObject private var messageCenter: IncomingMessageCenter
 | 
			
		||||
    @State private var selectedTab: Int = 0
 | 
			
		||||
//    @StateObject private var newHomeTabViewModel = NewHomeTabViewModel()
 | 
			
		||||
    
 | 
			
		||||
@ -33,6 +34,12 @@ struct MainView: View {
 | 
			
		||||
 | 
			
		||||
    var body: some View {
 | 
			
		||||
        NavigationView {
 | 
			
		||||
            let pendingNavigationBinding: Binding<IncomingMessageCenter.ChatNavigationTarget?> = AppConfig.PRESENT_CHAT_AS_SHEET
 | 
			
		||||
                ? .constant(nil)
 | 
			
		||||
                : Binding(
 | 
			
		||||
                    get: { messageCenter.pendingNavigation },
 | 
			
		||||
                    set: { messageCenter.pendingNavigation = $0 }
 | 
			
		||||
                )
 | 
			
		||||
            ZStack(alignment: .top) {
 | 
			
		||||
                ZStack(alignment: .leading) { // Выравниваем ZStack по левому краю
 | 
			
		||||
                    // Основной контент
 | 
			
		||||
@ -57,6 +64,7 @@ struct MainView: View {
 | 
			
		||||
 | 
			
		||||
                            ChatsTab(
 | 
			
		||||
                                loginViewModel: viewModel,
 | 
			
		||||
                                pendingNavigation: pendingNavigationBinding,
 | 
			
		||||
                                searchRevealProgress: $chatSearchRevealProgress,
 | 
			
		||||
                                searchText: $chatSearchText
 | 
			
		||||
                            )
 | 
			
		||||
@ -137,6 +145,20 @@ struct MainView: View {
 | 
			
		||||
                menuOffset = presented ? menuWidth : 0
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        .onChange(of: messageCenter.pendingNavigation?.id) { _ in
 | 
			
		||||
            guard !AppConfig.PRESENT_CHAT_AS_SHEET,
 | 
			
		||||
                  messageCenter.pendingNavigation != nil else { return }
 | 
			
		||||
            withAnimation(.easeInOut) {
 | 
			
		||||
                selectedTab = 2
 | 
			
		||||
                isSideMenuPresented = false
 | 
			
		||||
                menuOffset = 0
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        .onChange(of: selectedTab) { newValue in
 | 
			
		||||
            if newValue != 3 {
 | 
			
		||||
                isSettingsPresented = false
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -144,6 +166,7 @@ struct MainView_Previews: PreviewProvider {
 | 
			
		||||
    static var previews: some View {
 | 
			
		||||
        let mockViewModel = LoginViewModel()
 | 
			
		||||
        MainView(viewModel: mockViewModel)
 | 
			
		||||
            .environmentObject(IncomingMessageCenter())
 | 
			
		||||
            .environmentObject(ThemeManager())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,8 @@ struct AppConfig {
 | 
			
		||||
    static let APP_VERSION = "0.1"
 | 
			
		||||
 | 
			
		||||
    static let DISABLE_DB = false
 | 
			
		||||
    /// Controls whether incoming chat opens as a modal sheet (`true`) or navigates to Chats tab (`false`).
 | 
			
		||||
    static let PRESENT_CHAT_AS_SHEET = false
 | 
			
		||||
    /// Fallback SQLCipher key used until the user sets an application password.
 | 
			
		||||
    static let DEFAULT_DATABASE_ENCRYPTION_KEY = "yobble_dev_change_me"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -41,7 +41,7 @@ struct yobbleApp: App {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            .animation(.spring(response: 0.35, dampingFraction: 0.8), value: messageCenter.banner != nil)
 | 
			
		||||
            .sheet(item: $messageCenter.presentedChat) { chatItem in
 | 
			
		||||
            .sheet(item: AppConfig.PRESENT_CHAT_AS_SHEET ? $messageCenter.presentedChat : .constant(nil)) { chatItem in
 | 
			
		||||
                NavigationView {
 | 
			
		||||
                    PrivateChatView(
 | 
			
		||||
                        chat: chatItem,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user