diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index 7915419e5..3f59874b7 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -6040,7 +6040,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 392; + CURRENT_PROJECT_VERSION = 393; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; @@ -6065,7 +6065,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.2.7; + MARKETING_VERSION = 2.2.8; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.ShareExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -6113,7 +6113,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 392; + CURRENT_PROJECT_VERSION = 393; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = SUQ8J2PCT7; ENABLE_NS_ASSERTIONS = NO; @@ -6143,7 +6143,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.2.7; + MARKETING_VERSION = 2.2.8; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.ShareExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -6179,7 +6179,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 392; + CURRENT_PROJECT_VERSION = 393; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; @@ -6202,7 +6202,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.2.7; + MARKETING_VERSION = 2.2.8; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.NotificationServiceExtension"; @@ -6253,7 +6253,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 392; + CURRENT_PROJECT_VERSION = 393; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = SUQ8J2PCT7; ENABLE_NS_ASSERTIONS = NO; @@ -6281,7 +6281,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.2.7; + MARKETING_VERSION = 2.2.8; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.NotificationServiceExtension"; @@ -7181,7 +7181,7 @@ CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 392; + CURRENT_PROJECT_VERSION = 393; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -7220,7 +7220,7 @@ "$(SRCROOT)", ); LLVM_LTO = NO; - MARKETING_VERSION = 2.2.7; + MARKETING_VERSION = 2.2.8; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger"; @@ -7253,7 +7253,7 @@ CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 392; + CURRENT_PROJECT_VERSION = 393; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -7292,7 +7292,7 @@ "$(SRCROOT)", ); LLVM_LTO = NO; - MARKETING_VERSION = 2.2.7; + MARKETING_VERSION = 2.2.8; OTHER_LDFLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger"; PRODUCT_NAME = Session; diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index a5802c836..f4d029b1d 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -461,10 +461,17 @@ extension ConversationVC: .filter(id: threadId) .updateAll(db, SessionThread.Columns.shouldBeVisible.set(to: true)) + let authorId: String = { + if let blindedId = self?.viewModel.threadData.currentUserBlindedPublicKey { + return blindedId + } + return self?.viewModel.threadData.currentUserPublicKey ?? getUserHexEncodedPublicKey(db) + }() + // Create the interaction let interaction: Interaction = try Interaction( threadId: threadId, - authorId: getUserHexEncodedPublicKey(db), + authorId: authorId, variant: .standardOutgoing, body: text, timestampMs: sentTimestampMs, @@ -1519,6 +1526,7 @@ extension ConversationVC: } } + Modal.setupForIPadIfNeeded(sheet, targetView: self.view) present(sheet, animated: true, completion: nil) } @@ -2369,6 +2377,7 @@ extension ConversationVC { }) alertVC.addAction(UIAlertAction(title: "TXT_CANCEL_TITLE".localized(), style: .cancel, handler: nil)) + Modal.setupForIPadIfNeeded(alertVC, targetView: self.view) self.present(alertVC, animated: true, completion: nil) } @@ -2416,6 +2425,7 @@ extension ConversationVC { }) alertVC.addAction(UIAlertAction(title: "TXT_CANCEL_TITLE".localized(), style: .cancel, handler: nil)) + Modal.setupForIPadIfNeeded(alertVC, targetView: self.view) self.present(alertVC, animated: true, completion: nil) } } diff --git a/Session/Conversations/ConversationViewModel.swift b/Session/Conversations/ConversationViewModel.swift index b37e53b90..d21d932d0 100644 --- a/Session/Conversations/ConversationViewModel.swift +++ b/Session/Conversations/ConversationViewModel.swift @@ -82,7 +82,11 @@ public class ConversationViewModel: OWSAudioPlayerDelegate { // distinct stutter) self.pagedDataObserver = self.setupPagedObserver( for: threadId, - userPublicKey: getUserHexEncodedPublicKey() + userPublicKey: getUserHexEncodedPublicKey(), + blindedPublicKey: SessionThread.getUserHexEncodedBlindedKey( + threadId: threadId, + threadVariant: threadVariant + ) ) // Run the initial query on a background thread so we don't block the push transition @@ -172,7 +176,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate { } } - private func setupPagedObserver(for threadId: String, userPublicKey: String) -> PagedDatabaseObserver { + private func setupPagedObserver(for threadId: String, userPublicKey: String, blindedPublicKey: String?) -> PagedDatabaseObserver { return PagedDatabaseObserver( pagedTable: Interaction.self, pageSize: ConversationViewModel.pageSize, @@ -220,6 +224,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate { orderSQL: MessageViewModel.orderSQL, dataQuery: MessageViewModel.baseQuery( userPublicKey: userPublicKey, + blindedPublicKey: blindedPublicKey, orderSQL: MessageViewModel.orderSQL, groupSQL: MessageViewModel.groupSQL ), @@ -458,7 +463,8 @@ public class ConversationViewModel: OWSAudioPlayerDelegate { self.observableThreadData = self.setupObservableThreadData(for: updatedThreadId) self.pagedDataObserver = self.setupPagedObserver( for: updatedThreadId, - userPublicKey: getUserHexEncodedPublicKey() + userPublicKey: getUserHexEncodedPublicKey(), + blindedPublicKey: nil ) // Try load everything up to the initial visible message, fallback to just the initial page of messages diff --git a/Session/Home/Message Requests/MessageRequestsViewController.swift b/Session/Home/Message Requests/MessageRequestsViewController.swift index 619ff0792..2dfbbf89f 100644 --- a/Session/Home/Message Requests/MessageRequestsViewController.swift +++ b/Session/Home/Message Requests/MessageRequestsViewController.swift @@ -449,6 +449,8 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat } }) alertVC.addAction(UIAlertAction(title: "TXT_CANCEL_TITLE".localized(), style: .cancel, handler: nil)) + + Modal.setupForIPadIfNeeded(alertVC, targetView: self.view) self.present(alertVC, animated: true, completion: nil) } @@ -470,6 +472,8 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat }) alertVC.addAction(UIAlertAction(title: "TXT_CANCEL_TITLE".localized(), style: .cancel, handler: nil)) + + Modal.setupForIPadIfNeeded(alertVC, targetView: self.view) self.present(alertVC, animated: true, completion: nil) } @@ -501,6 +505,8 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat }) alertVC.addAction(UIAlertAction(title: "TXT_CANCEL_TITLE".localized(), style: .cancel, handler: nil)) + + Modal.setupForIPadIfNeeded(alertVC, targetView: self.view) self.present(alertVC, animated: true, completion: nil) } } diff --git a/Session/Notifications/SyncPushTokensJob.swift b/Session/Notifications/SyncPushTokensJob.swift index 4b80934b4..61fb77c80 100644 --- a/Session/Notifications/SyncPushTokensJob.swift +++ b/Session/Notifications/SyncPushTokensJob.swift @@ -20,8 +20,11 @@ public enum SyncPushTokensJob: JobExecutor { failure: @escaping (Job, Error?, Bool) -> (), deferred: @escaping (Job) -> () ) { - // Don't run when inactive or not in main app - guard (UserDefaults.sharedLokiProject?[.isMainAppActive]).defaulting(to: false) else { + // Don't run when inactive or not in main app or if the user doesn't exist yet + guard + (UserDefaults.sharedLokiProject?[.isMainAppActive]).defaulting(to: false), + Identity.userExists() + else { deferred(job) // Don't need to do anything if it's not the main app return } diff --git a/SessionMessagingKit/Database/Models/SessionThread.swift b/SessionMessagingKit/Database/Models/SessionThread.swift index ca08aa182..f5d743acf 100644 --- a/SessionMessagingKit/Database/Models/SessionThread.swift +++ b/SessionMessagingKit/Database/Models/SessionThread.swift @@ -322,18 +322,31 @@ public extension SessionThread { ) -> String? { guard threadVariant == .openGroup, - let blindingInfo: (edkeyPair: Box.KeyPair?, publicKey: String?) = Storage.shared.read({ db in + let blindingInfo: (edkeyPair: Box.KeyPair?, publicKey: String?, capabilities: Set) = Storage.shared.read({ db in + struct OpenGroupInfo: Decodable, FetchableRecord { + let publicKey: String? + let server: String? + } + let openGroupInfo: OpenGroupInfo? = try OpenGroup + .filter(id: threadId) + .select(.publicKey, .server) + .asRequest(of: OpenGroupInfo.self) + .fetchOne(db) + return ( Identity.fetchUserEd25519KeyPair(db), - try OpenGroup - .filter(id: threadId) - .select(.publicKey) - .asRequest(of: String.self) - .fetchOne(db) + openGroupInfo?.publicKey, + (try? Capability + .select(.variant) + .filter(Capability.Columns.openGroupServer == openGroupInfo?.server?.lowercased()) + .asRequest(of: Capability.Variant.self) + .fetchSet(db)) + .defaulting(to: []) ) }), let userEdKeyPair: Box.KeyPair = blindingInfo.edkeyPair, - let publicKey: String = blindingInfo.publicKey + let publicKey: String = blindingInfo.publicKey, + blindingInfo.capabilities.isEmpty || blindingInfo.capabilities.contains(.blind) else { return nil } let sodium: Sodium = Sodium() diff --git a/SessionMessagingKit/Messages/Visible Messages/VisibleMessage.swift b/SessionMessagingKit/Messages/Visible Messages/VisibleMessage.swift index 980d90b70..2780ae0eb 100644 --- a/SessionMessagingKit/Messages/Visible Messages/VisibleMessage.swift +++ b/SessionMessagingKit/Messages/Visible Messages/VisibleMessage.swift @@ -44,6 +44,7 @@ public final class VisibleMessage: Message { // MARK: - Initialization public init( + sender: String? = nil, sentTimestamp: UInt64? = nil, recipient: String? = nil, groupPublicKey: String? = nil, @@ -68,6 +69,7 @@ public final class VisibleMessage: Message { super.init( sentTimestamp: sentTimestamp, recipient: recipient, + sender: sender, groupPublicKey: groupPublicKey ) } @@ -228,6 +230,7 @@ public extension VisibleMessage { let linkPreview: LinkPreview? = try? interaction.linkPreview.fetchOne(db) return VisibleMessage( + sender: interaction.authorId, sentTimestamp: UInt64(interaction.timestampMs), recipient: (try? interaction.recipientStates.fetchOne(db))?.recipientId, groupPublicKey: try? interaction.thread diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender.swift b/SessionMessagingKit/Sending & Receiving/MessageSender.swift index 85746de0b..32bb8cbc5 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender.swift @@ -318,7 +318,6 @@ public final class MessageSender { dependencies: SMKDependencies = SMKDependencies() ) -> Promise { let (promise, seal) = Promise.pending() - let threadId: String // Set the timestamp, sender and recipient if message.sentTimestamp == nil { // Visible messages will already have their sent timestamp set @@ -328,7 +327,6 @@ public final class MessageSender { switch destination { case .contact, .closedGroup, .openGroupInbox: preconditionFailure() case .openGroup(let roomToken, let server, let whisperTo, let whisperMods, _): - threadId = OpenGroup.idFor(roomToken: roomToken, server: server) message.recipient = [ server, roomToken, @@ -343,34 +341,12 @@ public final class MessageSender { // which would go into this case, so rather than handling it as an invalid state we just want to // error in a non-retryable way guard - let openGroup: OpenGroup = try? OpenGroup.fetchOne(db, id: threadId), - let userEdKeyPair: Box.KeyPair = Identity.fetchUserEd25519KeyPair(db), case .openGroup(let roomToken, let server, let whisperTo, let whisperMods, let fileIds) = destination else { seal.reject(MessageSenderError.invalidMessage) return promise } - message.sender = { - let capabilities: [Capability.Variant] = (try? Capability - .select(.variant) - .filter(Capability.Columns.openGroupServer == server) - .filter(Capability.Columns.isMissing == false) - .asRequest(of: Capability.Variant.self) - .fetchAll(db)) - .defaulting(to: []) - - // If the server doesn't support blinding then go with an unblinded id - guard capabilities.isEmpty || capabilities.contains(.blind) else { - return SessionId(.unblinded, publicKey: userEdKeyPair.publicKey).hexString - } - guard let blindedKeyPair: Box.KeyPair = dependencies.sodium.blindedKeyPair(serverPublicKey: openGroup.publicKey, edKeyPair: userEdKeyPair, genericHash: dependencies.genericHash) else { - preconditionFailure() - } - - return SessionId(.blinded, publicKey: blindedKeyPair.publicKey).hexString - }() - // Set the failure handler (need it here already for precondition failure handling) func handleFailure(_ db: Database, with error: MessageSenderError) { MessageSender.handleFailedMessageSend(db, message: message, with: error, interactionId: interactionId) @@ -467,7 +443,6 @@ public final class MessageSender { dependencies: SMKDependencies = SMKDependencies() ) -> Promise { let (promise, seal) = Promise.pending() - let currentUserPublicKey: String = getUserHexEncodedPublicKey(db, dependencies: dependencies) guard case .openGroupInbox(let server, let openGroupPublicKey, let recipientBlindedPublicKey) = destination else { preconditionFailure() @@ -478,7 +453,6 @@ public final class MessageSender { message.sentTimestamp = UInt64(SnodeAPI.currentOffsetTimestampMs()) } - message.sender = currentUserPublicKey message.recipient = recipientBlindedPublicKey // Set the failure handler (need it here already for precondition failure handling) @@ -628,7 +602,6 @@ public final class MessageSender { // real message has no use when we delete a message. It is OK to let it be. try interaction.with( serverHash: message.serverHash, - // Track the open group server message ID and update server timestamp (use server // timestamp for open group messages otherwise the quote messages may not be able // to be found by the timestamp on other devices @@ -774,21 +747,19 @@ public final class MessageSender { if let message = message as? VisibleMessage { message.syncTarget = publicKey } if let message = message as? ExpirationTimerUpdate { message.syncTarget = publicKey } - Storage.shared.write { db in - JobRunner.add( - db, - job: Job( - variant: .messageSend, - threadId: threadId, - interactionId: interactionId, - details: MessageSendJob.Details( - destination: .contact(publicKey: currentUserPublicKey), - message: message, - isSyncMessage: true - ) + JobRunner.add( + db, + job: Job( + variant: .messageSend, + threadId: threadId, + interactionId: interactionId, + details: MessageSendJob.Details( + destination: .contact(publicKey: currentUserPublicKey), + message: message, + isSyncMessage: true ) ) - } + ) } } } diff --git a/SessionMessagingKit/Shared Models/MessageViewModel.swift b/SessionMessagingKit/Shared Models/MessageViewModel.swift index ece71bca3..e2a1917cc 100644 --- a/SessionMessagingKit/Shared Models/MessageViewModel.swift +++ b/SessionMessagingKit/Shared Models/MessageViewModel.swift @@ -629,6 +629,7 @@ public extension MessageViewModel { static func baseQuery( userPublicKey: String, + blindedPublicKey: String?, orderSQL: SQL, groupSQL: SQL? ) -> (([Int64]) -> AdaptedFetchRequest>) { @@ -726,7 +727,12 @@ public extension MessageViewModel { \(interactionAttachment[.attachmentId]) AS \(Quote.Columns.attachmentId) FROM \(Quote.self) LEFT JOIN \(Interaction.self) ON ( - \(quote[.authorId]) = \(interaction[.authorId]) AND + ( + \(quote[.authorId]) = \(interaction[.authorId]) OR ( + \(quote[.authorId]) = \(blindedPublicKey ?? "") AND + \(userPublicKey) = \(interaction[.authorId]) + ) + ) AND \(quote[.timestampMs]) = \(interaction[.timestampMs]) ) LEFT JOIN \(InteractionAttachment.self) ON \(interaction[.id]) = \(interactionAttachment[.interactionId])