wip
This commit is contained in:
parent
995d627fde
commit
1e27b8643c
|
@ -1,4 +1,8 @@
|
|||
enum XMPPAction: Codable {
|
||||
case clientConnectionChanged(jid: String, state: ConnectionStatus)
|
||||
case xmppMessageReceived(Message)
|
||||
|
||||
case xmppMessageSent(Message)
|
||||
case xmppMessageSendFailed(msgId: String)
|
||||
case xmppMessageSendSuccess(msgId: String)
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ extension Database {
|
|||
table.column("oobUrl", .text)
|
||||
table.column("date", .datetime).notNull()
|
||||
table.column("pending", .boolean).notNull()
|
||||
table.column("sentError", .boolean).notNull()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -184,7 +184,83 @@ final class DatabaseMiddleware {
|
|||
.eraseToAnyPublisher()
|
||||
|
||||
case .conversationAction(.sendMessage(let from, let to, let body)):
|
||||
return Empty().eraseToAnyPublisher()
|
||||
return Future<AppAction, Never> { promise in
|
||||
Task(priority: .background) { [weak self] in
|
||||
guard let database = self?.database else {
|
||||
promise(.success(.databaseAction(.storeMessageFailed(reason: L10n.Global.Error.genericDbError))))
|
||||
return
|
||||
}
|
||||
do {
|
||||
let message = Message(
|
||||
id: UUID().uuidString,
|
||||
type: .chat,
|
||||
contentType: .text,
|
||||
from: from,
|
||||
to: to,
|
||||
body: body,
|
||||
subject: nil,
|
||||
thread: nil,
|
||||
oobUrl: nil,
|
||||
date: Date(),
|
||||
pending: true,
|
||||
sentError: false
|
||||
)
|
||||
try database._db.write { db in
|
||||
try message.insert(db)
|
||||
}
|
||||
promise(.success(.xmppAction(.xmppMessageSent(message))))
|
||||
} catch {
|
||||
promise(.success(.databaseAction(.storeMessageFailed(reason: error.localizedDescription))))
|
||||
}
|
||||
}
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
|
||||
case .xmppAction(.xmppMessageSendSuccess(let msgId)):
|
||||
// mark message as pending false and sentError false
|
||||
return Future<AppAction, Never> { promise in
|
||||
Task(priority: .background) { [weak self] in
|
||||
guard let database = self?.database else {
|
||||
promise(.success(.databaseAction(.storeMessageFailed(reason: L10n.Global.Error.genericDbError))))
|
||||
return
|
||||
}
|
||||
do {
|
||||
_ = try database._db.write { db in
|
||||
try Message
|
||||
.filter(Column("id") == msgId)
|
||||
.updateAll(db, Column("pending").set(to: false), Column("sentError").set(to: false))
|
||||
}
|
||||
promise(.success(.empty))
|
||||
} catch {
|
||||
promise(.success(.databaseAction(.storeMessageFailed(reason: error.localizedDescription)))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
|
||||
case .xmppAction(.xmppMessageSendFailed(let msgId)):
|
||||
// mark message as pending false and sentError true
|
||||
return Future<AppAction, Never> { promise in
|
||||
Task(priority: .background) { [weak self] in
|
||||
guard let database = self?.database else {
|
||||
promise(.success(.databaseAction(.storeMessageFailed(reason: L10n.Global.Error.genericDbError))))
|
||||
return
|
||||
}
|
||||
do {
|
||||
_ = try database._db.write { db in
|
||||
try Message
|
||||
.filter(Column("id") == msgId)
|
||||
.updateAll(db, Column("pending").set(to: false), Column("sentError").set(to: true))
|
||||
}
|
||||
promise(.success(.empty))
|
||||
} catch {
|
||||
promise(.success(.databaseAction(.storeMessageFailed(reason: error.localizedDescription)))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
|
||||
default:
|
||||
return Empty().eraseToAnyPublisher()
|
||||
|
@ -206,9 +282,7 @@ private extension DatabaseMiddleware {
|
|||
.fetchAll
|
||||
)
|
||||
.publisher(in: database._db, scheduling: .immediate)
|
||||
.sink { res in
|
||||
print("!!!---Messages received: \(res)")
|
||||
// Handle completion
|
||||
.sink { _ in
|
||||
} receiveValue: { messages in
|
||||
DispatchQueue.main.async {
|
||||
store.dispatch(.conversationAction(.messagesUpdated(messages: messages)))
|
||||
|
|
|
@ -86,13 +86,19 @@ final class XMPPMiddleware {
|
|||
}
|
||||
.eraseToAnyPublisher()
|
||||
|
||||
// case .conversationAction(.sendMessage(let from, let to, let body)):
|
||||
// return Future<AppAction, Never> { [weak self] promise in
|
||||
// // TODO: handle errors
|
||||
// self?.service.sendMessage(from: from, to: to, body: body)
|
||||
// promise(.success(.empty))
|
||||
// }
|
||||
// .eraseToAnyPublisher()
|
||||
case .xmppAction(.xmppMessageSent(let message)):
|
||||
return Future<AppAction, Never> { [weak self] promise in
|
||||
DispatchQueue.global().async {
|
||||
self?.service.sendMessage(message: message) { done in
|
||||
if done {
|
||||
promise(.success(.xmppAction(.xmppMessageSendSuccess(msgId: message.id))))
|
||||
} else {
|
||||
promise(.success(.xmppAction(.xmppMessageSendFailed(msgId: message.id))))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
|
||||
default:
|
||||
return Empty().eraseToAnyPublisher()
|
||||
|
|
|
@ -31,6 +31,7 @@ struct Message: DBStorable, Equatable {
|
|||
|
||||
let date: Date
|
||||
let pending: Bool
|
||||
let sentError: Bool
|
||||
}
|
||||
|
||||
extension Message {
|
||||
|
@ -76,7 +77,8 @@ extension Message {
|
|||
thread: martinMessage.thread,
|
||||
oobUrl: martinMessage.oob,
|
||||
date: Date(),
|
||||
pending: false
|
||||
pending: false,
|
||||
sentError: false
|
||||
)
|
||||
return msg
|
||||
}
|
||||
|
|
|
@ -104,16 +104,25 @@ final class XMPPService: ObservableObject {
|
|||
clients.first { $0.connectionConfiguration.userJid.stringValue == jid }
|
||||
}
|
||||
|
||||
// TODO: add handler
|
||||
func sendMessage(from: String, to: String, body: String) {
|
||||
guard let client = getClient(for: from) else { return }
|
||||
func sendMessage(message: Message, completion: @escaping (Bool) -> Void) {
|
||||
guard let client = getClient(for: message.from), let to = message.to else {
|
||||
completion(false)
|
||||
return
|
||||
}
|
||||
let message = Martin.Message()
|
||||
// message.from = client.connectionConfiguration.userJid
|
||||
message.to = JID(to)
|
||||
message.body = body
|
||||
message.body = message.body
|
||||
|
||||
client.writer.write(message) { res in
|
||||
print(res)
|
||||
client.module(MessageModule.self)
|
||||
.chatManager
|
||||
.chat(for: client.context, with: JID(to).bareJid)?
|
||||
.send(message: message) { res in
|
||||
switch res {
|
||||
case .success:
|
||||
completion(true)
|
||||
case .failure:
|
||||
completion(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,20 +129,14 @@ private struct ConversationMessageRow: View {
|
|||
HStack(spacing: 0) {
|
||||
if isOutgoing() {
|
||||
Spacer()
|
||||
VStack(spacing: 0) {
|
||||
MessageTime(message: message)
|
||||
Spacer()
|
||||
}
|
||||
MessageAttr(message: message)
|
||||
.padding(.trailing, 4)
|
||||
}
|
||||
MessageContainer(message: message, isOutgoing: isOutgoing())
|
||||
.background(isOutgoing() ? Color.Material.greenDark100 : Color.Main.white)
|
||||
.clipShape(MessageBubble(isOutgoing: isOutgoing()))
|
||||
if !isOutgoing() {
|
||||
VStack(spacing: 0) {
|
||||
MessageTime(message: message)
|
||||
Spacer()
|
||||
}
|
||||
MessageAttr(message: message)
|
||||
.padding(.leading, 4)
|
||||
Spacer()
|
||||
}
|
||||
|
@ -184,13 +178,25 @@ struct MessageBubble: Shape {
|
|||
}
|
||||
}
|
||||
|
||||
struct MessageTime: View {
|
||||
struct MessageAttr: View {
|
||||
let message: Message
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
Text(message.date, style: .time)
|
||||
.font(.sub2)
|
||||
.foregroundColor(Color.Main.gray)
|
||||
Spacer()
|
||||
if message.sentError {
|
||||
Image(systemName: "exclamationmark.circle")
|
||||
.font(.body3)
|
||||
.foregroundColor(Color.Tango.redLight)
|
||||
} else if message.pending {
|
||||
Image(systemName: "clock")
|
||||
.font(.body3)
|
||||
.foregroundColor(Color.Main.gray)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,13 +232,13 @@ struct MessageTime: View {
|
|||
thread: nil,
|
||||
oobUrl: nil,
|
||||
date: Date(),
|
||||
pending: false
|
||||
pending: true, sentError: false
|
||||
),
|
||||
Message(id: "2", type: .chat, contentType: .text, from: contact, to: acc, body: "this is for testsdfsdf sdfsdf sdfs sdf sdffsdf sdf sdf sdf sdf sdf sdff sdfffwwe ", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false),
|
||||
Message(id: "3", type: .chat, contentType: .text, from: contact, to: acc, body: "this is for test", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false),
|
||||
Message(id: "4", type: .chat, contentType: .text, from: acc, to: contact, body: "this is for test sdfkjwek jwkjfh jwerf jdfhskjdhf jsdhfjhwefh sjdhfh fsdjhfh sd ", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false),
|
||||
Message(id: "5", type: .chat, contentType: .text, from: contact, to: acc, body: "this is for test sdfjkkeke kekkddjw;; w;edkdjfj l kjwekrjfk wef", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false),
|
||||
Message(id: "6", type: .chat, contentType: .text, from: acc, to: contact, body: "this is for testsdf dsdkkekkddn wejkjfj ", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false),
|
||||
Message(id: "2", type: .chat, contentType: .text, from: contact, to: acc, body: "this is for testsdfsdf sdfsdf sdfs sdf sdffsdf sdf sdf sdf sdf sdf sdff sdfffwwe ", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false),
|
||||
Message(id: "3", type: .chat, contentType: .text, from: contact, to: acc, body: "this is for test", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: true),
|
||||
Message(id: "4", type: .chat, contentType: .text, from: acc, to: contact, body: "this is for test sdfkjwek jwkjfh jwerf jdfhskjdhf jsdhfjhwefh sjdhfh fsdjhfh sd ", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false),
|
||||
Message(id: "5", type: .chat, contentType: .text, from: contact, to: acc, body: "this is for test sdfjkkeke kekkddjw;; w;edkdjfj l kjwekrjfk wef", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false),
|
||||
Message(id: "6", type: .chat, contentType: .text, from: acc, to: contact, body: "this is for testsdf dsdkkekkddn wejkjfj ", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false),
|
||||
Message(
|
||||
id: "7",
|
||||
type: .chat,
|
||||
|
@ -244,12 +250,12 @@ struct MessageTime: View {
|
|||
subject: nil,
|
||||
thread: nil,
|
||||
oobUrl: nil,
|
||||
date: Date(), pending: false
|
||||
date: Date(), pending: false, sentError: false
|
||||
),
|
||||
Message(id: "8", type: .chat, contentType: .text, from: acc, to: contact, body: "so test", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false),
|
||||
Message(id: "9", type: .chat, contentType: .text, from: contact, to: acc, body: "so test", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false),
|
||||
Message(id: "10", type: .chat, contentType: .text, from: acc, to: contact, body: "so test so test so test", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false),
|
||||
Message(id: "11", type: .chat, contentType: .text, from: contact, to: acc, body: "xD", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false)
|
||||
Message(id: "8", type: .chat, contentType: .text, from: acc, to: contact, body: "so test", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false),
|
||||
Message(id: "9", type: .chat, contentType: .text, from: contact, to: acc, body: "so test", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false),
|
||||
Message(id: "10", type: .chat, contentType: .text, from: acc, to: contact, body: "so test so test so test", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false),
|
||||
Message(id: "11", type: .chat, contentType: .text, from: contact, to: acc, body: "xD", subject: nil, thread: nil, oobUrl: nil, date: Date(), pending: false, sentError: false)
|
||||
]
|
||||
return state
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue