add 2 type chat view
This commit is contained in:
parent
86924af785
commit
cc9cc3149f
@ -4,6 +4,7 @@ import Combine
|
|||||||
final class IncomingMessageCenter: ObservableObject {
|
final class IncomingMessageCenter: ObservableObject {
|
||||||
@Published private(set) var banner: IncomingMessageBanner?
|
@Published private(set) var banner: IncomingMessageBanner?
|
||||||
@Published var presentedChat: PrivateChatListItem?
|
@Published var presentedChat: PrivateChatListItem?
|
||||||
|
@Published var pendingNavigation: ChatNavigationTarget?
|
||||||
var currentUserId: String?
|
var currentUserId: String?
|
||||||
var activeChatId: String?
|
var activeChatId: String?
|
||||||
|
|
||||||
@ -31,7 +32,14 @@ final class IncomingMessageCenter: ObservableObject {
|
|||||||
func openCurrentChat() {
|
func openCurrentChat() {
|
||||||
guard let banner else { return }
|
guard let banner else { return }
|
||||||
activeChatId = banner.message.chatId
|
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()
|
dismissBanner()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +52,9 @@ final class IncomingMessageCenter: ObservableObject {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if let presentedChat, presentedChat.chatId == message.chatId {
|
if AppConfig.PRESENT_CHAT_AS_SHEET,
|
||||||
|
let presentedChat,
|
||||||
|
presentedChat.chatId == message.chatId {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,4 +122,9 @@ final class IncomingMessageCenter: ObservableObject {
|
|||||||
dismissWorkItem = workItem
|
dismissWorkItem = workItem
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: 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 {
|
struct ChatsTab: View {
|
||||||
@ObservedObject private var loginViewModel: LoginViewModel
|
@ObservedObject private var loginViewModel: LoginViewModel
|
||||||
|
@Binding private var pendingNavigation: IncomingMessageCenter.ChatNavigationTarget?
|
||||||
@Binding var searchRevealProgress: CGFloat
|
@Binding var searchRevealProgress: CGFloat
|
||||||
@Binding var searchText: String
|
@Binding var searchText: String
|
||||||
private let searchService = SearchService()
|
private let searchService = SearchService()
|
||||||
@ -40,10 +41,12 @@ struct ChatsTab: View {
|
|||||||
|
|
||||||
init(
|
init(
|
||||||
loginViewModel: LoginViewModel,
|
loginViewModel: LoginViewModel,
|
||||||
|
pendingNavigation: Binding<IncomingMessageCenter.ChatNavigationTarget?>,
|
||||||
searchRevealProgress: Binding<CGFloat>,
|
searchRevealProgress: Binding<CGFloat>,
|
||||||
searchText: Binding<String>
|
searchText: Binding<String>
|
||||||
) {
|
) {
|
||||||
self._loginViewModel = ObservedObject(wrappedValue: loginViewModel)
|
self._loginViewModel = ObservedObject(wrappedValue: loginViewModel)
|
||||||
|
self._pendingNavigation = pendingNavigation
|
||||||
self._searchRevealProgress = searchRevealProgress
|
self._searchRevealProgress = searchRevealProgress
|
||||||
self._searchText = searchText
|
self._searchText = searchText
|
||||||
}
|
}
|
||||||
@ -97,6 +100,13 @@ struct ChatsTab: View {
|
|||||||
globalSearchTask?.cancel()
|
globalSearchTask?.cancel()
|
||||||
globalSearchTask = nil
|
globalSearchTask = nil
|
||||||
}
|
}
|
||||||
|
.onChange(of: pendingNavigation?.id) { _ in
|
||||||
|
guard let target = pendingNavigation else { return }
|
||||||
|
handleNavigationTarget(target.chat)
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
pendingNavigation = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
@ -542,6 +552,30 @@ private extension ChatsTab {
|
|||||||
#endif
|
#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) {
|
func handleSearchQueryChange(_ query: String) {
|
||||||
let trimmed = query.trimmingCharacters(in: .whitespacesAndNewlines)
|
let trimmed = query.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
|
||||||
@ -1161,10 +1195,12 @@ struct ChatsTab_Previews: PreviewProvider {
|
|||||||
@State private var progress: CGFloat = 1
|
@State private var progress: CGFloat = 1
|
||||||
@State private var searchText: String = ""
|
@State private var searchText: String = ""
|
||||||
@StateObject private var loginViewModel = LoginViewModel()
|
@StateObject private var loginViewModel = LoginViewModel()
|
||||||
|
@State private var pendingNavigation: IncomingMessageCenter.ChatNavigationTarget?
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ChatsTab(
|
ChatsTab(
|
||||||
loginViewModel: loginViewModel,
|
loginViewModel: loginViewModel,
|
||||||
|
pendingNavigation: $pendingNavigation,
|
||||||
searchRevealProgress: $progress,
|
searchRevealProgress: $progress,
|
||||||
searchText: $searchText
|
searchText: $searchText
|
||||||
)
|
)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import SwiftUI
|
|||||||
|
|
||||||
struct MainView: View {
|
struct MainView: View {
|
||||||
@ObservedObject var viewModel: LoginViewModel
|
@ObservedObject var viewModel: LoginViewModel
|
||||||
|
@EnvironmentObject private var messageCenter: IncomingMessageCenter
|
||||||
@State private var selectedTab: Int = 0
|
@State private var selectedTab: Int = 0
|
||||||
// @StateObject private var newHomeTabViewModel = NewHomeTabViewModel()
|
// @StateObject private var newHomeTabViewModel = NewHomeTabViewModel()
|
||||||
|
|
||||||
@ -33,6 +34,12 @@ struct MainView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationView {
|
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: .top) {
|
||||||
ZStack(alignment: .leading) { // Выравниваем ZStack по левому краю
|
ZStack(alignment: .leading) { // Выравниваем ZStack по левому краю
|
||||||
// Основной контент
|
// Основной контент
|
||||||
@ -57,6 +64,7 @@ struct MainView: View {
|
|||||||
|
|
||||||
ChatsTab(
|
ChatsTab(
|
||||||
loginViewModel: viewModel,
|
loginViewModel: viewModel,
|
||||||
|
pendingNavigation: pendingNavigationBinding,
|
||||||
searchRevealProgress: $chatSearchRevealProgress,
|
searchRevealProgress: $chatSearchRevealProgress,
|
||||||
searchText: $chatSearchText
|
searchText: $chatSearchText
|
||||||
)
|
)
|
||||||
@ -137,6 +145,20 @@ struct MainView: View {
|
|||||||
menuOffset = presented ? menuWidth : 0
|
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 {
|
static var previews: some View {
|
||||||
let mockViewModel = LoginViewModel()
|
let mockViewModel = LoginViewModel()
|
||||||
MainView(viewModel: mockViewModel)
|
MainView(viewModel: mockViewModel)
|
||||||
|
.environmentObject(IncomingMessageCenter())
|
||||||
.environmentObject(ThemeManager())
|
.environmentObject(ThemeManager())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,8 @@ struct AppConfig {
|
|||||||
static let APP_VERSION = "0.1"
|
static let APP_VERSION = "0.1"
|
||||||
|
|
||||||
static let DISABLE_DB = false
|
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.
|
/// Fallback SQLCipher key used until the user sets an application password.
|
||||||
static let DEFAULT_DATABASE_ENCRYPTION_KEY = "yobble_dev_change_me"
|
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)
|
.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 {
|
NavigationView {
|
||||||
PrivateChatView(
|
PrivateChatView(
|
||||||
chat: chatItem,
|
chat: chatItem,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user