diff --git a/Monal/another.im/Views/Conversation/ConversationScreen.swift b/Monal/another.im/Views/Conversation/ConversationScreen.swift index 0e63020..f75ca2a 100644 --- a/Monal/another.im/Views/Conversation/ConversationScreen.swift +++ b/Monal/another.im/Views/Conversation/ConversationScreen.swift @@ -107,14 +107,10 @@ struct ConversationScreen: View { } } } - // .environmentObject(messagesStore) - // .environmentObject(attachments) - // .safeAreaInset(edge: .bottom, spacing: 0) { - // ConversationTextInput(autoScroll: $autoScroll) - // .environmentObject(messagesStore) - // .environmentObject(attachments) - // .environmentObject(settings) - // } + .safeAreaInset(edge: .bottom, spacing: 0) { + ConversationTextInput(autoScroll: $autoScroll) + .environmentObject(chatWrapper) + } } private func centerText() -> String { diff --git a/Monal/another.im/Views/Conversation/ConversationTextInput.swift b/Monal/another.im/Views/Conversation/ConversationTextInput.swift index f8c539f..5b6dcef 100644 --- a/Monal/another.im/Views/Conversation/ConversationTextInput.swift +++ b/Monal/another.im/Views/Conversation/ConversationTextInput.swift @@ -3,8 +3,7 @@ import UIKit struct ConversationTextInput: View { @Environment(\.router) var router - // @EnvironmentObject var messages: MessagesStore - // @EnvironmentObject var attachments: AttachmentsStore + @EnvironmentObject var chatWrapper: MonalChatWrapper @State private var messageStr = "" @FocusState private var isFocused: Bool @@ -16,35 +15,35 @@ struct ConversationTextInput: View { .foregroundColor(.Material.Shape.separator) .frame(height: 0.5) .padding(.bottom, 8) - // if !messages.replyText.isEmpty { - // VStack(spacing: 0) { - // HStack(alignment: .top) { - // Text(messages.replyText) - // .font(.body3) - // .foregroundColor(Color.Material.Text.main) - // .multilineTextAlignment(.leading) - // .lineLimit(3) - // .padding(8) - // Spacer() - // Image(systemName: "xmark") - // .font(.title2) - // .foregroundColor(.Material.Elements.active) - // .padding(.leading, 8) - // .tappablePadding(.symmetric(8)) { - // messages.replyText = "" - // } - // .padding(8) - // } - // .frame(maxWidth: .infinity) - // .background(RoundedRectangle(cornerRadius: 4) - // .foregroundColor(.Material.Background.light) - // .shadow(radius: 0.5) - // ) - // .padding(.bottom, 8) - // .padding(.horizontal, 8) - // } - // .padding(.horizontal, 8) - // } + if !chatWrapper.replyText.isEmpty { + VStack(spacing: 0) { + HStack(alignment: .top) { + Text(chatWrapper.replyText) + .font(.body3) + .foregroundColor(Color.Material.Text.main) + .multilineTextAlignment(.leading) + .lineLimit(3) + .padding(8) + Spacer() + Image(systemName: "xmark") + .font(.title2) + .foregroundColor(.Material.Elements.active) + .padding(.leading, 8) + .tappablePadding(.symmetric(8)) { + chatWrapper.replyText = "" + } + .padding(8) + } + .frame(maxWidth: .infinity) + .background(RoundedRectangle(cornerRadius: 4) + .foregroundColor(.Material.Background.light) + .shadow(radius: 0.5) + ) + .padding(.bottom, 8) + .padding(.horizontal, 8) + } + .padding(.horizontal, 8) + } HStack { Image(systemName: "paperclip") .font(.title2) @@ -52,7 +51,8 @@ struct ConversationTextInput: View { .padding(.leading, 8) .tappablePadding(.symmetric(8)) { router.showScreen(.fullScreenCover) { _ in - AttachmentPickerScreen() + Text("not yet implemented") + // AttachmentPickerScreen() // .environmentObject(messages) // .environmentObject(attachments) } @@ -74,31 +74,31 @@ struct ConversationTextInput: View { .padding(.trailing, 8) .tappablePadding(.symmetric(8)) { if !messageStr.isEmpty { - // messages.sendMessage(composedMessage) - // messageStr = "" - // autoScroll = true - // if !messages.replyText.isEmpty { - // messages.replyText = "" - // } + chatWrapper.sendText(composedMessage) + messageStr = "" + autoScroll = true + if !chatWrapper.replyText.isEmpty { + chatWrapper.replyText = "" + } } } } } .padding(.bottom, 8) .background(Color.Material.Background.dark) - // .onChange(of: messages.replyText) { new in - // if !new.isEmpty { - // isFocused = true - // } - // } + .onChange(of: chatWrapper.replyText) { new in + if !new.isEmpty { + isFocused = true + } + } } private var composedMessage: String { var result = "" - // if !messages.replyText.isEmpty { - // result += messages.replyText.makeReply + "\n\n" - // } - // result += messageStr + if !chatWrapper.replyText.isEmpty { + result += chatWrapper.replyText.makeReply + "\n\n" + } + result += messageStr return result } } diff --git a/Monal/another.im/XMPP/MonalXmppWrapper.swift b/Monal/another.im/XMPP/MonalXmppWrapper.swift index 007363a..915a47e 100644 --- a/Monal/another.im/XMPP/MonalXmppWrapper.swift +++ b/Monal/another.im/XMPP/MonalXmppWrapper.swift @@ -60,13 +60,16 @@ extension MonalXmppWrapper { } func chat(with: Contact) -> MonalChatWrapper { - let chatModel = MonalChatWrapper(contact: with, db: db, xmpp: xmpp) + // swiftlint:disable:next force_unwrapping + let account = accounts.first { $0.id == with.ownerId }! + let chatModel = MonalChatWrapper(account: account, contact: with, db: db, xmpp: xmpp) return chatModel } func chat(with: Chat) -> MonalChatWrapper? { + guard let account = accounts.first(where: { $0.id == with.accountId }) else { return nil } guard let contact = contacts.first(where: { $0.ownerId == with.accountId && $0.contactJid == with.participantJid }) else { return nil } - let chatModel = MonalChatWrapper(contact: contact, db: db, xmpp: xmpp) + let chatModel = MonalChatWrapper(account: account, contact: contact, db: db, xmpp: xmpp) return chatModel } } @@ -177,36 +180,70 @@ private extension MonalXmppWrapper { // MARK: - Chat object final class MonalChatWrapper: ObservableObject { @Published private(set) var messages: [Message] = [] + @Published var replyText: String = "" let contact: Contact + + private let monalContact: MLContact + private let account: Account private let xmpp: MLXMPPManager private let db: DataLayer private var notificationObservers: [AnyObject] = [] - init(contact: Contact, db: DataLayer, xmpp: MLXMPPManager) { + init(account: Account, contact: Contact, db: DataLayer, xmpp: MLXMPPManager) { self.contact = contact + self.account = account self.db = db self.xmpp = xmpp + // swiftlint:disable:next force_unwrapping + monalContact = db.contactList().first { $0.accountID.intValue == contact.ownerId && $0.contactJid == contact.contactJid }! + subscribe() + NotificationCenter.default.post(name: Notification.Name(kMonalNewMessageNotice), object: nil) } deinit { notificationObservers.forEach { NotificationCenter.default.removeObserver($0) } } - private func subscribe() { + func sendText(_ text: String) { + let msgId = db.addMessageHistory( + to: contact.contactJid, + forAccount: monalContact.accountID, + withMessage: text, + actuallyFrom: account.jid, + withId: UUID().uuidString, + encrypted: monalContact.isEncrypted, + messageType: kMessageTypeText, + mimeType: nil, + size: nil + ) + xmpp.sendMessage(text, to: monalContact, isEncrypted: monalContact.isEncrypted, isUpload: false, messageId: "\(msgId)") + NotificationCenter.default.post(name: Notification.Name(kMonalSentMessageNotice), object: nil) + } +} + +private extension MonalChatWrapper { + func subscribe() { let newMsg = NotificationCenter.default.addObserver(forName: Notification.Name(kMonalNewMessageNotice), object: nil, queue: .main) { [weak self] _ in self?.refreshMessages() } notificationObservers.append(newMsg) + + let sentMsg = NotificationCenter.default.addObserver(forName: Notification.Name(kMonalSentMessageNotice), object: nil, queue: .main) { [weak self] _ in + self?.refreshMessages() + } + notificationObservers.append(sentMsg) } - private func refreshMessages() { - messages = db.messages(forContact: contact.contactJid, forAccount: NSNumber(value: contact.ownerId)) - .compactMap { - guard let message = $0 as? MLMessage else { return nil } + func refreshMessages() { + let messages = db.messages(forContact: contact.contactJid, forAccount: NSNumber(value: contact.ownerId)) + .compactMap { obj -> Message? in + guard let message = obj as? MLMessage else { return nil } return Message(message) } + .sorted { $0.timestamp > $1.timestamp } + self.messages = messages } }