diff --git a/Monal/Monal.xcodeproj/project.pbxproj b/Monal/Monal.xcodeproj/project.pbxproj index 2ef10ea..8327aa9 100644 --- a/Monal/Monal.xcodeproj/project.pbxproj +++ b/Monal/Monal.xcodeproj/project.pbxproj @@ -176,6 +176,8 @@ 7E995F2B2CEAC9A0005B30EE /* monalxmpp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26CC579223A0867400ABB92A /* monalxmpp.framework */; }; 7E995F2C2CEAC9A0005B30EE /* monalxmpp.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 26CC579223A0867400ABB92A /* monalxmpp.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 7E995F302CEAC9F6005B30EE /* Pods_monalxmpp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B9C86E0A568734587FE9BA2 /* Pods_monalxmpp.framework */; }; + 7EA6B8EC2CF208FB00196B10 /* ChatsCreateScreenMain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EA6B8E92CF208FB00196B10 /* ChatsCreateScreenMain.swift */; }; + 7EA6B8ED2CF208FB00196B10 /* ChatsListScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EA6B8EA2CF208FB00196B10 /* ChatsListScreen.swift */; }; 7ED6F0172CECC3AB0035B3B7 /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7ED6F0162CECC3AB0035B3B7 /* Colors.xcassets */; }; 7ED6F0192CECC3BF0035B3B7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7ED6F0182CECC3BF0035B3B7 /* Images.xcassets */; }; 840E23CA28ADA56900A7FAC9 /* MLUploadQueueCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 840E23C828ADA56900A7FAC9 /* MLUploadQueueCell.m */; }; @@ -680,6 +682,8 @@ 7E995F202CEAC5D2005B30EE /* AnotherIMApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnotherIMApp.swift; sourceTree = ""; }; 7E995F222CEAC5D2005B30EE /* RootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootView.swift; sourceTree = ""; }; 7E995F282CEAC672005B30EE /* ASN1Decoder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = ASN1Decoder.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7EA6B8E92CF208FB00196B10 /* ChatsCreateScreenMain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsCreateScreenMain.swift; sourceTree = ""; }; + 7EA6B8EA2CF208FB00196B10 /* ChatsListScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsListScreen.swift; sourceTree = ""; }; 7ED6F0162CECC3AB0035B3B7 /* Colors.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Colors.xcassets; sourceTree = ""; }; 7ED6F0182CECC3BF0035B3B7 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 7FA9582E4CC566FE5466C557 /* Pods-Monal.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Monal.debug.xcconfig"; path = "Target Support Files/Pods-Monal/Pods-Monal.debug.xcconfig"; sourceTree = ""; }; @@ -1558,6 +1562,15 @@ path = another.im; sourceTree = ""; }; + 7EA6B8EB2CF208FB00196B10 /* ChatList */ = { + isa = PBXGroup; + children = ( + 7EA6B8E92CF208FB00196B10 /* ChatsCreateScreenMain.swift */, + 7EA6B8EA2CF208FB00196B10 /* ChatsListScreen.swift */, + ); + path = ChatList; + sourceTree = ""; + }; 7ED6F0152CECC37E0035B3B7 /* Assets */ = { isa = PBXGroup; children = ( @@ -1730,6 +1743,7 @@ isa = PBXGroup; children = ( 7E1C0AC62CEF68C000B8FEC0 /* MainTabScreen.swift */, + 7EA6B8EB2CF208FB00196B10 /* ChatList */, 7E1C0ACA2CEF6C7800B8FEC0 /* Contacts */, ); path = Main; @@ -2630,6 +2644,8 @@ 7E8D7B182CECEE79009AD3DF /* ButtonStyles.swift in Sources */, 7E8D7B192CECEE79009AD3DF /* AVAsset+Thumbnail.swift in Sources */, 7E8D7B1A2CECEE79009AD3DF /* Const.swift in Sources */, + 7EA6B8EC2CF208FB00196B10 /* ChatsCreateScreenMain.swift in Sources */, + 7EA6B8ED2CF208FB00196B10 /* ChatsListScreen.swift in Sources */, 7E8D7B1B2CECEE79009AD3DF /* Typography.swift in Sources */, 7E8D7B1C2CECEE79009AD3DF /* TimeInterval+Extensions.swift in Sources */, 7E8D7B1D2CECEE79009AD3DF /* EdgeInsets+Extensions.swift in Sources */, diff --git a/Monal/another.im/Views/Main/ChatList/ChatsListScreen.swift b/Monal/another.im/Views/Main/ChatList/ChatsListScreen.swift index 4984ec3..e0d8b39 100644 --- a/Monal/another.im/Views/Main/ChatList/ChatsListScreen.swift +++ b/Monal/another.im/Views/Main/ChatList/ChatsListScreen.swift @@ -1,8 +1,8 @@ import SwiftUI struct ChatsListScreen: View { + @EnvironmentObject var wrapper: MonalXmppWrapper @Environment(\.router) var router - @EnvironmentObject var clientsStore: ClientsStore var body: some View { ZStack { @@ -26,15 +26,10 @@ struct ChatsListScreen: View { ) // Chats list - if !clientsStore.actualChats.isEmpty { + if !wrapper.activeChats.isEmpty { List { - ForEach(elements.indices, id: \.self) { index in - let element = elements[index] - if let chat = element as? Chat { - ChatsRow(chat: chat) - } else if let account = element as? String { - SharedSectionTitle(text: account) - } + ForEach(wrapper.activeChats) { + ChatsRow(chat: $0) } } .listStyle(.plain) @@ -45,33 +40,17 @@ struct ChatsListScreen: View { } } } - - private var elements: [Any] { - if clientsStore.clients.filter({ $0.credentials.isActive }).count == 1 { - return clientsStore.actualChats - } else { - var result: [Any] = [] - for chat in clientsStore.actualChats { - if result.isEmpty { - result.append(chat.account) - } else if let last = result.last as? Chat, last.account != chat.account { - result.append(chat.account) - } - result.append(chat) - } - return result - } - } } private struct ChatsRow: View { + @EnvironmentObject var wrapper: MonalXmppWrapper @Environment(\.router) var router - @EnvironmentObject var clientsStore: ClientsStore var chat: Chat var body: some View { - SharedListRow(iconType: .charCircle(chat.participant), text: chat.participant, controlType: .none) + Text("dump") + SharedListRow(iconType: .charCircle(chat.name), text: chat.name, controlType: .none) .onTapGesture { Task { router.showModal { @@ -82,12 +61,12 @@ private struct ChatsRow: View { } do { - try? await clientsStore.addRosterForNewChatIfNeeded(chat) - let (messages, attachments, settings) = try await clientsStore.conversationStores(for: chat) - router.showScreen(.push) { _ in - ConversationScreen(messagesStore: messages, attachments: attachments, settings: settings) - .navigationBarHidden(true) - } + // try? await clientsStore.addRosterForNewChatIfNeeded(chat) + // let (messages, attachments, settings) = try await clientsStore.conversationStores(for: chat) + // router.showScreen(.push) { _ in + // ConversationScreen(messagesStore: messages, attachments: attachments, settings: settings) + // .navigationBarHidden(true) + // } } catch { router.showAlert( .alert, diff --git a/Monal/another.im/Views/Main/MainTabScreen.swift b/Monal/another.im/Views/Main/MainTabScreen.swift index 7c8ce89..d39f29e 100644 --- a/Monal/another.im/Views/Main/MainTabScreen.swift +++ b/Monal/another.im/Views/Main/MainTabScreen.swift @@ -23,9 +23,7 @@ struct MainTabScreen: View { VStack(spacing: 0) { switch selectedTab { case .chats: - Text("chats") - Spacer() - // ChatsListScreen() + ChatsListScreen() case .contacts: ContactsScreen() diff --git a/Monal/another.im/XMPP/MonalWrapperModels.swift b/Monal/another.im/XMPP/MonalWrapperModels.swift index 7ec89b0..cb32c36 100644 --- a/Monal/another.im/XMPP/MonalWrapperModels.swift +++ b/Monal/another.im/XMPP/MonalWrapperModels.swift @@ -54,3 +54,29 @@ struct Contact: Identifiable { name = obj.nickName.isEmpty ? nil : obj.nickName } } + +// MARK: - Chat +struct Chat: Identifiable { + let accountId: Int + let participantJid: String + let participantName: String? + + var id: String { + "\(accountId)_\(participantJid)" + } + + var name: String { + if let participantName, !participantName.isEmpty { + return participantName + } else { + return participantJid + } + } + + init?(_ obj: MLContact) { + guard let accId = obj.accountID as? Int else { return nil } + accountId = accId + participantJid = obj.contactJid + participantName = obj.nickName + } +} diff --git a/Monal/another.im/XMPP/MonalXmppWrapper.swift b/Monal/another.im/XMPP/MonalXmppWrapper.swift index 6a26d72..9f1f1f1 100644 --- a/Monal/another.im/XMPP/MonalXmppWrapper.swift +++ b/Monal/another.im/XMPP/MonalXmppWrapper.swift @@ -5,6 +5,7 @@ final class MonalXmppWrapper: ObservableObject { @Published private(set) var accountsAvailability: AccountsAvailability = .noAccounts @Published private(set) var accounts: [Account] = [] @Published private(set) var contacts: [Contact] = [] + @Published private(set) var activeChats: [Chat] = [] private let xmpp: MLXMPPManager private let db: DataLayer @@ -106,17 +107,23 @@ private extension MonalXmppWrapper { let generalRefresh = NotificationCenter.default.addObserver(forName: Notification.Name(kMonalRefresh), object: nil, queue: .main) { [weak self] _ in self?.refreshAccounts() self?.refreshContacts() + self?.refreshChats() } notificationObservers.append(generalRefresh) // For contacts let contactRefresh = NotificationCenter.default.addObserver(forName: Notification.Name(kMonalContactRefresh), object: nil, queue: .main) { [weak self] _ in self?.refreshContacts() + self?.refreshChats() } let contactRemove = NotificationCenter.default.addObserver(forName: Notification.Name(kMonalContactRemoved), object: nil, queue: .main) { [weak self] _ in self?.refreshContacts() + self?.refreshChats() } notificationObservers.append(contentsOf: [contactRefresh, contactRemove]) + + // For chats + // ??? } func refreshAccounts() { @@ -144,4 +151,12 @@ private extension MonalXmppWrapper { .filter { !$0.isSelfChat } // removed for now .compactMap { Contact($0) } } + + func refreshChats() { + activeChats = db.activeContacts(withPinned: false) + .compactMap { + guard let contact = $0 as? MLContact else { return nil } + return Chat(contact) + } + } }