Skip to content

Commit

Permalink
Merge branch 'release/cycle-3.116' into fix/Crash-dismissPresentedVie…
Browse files Browse the repository at this point in the history
…wController-WPB-15345
  • Loading branch information
netbe authored Jan 29, 2025
2 parents de7af39 + 7fe488e commit 277f4d2
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ struct OneOnOneResolver: OneOnOneResolverProtocol {

await switchLocalConversationToMLS(
mlsConversation: mlsConversation,
for: user
for: user,
userID: userID
)
}

Expand Down Expand Up @@ -219,15 +220,38 @@ struct OneOnOneResolver: OneOnOneResolverProtocol {

private func switchLocalConversationToMLS(
mlsConversation: ZMConversation,
for user: ZMUser
for user: ZMUser,
userID: WireDataModel.QualifiedID
) async {
await context.perform {
/// Move local messages from proteus conversation if it exists
if let proteusConversation = user.oneOnOneConversation {
/// Since ZMMessages only have a single conversation connected,
/// forming this union also removes the relationship to the proteus conversation.

// Note on proteus, it's possible to have 2 duplicate 1-1 conversations, so we need to fetch both
// conversations here.
let proteusConversations: [ZMConversation] = fetchAllTeamOneOnOneProteusConversations(
otherUserID: userID,
in: context
)

var allProteusConversations = Set(proteusConversations)
if let existingConversation = user.oneOnOneConversation,
existingConversation.messageProtocol == .proteus {
allProteusConversations.insert(existingConversation)
}

// move local messages from proteus conversations if they exist
for proteusConversation in allProteusConversations {
// Since ZMMessages only have a single conversation connected,
// forming this union also removes the relationship to the proteus conversation.
mlsConversation.mutableMessages.union(proteusConversation.allMessages)
}

// insert system message that we moved from proteus to MLS
let sender = ZMUser.selfUser(in: context)
mlsConversation.appendMLSMigrationFinalizedSystemMessage(sender: sender, at: .now)

if !allProteusConversations.isEmpty {
mlsConversation.isForcedReadOnly = false
// update just to be sure
mlsConversation.needsToBeUpdatedFromBackend = true
}

Expand All @@ -236,6 +260,37 @@ struct OneOnOneResolver: OneOnOneResolverProtocol {
}
}

private func fetchAllTeamOneOnOneProteusConversations(
otherUserID: WireDataModel.QualifiedID,
in context: NSManagedObjectContext
) -> [ZMConversation] {
guard let otherUser = ZMUser.fetch(with: otherUserID, in: context) else {
return []
}
let selfUser = ZMUser.selfUser(in: context)
guard selfUser.team != nil else {
return []
}

let request = NSFetchRequest<ZMConversation>(entityName: ZMConversation.entityName())
let teamOneOnOnePredicate = ZMConversation.predicateForTeamOneToOneConversation()

let sameParticipant = NSPredicate(
format: "ANY %K.user == %@ AND ANY %K.user == %@",
ZMConversationParticipantRolesKey,
otherUser,
ZMConversationParticipantRolesKey,
selfUser
)

request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [
teamOneOnOnePredicate,
sameParticipant
])

return context.fetchOrAssert(request: request)
}

/// Resolves a Proteus 1:1 conversation.
/// - Parameter user: The user to resolve the conversation for.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,19 @@ final class OneOnOneResolverTests: XCTestCase {

// Then

await context.perform {
let migratedMessagesTexts = mlsOneOnOneConversation.allMessages
try await context.perform { [self] in
let allMessages = mlsOneOnOneConversation.allMessages

try XCTAssertCount(allMessages, count: 3)
let mlsSystemMessage = try XCTUnwrap(mlsOneOnOneConversation.lastMessage as? ZMSystemMessage)
XCTAssertEqual(
mlsSystemMessage.systemMessageType.rawValue,
ZMSystemMessageType.mlsMigrationFinalized.rawValue
)

XCTAssertEqual(mlsOneOnOneConversation.needsToBeUpdatedFromBackend, true)

let migratedMessagesTexts = allMessages
.compactMap(\.textMessageData)
.compactMap(\.messageText)
.sorted()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public struct OneOnOneMigrator: OneOnOneMigratorInterface {
)

await context.perform {

_ = context.saveOrRollback()
}

Expand Down Expand Up @@ -166,6 +167,10 @@ public struct OneOnOneMigrator: OneOnOneMigratorInterface {
mlsConversation.mutableMessages.union(proteusConversation.allMessages)
}

// insert system message that we moved from proteus to MLS
let sender = ZMUser.selfUser(in: context)
mlsConversation.appendMLSMigrationFinalizedSystemMessage(sender: sender, at: .now)

if !proteusConversations.isEmpty {
// update just to be sure
mlsConversation.needsToBeUpdatedFromBackend = true
Expand Down
13 changes: 9 additions & 4 deletions wire-ios-data-model/Tests/OneOnOne/OneOnOneMigratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -244,13 +244,16 @@ final class OneOnOneMigratorTests: XCTestCase {
)

// Then
await syncContext.perform {
try await syncContext.perform {
let mlsMessages = mlsConversation.allMessages.sortedAscendingPrependingNil(by: \.serverTimestamp)
XCTAssertEqual(mlsMessages.count, 3)
XCTAssertEqual(mlsMessages.count, 4)
XCTAssertEqual(mlsMessages[0].textMessageData?.messageText, "Hello World!")
XCTAssertTrue(mlsMessages[1].isKnock)
XCTAssertTrue(mlsMessages[2].isImage)

let systemMessage = try XCTUnwrap(mlsMessages[3] as? ZMSystemMessage)
XCTAssertEqual(systemMessage.systemMessageType, .mlsMigrationFinalized)

XCTAssertNil(proteusConversation.lastMessage)
}
withExtendedLifetime(handler) {}
Expand Down Expand Up @@ -351,14 +354,15 @@ final class OneOnOneMigratorTests: XCTestCase {
// Then
await syncContext.perform {
let mlsMessages = mlsConversation.allMessages.sortedAscendingPrependingNil(by: \.serverTimestamp)
let expectedMessagesCount = 6
let expectedMessagesCount = 7
if mlsMessages.count == expectedMessagesCount {
XCTAssertEqual(mlsMessages[0].textMessageData?.messageText, "Hello World!")
XCTAssertTrue(mlsMessages[1].isKnock)
XCTAssertTrue(mlsMessages[2].isImage)
XCTAssertEqual(mlsMessages[3].textMessageData?.messageText, "Hello World Dup!")
XCTAssertTrue(mlsMessages[4].isKnock)
XCTAssertTrue(mlsMessages[5].isImage)
XCTAssertTrue(mlsMessages[6].isSystem)
} else {
XCTFail("messages count is \(mlsMessages.count) instead of \(expectedMessagesCount)")
}
Expand Down Expand Up @@ -497,7 +501,7 @@ final class OneOnOneMigratorTests: XCTestCase {
// Then
await syncContext.perform {
let mlsMessages = mlsConversation.allMessages.sortedAscendingPrependingNil(by: \.serverTimestamp)
let expectedMessagesCount = 9
let expectedMessagesCount = 10
if mlsMessages.count == expectedMessagesCount {
XCTAssertEqual(mlsMessages[0].textMessageData?.messageText, "Hello World!")
XCTAssertTrue(mlsMessages[1].isKnock)
Expand All @@ -508,6 +512,7 @@ final class OneOnOneMigratorTests: XCTestCase {
XCTAssertEqual(mlsMessages[6].textMessageData?.messageText, "Hello World 1!")
XCTAssertEqual(mlsMessages[7].textMessageData?.messageText, "Hello World 2!")
XCTAssertEqual(mlsMessages[8].textMessageData?.messageText, "Hello World 3!")
XCTAssertTrue(mlsMessages[9].isSystem)
} else {
XCTFail("messages count is \(mlsMessages.count) instead of \(expectedMessagesCount)")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
// along with this program. If not, see http://www.gnu.org/licenses/.
//

import Foundation
import WireDataModel

public extension ZMLocalNotification {
Expand Down Expand Up @@ -191,6 +192,17 @@ private class ConversationCreateEventNotificationBuilder: EventNotificationBuild
LocalNotificationType.event(.conversationCreated)
}

override func shouldCreateNotification() -> Bool {
if conversation == nil {
// WPB-8946: fixes bug: notifications shown even though availability is busy or away
let availability = moc.performAndWait { ZMUser.selfUser(in: moc).availability }
return [.none, .available].contains(availability)
}

// default behavior
return super.shouldCreateNotification()
}

}

// MARK: - Conversation Delete Event
Expand Down Expand Up @@ -322,7 +334,12 @@ private class NewMessageNotificationBuilder: EventNotificationBuilder {
"Not creating local notification for message with nonce = \(event.messageNonce) because conversation is silenced"
)
return false
} else if conversation == nil {
// WPB-8946: fixes bug: notifications shown even though availability is busy or away
let availability = moc.performAndWait { ZMUser.selfUser(in: moc).availability }
return [.none, .available].contains(availability)
}

if ZMUser.selfUser(in: moc).remoteIdentifier == event.senderUUID {
return false
}
Expand Down
12 changes: 11 additions & 1 deletion wire-ios/Wire-iOS/Sources/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,11 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
}

func applicationProtectedDataDidBecomeAvailable(_ application: UIApplication) {
guard appRootRouter == nil else { return }
WireLogger.appDelegate.info("applicationProtectedDataDidBecomeAvailable", attributes: .safePublic)
guard appRootRouter == nil else {
WireLogger.appDelegate.debug("applicationProtectedDataDidBecomeAvailable: appRootRouter nil")
return
}
createAppRootRouterAndInitialiazeOperations(launchOptions)
}
}
Expand All @@ -347,6 +351,12 @@ private extension AppDelegate {
fatalError("sessionManager is not created")
}

guard mainWindow != nil else {
WireLogger.appDelegate.critical("no mainWindow this should not be possible at this point")
assertionFailure("no mainWindow this should not be possible at this point")
return
}

appRootRouter = AppRootRouter(
mainWindow: mainWindow,
sessionManager: sessionManager,
Expand Down

0 comments on commit 277f4d2

Please sign in to comment.