|
|
|
@ -41,7 +41,7 @@ public final class MultiDeviceProtocol : NSObject {
|
|
|
|
|
return !(message is DeviceLinkMessage) && !message.thread.isGroupThread()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static func copy(_ messageSend: OWSMessageSend, for destination: MultiDeviceDestination, with seal: Resolver<TSContactThread>) -> OWSMessageSend {
|
|
|
|
|
private static func copy(_ messageSend: OWSMessageSend, for destination: MultiDeviceDestination, with seal: Resolver<Void>) -> OWSMessageSend {
|
|
|
|
|
var recipient: SignalRecipient!
|
|
|
|
|
storage.dbReadConnection.read { transaction in
|
|
|
|
|
recipient = SignalRecipient.getOrBuildUnsavedRecipient(forRecipientId: destination.hexEncodedPublicKey, transaction: transaction)
|
|
|
|
@ -49,47 +49,47 @@ public final class MultiDeviceProtocol : NSObject {
|
|
|
|
|
// TODO: Why is it okay that the thread, sender certificate, etc. don't get changed?
|
|
|
|
|
return OWSMessageSend(message: messageSend.message, thread: messageSend.thread, recipient: recipient,
|
|
|
|
|
senderCertificate: messageSend.senderCertificate, udAccess: messageSend.udAccess, localNumber: messageSend.localNumber, success: {
|
|
|
|
|
seal.fulfill(messageSend.message.thread as! TSContactThread)
|
|
|
|
|
seal.fulfill(())
|
|
|
|
|
}, failure: { error in
|
|
|
|
|
seal.reject(error)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static func sendMessage(_ messageSend: OWSMessageSend, to destination: MultiDeviceDestination, in transaction: YapDatabaseReadTransaction) -> Promise<Void> {
|
|
|
|
|
let (promise, seal) = Promise<TSContactThread>.pending()
|
|
|
|
|
let message = messageSend.message
|
|
|
|
|
let messageSender = SSKEnvironment.shared.messageSender
|
|
|
|
|
promise.done(on: OWSDispatch.sendingQueue()) { thread in
|
|
|
|
|
let (threadPromise, threadPromiseSeal) = Promise<TSContactThread>.pending()
|
|
|
|
|
if let thread = TSContactThread.getWithContactId(destination.hexEncodedPublicKey, transaction: transaction) {
|
|
|
|
|
threadPromiseSeal.fulfill(thread)
|
|
|
|
|
} else {
|
|
|
|
|
// Dispatch async on the main queue to avoid nested write transactions
|
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
storage.dbReadWriteConnection.readWrite { transaction in
|
|
|
|
|
let thread = TSContactThread.getOrCreateThread(withContactId: destination.hexEncodedPublicKey, transaction: transaction)
|
|
|
|
|
threadPromiseSeal.fulfill(thread)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return threadPromise.then(on: OWSDispatch.sendingQueue()) { thread -> Promise<Void> in
|
|
|
|
|
let message = messageSend.message
|
|
|
|
|
let messageSender = SSKEnvironment.shared.messageSender
|
|
|
|
|
let (promise, seal) = Promise<Void>.pending()
|
|
|
|
|
let shouldSendAutoGeneratedFR = !thread.isContactFriend && !(message is FriendRequestMessage)
|
|
|
|
|
&& message.shouldBeSaved() // shouldBeSaved indicates it isn't a transient message
|
|
|
|
|
if !shouldSendAutoGeneratedFR {
|
|
|
|
|
let messageSendCopy = copy(messageSend, for: destination, with: seal)
|
|
|
|
|
messageSender.sendMessage(messageSendCopy)
|
|
|
|
|
} else {
|
|
|
|
|
// Dispatch async on the main queue to avoid nested write transactions
|
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
storage.dbReadWriteConnection.readWrite { transaction in
|
|
|
|
|
getAutoGeneratedMultiDeviceFRMessageSend(for: destination.hexEncodedPublicKey, in: transaction)
|
|
|
|
|
getAutoGeneratedMultiDeviceFRMessageSend(for: destination.hexEncodedPublicKey, in: transaction, seal: seal)
|
|
|
|
|
.done(on: OWSDispatch.sendingQueue()) { autoGeneratedFRMessageSend in
|
|
|
|
|
messageSender.sendMessage(autoGeneratedFRMessageSend)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return promise
|
|
|
|
|
}
|
|
|
|
|
promise.catch(on: OWSDispatch.sendingQueue()) { error in
|
|
|
|
|
print("[Loki] Couldn't get thread for destination: \(destination.hexEncodedPublicKey).")
|
|
|
|
|
}
|
|
|
|
|
if let thread = TSContactThread.getWithContactId(destination.hexEncodedPublicKey, transaction: transaction) {
|
|
|
|
|
seal.fulfill(thread)
|
|
|
|
|
} else {
|
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
storage.dbReadWriteConnection.readWrite { transaction in
|
|
|
|
|
let thread = TSContactThread.getOrCreateThread(withContactId: destination.hexEncodedPublicKey, transaction: transaction)
|
|
|
|
|
seal.fulfill(thread)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return promise.map { _ in }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@objc(sendMessageToDestinationAndLinkedDevices:in:)
|
|
|
|
@ -166,7 +166,7 @@ public final class MultiDeviceProtocol : NSObject {
|
|
|
|
|
return AnyPromise.from(getAutoGeneratedMultiDeviceFRMessageSend(for: hexEncodedPublicKey, in: transaction))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static func getAutoGeneratedMultiDeviceFRMessageSend(for hexEncodedPublicKey: String, in transaction: YapDatabaseReadWriteTransaction) -> Promise<OWSMessageSend> {
|
|
|
|
|
public static func getAutoGeneratedMultiDeviceFRMessageSend(for hexEncodedPublicKey: String, in transaction: YapDatabaseReadWriteTransaction, seal externalSeal: Resolver<Void>? = nil) -> Promise<OWSMessageSend> {
|
|
|
|
|
let thread = TSContactThread.getOrCreateThread(withContactId: hexEncodedPublicKey, transaction: transaction)
|
|
|
|
|
let message = getAutoGeneratedMultiDeviceFRMessage(for: hexEncodedPublicKey, in: transaction)
|
|
|
|
|
thread.friendRequestStatus = .requestSending
|
|
|
|
@ -183,11 +183,15 @@ public final class MultiDeviceProtocol : NSObject {
|
|
|
|
|
}
|
|
|
|
|
let messageSend = OWSMessageSend(message: message, thread: thread, recipient: recipient, senderCertificate: senderCertificate,
|
|
|
|
|
udAccess: recipientUDAccess, localNumber: getUserHexEncodedPublicKey(), success: {
|
|
|
|
|
externalSeal?.fulfill(())
|
|
|
|
|
// Dispatch async on the main queue to avoid nested write transactions
|
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
thread.friendRequestStatus = .requestSent
|
|
|
|
|
thread.save()
|
|
|
|
|
}
|
|
|
|
|
}, failure: { _ in
|
|
|
|
|
}, failure: { error in
|
|
|
|
|
externalSeal?.reject(error)
|
|
|
|
|
// Dispatch async on the main queue to avoid nested write transactions
|
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
|
thread.friendRequestStatus = .none
|
|
|
|
|
thread.save()
|
|
|
|
|