diff --git a/Session/Signal/ConversationView/ConversationViewModel.m b/Session/Signal/ConversationView/ConversationViewModel.m index 1833020b6..aa287a615 100644 --- a/Session/Signal/ConversationView/ConversationViewModel.m +++ b/Session/Signal/ConversationView/ConversationViewModel.m @@ -1235,6 +1235,17 @@ static const int kYapDatabaseRangeMaxLength = 25000; OWSAssertDebug(!viewItemCache[interaction.uniqueId]); viewItemCache[interaction.uniqueId] = viewItem; [viewItems addObject:viewItem]; + TSMessage *message = (TSMessage *)viewItem.interaction; + if (message.hasAttachmentsInNSE) { + [SSKEnvironment.shared.attachmentDownloads downloadAttachmentsForMessage:message + transaction:transaction + success:^(NSArray *attachmentStreams) { + OWSLogInfo(@"Successfully redownloaded attachment in thread: %@", message.thread); + } + failure:^(NSError *error) { + OWSLogWarn(@"Failed to redownload message with error: %@", error); + }]; + } return viewItem; }; diff --git a/SessionMessagingKit/File Server/FileServerAPI.swift b/SessionMessagingKit/File Server/FileServerAPI.swift index 957e8ff80..95ee986a7 100644 --- a/SessionMessagingKit/File Server/FileServerAPI.swift +++ b/SessionMessagingKit/File Server/FileServerAPI.swift @@ -19,7 +19,7 @@ public final class FileServerAPI : DotNetAPI { /// be other parameters in the request. On average the multiplier appears to be about 1.5, so when checking whether the file will exceed the file size limit when /// uploading a file we just divide the size of the file by this number. The alternative would be to actually check the size of the HTTP request but that's only /// possible after proof of work has been calculated and the onion request encryption has happened, which takes several seconds. - public static let fileSizeORMultiplier: Double = 3 + public static let fileSizeORMultiplier: Double = 2 @objc public static let server = "https://file.getsession.org" @objc public static let fileStorageBucketURL = "https://file-static.lokinet.org" diff --git a/SessionMessagingKit/Jobs/NotifyPNServerJob.swift b/SessionMessagingKit/Jobs/NotifyPNServerJob.swift index 5e4bd1090..b208c7ac8 100644 --- a/SessionMessagingKit/Jobs/NotifyPNServerJob.swift +++ b/SessionMessagingKit/Jobs/NotifyPNServerJob.swift @@ -35,7 +35,7 @@ public final class NotifyPNServerJob : NSObject, Job, NSCoding { // NSObject/NSC let request = TSRequest(url: url, method: "POST", parameters: parameters) request.allHTTPHeaderFields = [ "Content-Type" : "application/json" ] attempt(maxRetryCount: 4, recoveringOn: DispatchQueue.global()) { - OnionRequestAPI.sendOnionRequest(request, to: server, using: Configuration.shared.pnServerPublicKey).map { _ in } + OnionRequestAPI.sendOnionRequest(request, to: server, target: "/loki/v2/lsrpc", using: Configuration.shared.pnServerPublicKey).map { _ in } }.done(on: DispatchQueue.global()) { // Intentionally capture self self.handleSuccess() }.catch(on: DispatchQueue.global()) { error in diff --git a/SessionMessagingKit/Utilities/DotNetAPI.swift b/SessionMessagingKit/Utilities/DotNetAPI.swift index 609003b17..82f11d125 100644 --- a/SessionMessagingKit/Utilities/DotNetAPI.swift +++ b/SessionMessagingKit/Utilities/DotNetAPI.swift @@ -122,11 +122,11 @@ public class DotNetAPI : NSObject { return attempt(maxRetryCount: maxRetryCount, recoveringOn: DispatchQueue.global(qos: .userInitiated)) { serverPublicKeyPromise.then(on: DispatchQueue.global(qos: .userInitiated)) { serverPublicKey in return OnionRequestAPI.sendOnionRequest(request, to: host, using: serverPublicKey, isJSONRequired: false).map(on: DispatchQueue.global(qos: .userInitiated)) { json in - guard let body = json["body"] as? JSON, let data = body["data"] as? [UInt8] else { + guard let body = json["result"] as? String, let data = Data(base64Encoded: body) else { SNLog("Couldn't parse attachment from: \(json).") throw Error.parsingFailed } - return Data(data) + return data } } } diff --git a/SessionSnodeKit/OnionRequestAPI+Encryption.swift b/SessionSnodeKit/OnionRequestAPI+Encryption.swift index 8b6f0093f..b46ede035 100644 --- a/SessionSnodeKit/OnionRequestAPI+Encryption.swift +++ b/SessionSnodeKit/OnionRequestAPI+Encryption.swift @@ -27,7 +27,7 @@ internal extension OnionRequestAPI { let plaintext = try encode(ciphertext: payloadAsData, json: [ "headers" : "" ]) let result = try AESGCM.encrypt(plaintext, for: snodeX25519PublicKey) seal.fulfill(result) - case .server(_, let serverX25519PublicKey): + case .server(_, _, let serverX25519PublicKey): let plaintext = try JSONSerialization.data(withJSONObject: payload, options: [ .fragmentsAllowed ]) let result = try AESGCM.encrypt(plaintext, for: serverX25519PublicKey) seal.fulfill(result) @@ -48,8 +48,8 @@ internal extension OnionRequestAPI { case .snode(let snode): let snodeED25519PublicKey = snode.publicKeySet.ed25519Key parameters = [ "destination" : snodeED25519PublicKey ] - case .server(let host, _): - parameters = [ "host" : host, "target" : "/loki/v2/lsrpc", "method" : "POST" ] + case .server(let host, let target, _): + parameters = [ "host" : host, "target" : target, "method" : "POST" ] } parameters["ephemeral_key"] = previousEncryptionResult.ephemeralPublicKey.toHexString() let x25519PublicKey: String @@ -57,7 +57,7 @@ internal extension OnionRequestAPI { case .snode(let snode): let snodeX25519PublicKey = snode.publicKeySet.x25519Key x25519PublicKey = snodeX25519PublicKey - case .server(_, let serverX25519PublicKey): + case .server(_, _, let serverX25519PublicKey): x25519PublicKey = serverX25519PublicKey } do { diff --git a/SessionSnodeKit/OnionRequestAPI.swift b/SessionSnodeKit/OnionRequestAPI.swift index f73da2b1b..7cf51eb7b 100644 --- a/SessionSnodeKit/OnionRequestAPI.swift +++ b/SessionSnodeKit/OnionRequestAPI.swift @@ -26,7 +26,7 @@ public enum OnionRequestAPI { // MARK: Destination public enum Destination { case snode(Snode) - case server(host: String, x25519PublicKey: String) + case server(host: String, target: String, x25519PublicKey: String) } // MARK: Error @@ -284,7 +284,7 @@ public enum OnionRequestAPI { } /// Sends an onion request to `server`. Builds new paths as needed. - public static func sendOnionRequest(_ request: NSURLRequest, to server: String, using x25519PublicKey: String, isJSONRequired: Bool = true) -> Promise { + public static func sendOnionRequest(_ request: NSURLRequest, to server: String, target: String = "/loki/v3/lsrpc", using x25519PublicKey: String, isJSONRequired: Bool = true) -> Promise { var rawHeaders = request.allHTTPHeaderFields ?? [:] rawHeaders.removeValue(forKey: "User-Agent") var headers: JSON = rawHeaders.mapValues { value in @@ -327,7 +327,7 @@ public enum OnionRequestAPI { "method" : request.httpMethod!, "headers" : headers ] - let destination = Destination.server(host: host, x25519PublicKey: x25519PublicKey) + let destination = Destination.server(host: host, target: target, x25519PublicKey: x25519PublicKey) let promise = sendOnionRequest(with: payload, to: destination, isJSONRequired: isJSONRequired) promise.catch2 { error in SNLog("Couldn't reach server: \(url) due to error: \(error).") diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 640ba3bc0..3a6cde86a 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -7636,7 +7636,7 @@ CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 139; + CURRENT_PROJECT_VERSION = 143; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -7671,7 +7671,7 @@ "$(SRCROOT)", ); LLVM_LTO = NO; - MARKETING_VERSION = 1.6.4; + MARKETING_VERSION = 1.6.5; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger"; @@ -7703,7 +7703,7 @@ CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 139; + CURRENT_PROJECT_VERSION = 143; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -7738,7 +7738,7 @@ "$(SRCROOT)", ); LLVM_LTO = NO; - MARKETING_VERSION = 1.6.4; + MARKETING_VERSION = 1.6.5; OTHER_LDFLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger"; PRODUCT_NAME = Session; diff --git a/SignalUtilitiesKit/LokiPushNotificationManager.swift b/SignalUtilitiesKit/LokiPushNotificationManager.swift index d29e1b837..1d1c47095 100644 --- a/SignalUtilitiesKit/LokiPushNotificationManager.swift +++ b/SignalUtilitiesKit/LokiPushNotificationManager.swift @@ -30,7 +30,7 @@ public final class LokiPushNotificationManager : NSObject { let request = TSRequest(url: url, method: "POST", parameters: parameters) request.allHTTPHeaderFields = [ "Content-Type" : "application/json" ] let promise: Promise = attempt(maxRetryCount: maxRetryCount, recoveringOn: DispatchQueue.global()) { - OnionRequestAPI.sendOnionRequest(request, to: server, using: pnServerPublicKey).map2 { response in + OnionRequestAPI.sendOnionRequest(request, to: server, target: "/loki/v2/lsrpc", using: pnServerPublicKey).map2 { response in guard let json = response["body"] as? JSON else { return print("[Loki] Couldn't unregister from push notifications.") } @@ -72,7 +72,7 @@ public final class LokiPushNotificationManager : NSObject { let request = TSRequest(url: url, method: "POST", parameters: parameters) request.allHTTPHeaderFields = [ "Content-Type" : "application/json" ] let promise: Promise = attempt(maxRetryCount: maxRetryCount, recoveringOn: DispatchQueue.global()) { - OnionRequestAPI.sendOnionRequest(request, to: server, using: pnServerPublicKey).map2 { response in + OnionRequestAPI.sendOnionRequest(request, to: server, target: "/loki/v2/lsrpc", using: pnServerPublicKey).map2 { response in guard let json = response["body"] as? JSON else { return print("[Loki] Couldn't register device token.") } @@ -109,7 +109,7 @@ public final class LokiPushNotificationManager : NSObject { let request = TSRequest(url: url, method: "POST", parameters: parameters) request.allHTTPHeaderFields = [ "Content-Type" : "application/json" ] let promise: Promise = attempt(maxRetryCount: maxRetryCount, recoveringOn: DispatchQueue.global()) { - OnionRequestAPI.sendOnionRequest(request, to: server, using: pnServerPublicKey).map2 { response in + OnionRequestAPI.sendOnionRequest(request, to: server, target: "/loki/v2/lsrpc", using: pnServerPublicKey).map2 { response in guard let json = response["body"] as? JSON else { return print("[Loki] Couldn't subscribe/unsubscribe closed group: \(closedGroupPublicKey).") } @@ -131,7 +131,7 @@ public final class LokiPushNotificationManager : NSObject { let request = TSRequest(url: url, method: "POST", parameters: parameters) request.allHTTPHeaderFields = [ "Content-Type" : "application/json" ] let promise: Promise = attempt(maxRetryCount: maxRetryCount, recoveringOn: DispatchQueue.global()) { - OnionRequestAPI.sendOnionRequest(request, to: server, using: pnServerPublicKey).map2 { response in + OnionRequestAPI.sendOnionRequest(request, to: server, target: "/loki/v2/lsrpc", using: pnServerPublicKey).map2 { response in guard let json = response["body"] as? JSON else { return print("[Loki] Couldn't notify PN server.") } diff --git a/SignalUtilitiesKit/OWSAttachmentDownloads.m b/SignalUtilitiesKit/OWSAttachmentDownloads.m index c93b7ad25..908dba719 100644 --- a/SignalUtilitiesKit/OWSAttachmentDownloads.m +++ b/SignalUtilitiesKit/OWSAttachmentDownloads.m @@ -290,6 +290,13 @@ typedef void (^AttachmentDownloadFailure)(NSError *error); [job.attachmentPointer saveWithTransaction:transaction]; if (job.message) { + if (!CurrentAppContext().isMainApp) { + job.message.hasAttachmentsInNSE = true; + } else { + job.message.hasAttachmentsInNSE = false; + } + + [job.message saveWithTransaction:transaction]; [job.message touchWithTransaction:transaction]; } }]; diff --git a/SignalUtilitiesKit/OWSFailedAttachmentDownloadsJob.m b/SignalUtilitiesKit/OWSFailedAttachmentDownloadsJob.m index e653a69c1..c8483d415 100644 --- a/SignalUtilitiesKit/OWSFailedAttachmentDownloadsJob.m +++ b/SignalUtilitiesKit/OWSFailedAttachmentDownloadsJob.m @@ -25,6 +25,11 @@ static NSString *const OWSFailedAttachmentDownloadsJobAttachmentStateIndex = @"i @implementation OWSFailedAttachmentDownloadsJob +- (OWSAttachmentDownloads *)attachmentDownloads +{ + return SSKEnvironment.shared.attachmentDownloads; +} + - (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage { self = [super init]; diff --git a/SignalUtilitiesKit/OnionRequestAPI+Encryption.swift b/SignalUtilitiesKit/OnionRequestAPI+Encryption.swift index 77a195950..86dfec1f0 100644 --- a/SignalUtilitiesKit/OnionRequestAPI+Encryption.swift +++ b/SignalUtilitiesKit/OnionRequestAPI+Encryption.swift @@ -26,7 +26,7 @@ extension OnionRequestAPI { let plaintext = try encode(ciphertext: payloadAsData, json: [ "headers" : "" ]) let result = try EncryptionUtilities.encrypt(plaintext, using: snodeX25519PublicKey) seal.fulfill(result) - case .server(_, let serverX25519PublicKey): + case .server(_, _, let serverX25519PublicKey): let plaintext = try JSONSerialization.data(withJSONObject: payload, options: [ .fragmentsAllowed ]) let result = try EncryptionUtilities.encrypt(plaintext, using: serverX25519PublicKey) seal.fulfill(result) @@ -47,8 +47,8 @@ extension OnionRequestAPI { case .snode(let snode): let snodeED25519PublicKey = snode.publicKeySet.ed25519Key parameters = [ "destination" : snodeED25519PublicKey ] - case .server(let host, _): - parameters = [ "host" : host, "target" : "/loki/v2/lsrpc", "method" : "POST" ] + case .server(let host, let target, _): + parameters = [ "host" : host, "target" : target, "method" : "POST" ] } parameters["ephemeral_key"] = previousEncryptionResult.ephemeralPublicKey.toHexString() let x25519PublicKey: String @@ -56,7 +56,7 @@ extension OnionRequestAPI { case .snode(let snode): let snodeX25519PublicKey = snode.publicKeySet.x25519Key x25519PublicKey = snodeX25519PublicKey - case .server(_, let serverX25519PublicKey): + case .server(_, _, let serverX25519PublicKey): x25519PublicKey = serverX25519PublicKey } do { diff --git a/SignalUtilitiesKit/TSMessage.h b/SignalUtilitiesKit/TSMessage.h index fd26ade0c..bef830cad 100644 --- a/SignalUtilitiesKit/TSMessage.h +++ b/SignalUtilitiesKit/TSMessage.h @@ -34,6 +34,8 @@ NS_ASSUME_NONNULL_BEGIN // Open groups @property (nonatomic) uint64_t openGroupServerMessageID; @property (nonatomic, readonly) BOOL isOpenGroupMessage; +// Push notifications +@property (nonatomic) BOOL hasAttachmentsInNSE; - (instancetype)initInteractionWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread NS_UNAVAILABLE;