Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
6408b22
First more or less draft version of background calculations
dmitrysimkin Apr 16, 2025
4ff23a1
Try fix more message types
dmitrysimkin Apr 16, 2025
20c3ddb
Add logs
dmitrysimkin Apr 16, 2025
de354be
try fix reload individual cells
dmitrysimkin Apr 16, 2025
ac31a04
Merge branch 'develop' into chore/offload-conversation-calculation
dmitrysimkin Apr 16, 2025
a16f7ad
Fix accent color crash
dmitrysimkin Apr 16, 2025
bc2d602
Bring back cashing of controllers
dmitrysimkin Apr 16, 2025
2c10e5f
Try fix issues with actions
dmitrysimkin Apr 17, 2025
9e27b8f
Thread safe cache dict and global access accent color + prints
dmitrysimkin Apr 17, 2025
2b91715
Fixed too many updates
dmitrysimkin Apr 17, 2025
7c2e089
Improve sender cell
dmitrysimkin Apr 18, 2025
b9b9e6d
Try fix system message
dmitrysimkin Apr 18, 2025
2e9544e
Fix tests
dmitrysimkin Apr 21, 2025
9b12b59
Code style
dmitrysimkin Apr 21, 2025
b4d5260
Remove prints
dmitrysimkin Apr 21, 2025
5e26e30
Make safer
dmitrysimkin Apr 21, 2025
92e8676
FORMAT
dmitrysimkin Apr 21, 2025
cfee156
Revert atumockable
dmitrysimkin Apr 21, 2025
a17543a
Fixed crash with color
dmitrysimkin Apr 22, 2025
da42bdb
Fix building tests
dmitrysimkin Apr 22, 2025
665835f
Merge branch 'develop' into chore/offload-conversation-calculation
dmitrysimkin Apr 22, 2025
4393a72
Fix crash with unread messages
dmitrysimkin Apr 24, 2025
6564e7f
Improve perforamnce and crashes
dmitrysimkin Apr 25, 2025
914a6d1
Merge branch 'develop' into chore/offload-conversation-calculation
dmitrysimkin Apr 28, 2025
2d78a75
Format
dmitrysimkin Apr 28, 2025
1e52fe6
Re-create view background context
dmitrysimkin Apr 28, 2025
2ba7896
Merge branch 'develop' into chore/offload-conversation-calculation
dmitrysimkin Apr 29, 2025
d628c27
Code style
dmitrysimkin Apr 29, 2025
953e908
improve getting context and for tests
dmitrysimkin Apr 29, 2025
1534aeb
Improve getting main thread object from DB
dmitrysimkin Apr 29, 2025
0bca79e
Address PR comments
dmitrysimkin Apr 29, 2025
563c055
Address more comments
dmitrysimkin Apr 30, 2025
3d089bc
Code style
dmitrysimkin Apr 30, 2025
4844918
Merge branch 'develop' into chore/offload-conversation-calculation
dmitrysimkin May 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public class CoreDataStack: NSObject, ContextProvider {
public let accountContainer: URL
public let applicationContainer: URL

let messagesContainer: PersistentContainer
public let messagesContainer: PersistentContainer
let eventsContainer: PersistentContainer
let dispatchGroup: ZMSDispatchGroup?

Expand Down Expand Up @@ -562,7 +562,7 @@ public class CoreDataStack: NSObject, ContextProvider {

// MARK: -

class PersistentContainer: NSPersistentContainer {
public class PersistentContainer: NSPersistentContainer {

var storeURL: URL? {
persistentStoreDescriptions.first?.url
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ public typealias Conversation = ConversationLike & SwiftConversationLike
// sourcery: AutoMockable
@objc
public protocol ConversationLike: AnyObject {

var objectId: Any { get }
Comment thread
johnxnguyen marked this conversation as resolved.

var conversationType: ZMConversationType { get }
var isSelfAnActiveMember: Bool { get }
var teamRemoteIdentifier: UUID? { get }
Expand Down Expand Up @@ -70,6 +73,11 @@ public protocol SwiftConversationLike {
}

extension ZMConversation: ConversationLike {

public var objectId: Any {
objectID
}

public var localParticipantsCount: Int {
localParticipants.count
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,6 @@ public protocol ZMConversationMessage: NSObjectProtocol {
/// The replies quoting this message.
var replies: Set<ZMMessage> { get }

/// An in-memory identifier for tracking the message during its life cycle.
var objectIdentifier: String { get }

/// The links attached to the message.
var linkAttachments: [LinkAttachment]? { get set }

Expand Down Expand Up @@ -245,10 +242,6 @@ extension ZMMessage: ZMConversationMessage {
.sortedAscendingPrependingNil(by: \.serverTimestamp)
}

public var objectIdentifier: String {
nonpersistedObjectIdentifer
}

Comment thread
dmitrysimkin marked this conversation as resolved.
public var causedSecurityLevelDegradation: Bool {
false
}
Expand Down
2 changes: 2 additions & 0 deletions wire-ios-data-model/Source/Model/User/UserType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public protocol UserType: NSObjectProtocol, UserConnections {

/// The identifier which uniquely idenitifies the user in its domain
var remoteIdentifier: UUID! { get }

var objectId: Any { get }
Comment thread
dmitrysimkin marked this conversation as resolved.

/// The domain which the user originates from
var domain: String? { get }
Expand Down
4 changes: 3 additions & 1 deletion wire-ios-data-model/Source/Model/User/ZMSearchUser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ public class ZMSearchUser: NSObject, UserType {
public var teamIdentifier: UUID?
@objc public var user: ZMUser?
public private(set) var hasDownloadedFullUserProfile: Bool = false

public var objectId: Any {
user?.objectId ?? remoteIdentifier!
}
fileprivate weak var contextProvider: ContextProvider?
private let searchUsersCache: SearchUsersCache?

Expand Down
6 changes: 5 additions & 1 deletion wire-ios-data-model/Source/Model/User/ZMUser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ extension ZMUser: UserType {
}

public var accentColor: AccentColor? {
get { .init(rawValue: accentColorValue) }
get { .init(rawValue: accentColorValue) } // TODO: not optional?
set { accentColorValue = newValue?.rawValue ?? AccentColor.default.rawValue }
}

Expand Down Expand Up @@ -311,6 +311,10 @@ public extension ZMUser {
updatePrimaryKey(remoteIdentifier: newValue, domain: domain)
}
}

var objectId: Any {
return objectID
}

/// combination of domain and remoteIdentifier
@NSManaged private var primaryKey: String
Expand Down
30 changes: 0 additions & 30 deletions wire-ios-data-model/Source/Model/ZMManagedObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -768,33 +768,3 @@ - (BOOL)validateValue:(id *)ioValue forKey:(NSString *)key error:(NSError **)out
}

@end




@implementation ZMManagedObject (NonpersistedObjectIdentifer)

- (NSString *)nonpersistedObjectIdentifer;
{
return [NSString stringWithFormat:@"Z%tx", (unsigned long) self];
}

+ (instancetype)existingObjectWithNonpersistedObjectIdentifer:(NSString *)identifier inUserSession:(id<ContextProvider>)userSession;
{
VerifyReturnNil(identifier != nil);
intptr_t value = 0;
if (sscanf([identifier UTF8String], "Z%tx", &value) != 1) {
return nil;
}

NSManagedObjectContext *moc = userSession.viewContext;
for (ZMManagedObject *mo in moc.registeredObjects) {
intptr_t otherValue = (intptr_t) ((__bridge void *) mo);
if (otherValue == value) {
return mo;
}
}
return nil;
}

@end
8 changes: 0 additions & 8 deletions wire-ios-data-model/Source/Public/ZMManagedObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,3 @@ extern NSString * _Nonnull const ZMDataPropertySuffix;
- (nullable NSString *)objectIDURLString;

@end

@interface ZMManagedObject (NonpersistedObjectIdentifer)

@property (nonatomic, readonly, nonnull) NSString *nonpersistedObjectIdentifer;

+ (nullable instancetype)existingObjectWithNonpersistedObjectIdentifer:(nullable NSString *)identifier inUserSession:(nonnull id<ContextProvider>)userSession;

@end

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,6 @@ public class MockZMConversationMessage: NSObject, ZMConversationMessage {

public var underlyingReplies: Set<ZMMessage>!

// MARK: - objectIdentifier

public var objectIdentifier: String {
get { return underlyingObjectIdentifier }
set(value) { underlyingObjectIdentifier = value }
}

public var underlyingObjectIdentifier: String!

// MARK: - linkAttachments

public var linkAttachments: [LinkAttachment]?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -692,39 +692,4 @@ extension ZMClientMessageTests_Editing {
XCTAssertEqual(editedMessage.textMessageData?.messageText, editedText)
XCTAssertEqual(editedMessage, newMessage)
}

func testThatMessageNonPersistedIdentifierDoesNotChangeAfterEdit() {
// given
let oldText = "Mamma mia"
let newText = "here we go again"
let oldNonce = UUID.create()

let sender = ZMUser.insertNewObject(in: uiMOC)
sender.remoteIdentifier = UUID.create()

let conversation = ZMConversation.insertNewObject(in: uiMOC)
conversation.remoteIdentifier = UUID.create()
let message: ZMMessage = try! conversation.appendText(content: oldText) as! ZMMessage
message.sender = sender
message.nonce = oldNonce

let oldIdentifier = message.nonpersistedObjectIdentifer
let updateEvent = createMessageEditUpdateEvent(
oldNonce: message.nonce!,
newNonce: UUID.create(),
conversationID: conversation.remoteIdentifier!,
senderID: message.sender!.remoteIdentifier!,
newText: newText
)

// when
var newMessage: ZMClientMessage?
performPretendingUiMocIsSyncMoc {
newMessage = ZMClientMessage.createOrUpdate(from: updateEvent!, in: self.uiMOC, prefetchResult: nil)
}

// then
XCTAssertNotEqual(oldNonce, newMessage!.nonce)
XCTAssertEqual(oldIdentifier, newMessage!.nonpersistedObjectIdentifer)
}
}
72 changes: 0 additions & 72 deletions wire-ios-data-model/Tests/Source/Model/ZMManagedObjectTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -430,78 +430,6 @@ - (void)testThatDeletedObjectsAreZombiesAfterASave

@implementation ZMManagedObjectTests (NonpersistedObjectIdentifer)

- (void)testThatItReturnsTheSameIdentifierForTemporaryAndSavedObjects;
{
// given
ZMConversation *mo = [ZMConversation insertNewObjectInManagedObjectContext:self.uiMOC];

// when
NSString *s1 = [[mo nonpersistedObjectIdentifer] copy];
XCTAssert([self.uiMOC saveOrRollback]);
NSString *s2 = [[mo nonpersistedObjectIdentifer] copy];

// then
XCTAssertNotNil(s1);
XCTAssertEqualObjects(s1, s2);
}

- (void)testThatItReturnsAnObjectForANonpersistedObjectIdentifier
{
// given
ZMConversation *mo = [ZMConversation insertNewObjectInManagedObjectContext:self.uiMOC];
NSString *identifier = [[mo nonpersistedObjectIdentifer] copy];

// when
ZMConversation *mo2 = (id)[ZMManagedObject existingObjectWithNonpersistedObjectIdentifer:identifier inUserSession:self.coreDataStack];

// then
XCTAssertEqual(mo, mo2);
}

- (void)testThatItReturnsAnObjectForANonpersistedObjectIdentifierAfterASave
{
// given
ZMConversation *mo = [ZMConversation insertNewObjectInManagedObjectContext:self.uiMOC];
NSString *identifier = [[mo nonpersistedObjectIdentifer] copy];

// when
XCTAssert([self.uiMOC saveOrRollback]);
ZMConversation *mo2 = (id)[ZMManagedObject existingObjectWithNonpersistedObjectIdentifer:identifier inUserSession:self.coreDataStack];

// then
XCTAssertEqual(mo, mo2);
}

- (void)testThatItReturnsNilForANilIdentifier;
{
// given
id objectIdentifier = nil;

// then
[self performIgnoringZMLogError:^{
XCTAssertNil([ZMManagedObject existingObjectWithNonpersistedObjectIdentifer:objectIdentifier inUserSession:self.coreDataStack]);
}];
}

- (void)testThatItReturnsNilForANonExistingIdentifier;
{
// given
__block NSString *identifier;
[self.syncMOC performGroupedBlockAndWait:^{
ZMConversation *mo = [ZMConversation insertNewObjectInManagedObjectContext:self.syncMOC];
identifier = [[mo nonpersistedObjectIdentifer] copy];
}];

// then
XCTAssertNil([ZMManagedObject existingObjectWithNonpersistedObjectIdentifer:identifier inUserSession:self.coreDataStack]);
}

- (void)testThatItReturnsNilForAnInvalidExistingIdentifier;
{
XCTAssertNil([ZMManagedObject existingObjectWithNonpersistedObjectIdentifer:@"foo" inUserSession:self.coreDataStack]);
XCTAssertNil([ZMManagedObject existingObjectWithNonpersistedObjectIdentifer:@"Zfoo" inUserSession:self.coreDataStack]);
}

- (void)testPerformanceRetrievingLocallyModifiedKeys;
{
// measured with NSSet implementation: average: 0.000, relative standard deviation: 33.239%, values: [0.000581, 0.000390, 0.000353, 0.000351, 0.000269, 0.000238, 0.000249, 0.000239, 0.000239, 0.000237],
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions wire-ios-sync-engine/Source/UserSession/UserSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -292,4 +292,6 @@ public protocol UserSession: AnyObject {

/// Cache for search users.
var searchUsersCache: SearchUsersCache { get }

func performBackgroundTask(_ block: @escaping (NSManagedObjectContext) -> Void)
}
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,12 @@ extension ZMUserSession: UserSession {
isFederationUsageAllowed: isFederationUsageAllowed
)
}

public func performBackgroundTask(
_ block: @escaping (NSManagedObjectContext) -> Void
) {
coreDataStack.messagesContainer.performBackgroundTask(block)
}

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public final class ZMUserSession: NSObject {

private(set) var isNetworkOnline = true

private(set) var coreDataStack: CoreDataStack!
private(set) public var coreDataStack: CoreDataStack!
private let apiServiceFactory: APIServiceFactory
public var apiService: APIServiceProtocol? {
guard let clientId = selfUserClient?.remoteIdentifier else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1295,5 +1295,11 @@ public class MockUserSession: UserSession {
fatalError("no mock for `e2eIdentityUpdateCertificateUpdateStatus`")
}
}

public func performBackgroundTask(
_ block: @escaping (NSManagedObjectContext) -> Void
) {
block(contextProvider.viewContext)
}

}
1 change: 1 addition & 0 deletions wire-ios/Tests/Mocks/MockConversation.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
NS_CLASS_DEPRECATED_IOS(4_0, 13_0, "Use SwiftMockConversation instead")
@interface MockConversation : NSObject<Mockable>

@property (nonatomic, copy) id objectId;
@property (nonatomic, copy) NSString *displayName;
@property (nonatomic) id<LabelType> folder;
@property (nonatomic) ZMUser *creator;
Expand Down
2 changes: 2 additions & 0 deletions wire-ios/Tests/Mocks/MockConversation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import WireRequestStrategy
// swiftlint:disable:next todo_requires_jira_link
// TODO: rename to MockConversation after objc MockConversation is retired
class SwiftMockConversation: NSObject, Conversation {

var objectId: Any = UUID()

var isMLSConversationDegraded: Bool = false
var isProteusConversationDegraded: Bool = false
Expand Down
1 change: 0 additions & 1 deletion wire-ios/Tests/Mocks/MockMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,6 @@ class MockMessage: NSObject, ZMConversationMessage, ConversationCompositeMessage

var causedSecurityLevelDegradation: Bool = false
var needsReadConfirmation: Bool = false
let objectIdentifier: String = UUID().uuidString
var linkAttachments: [LinkAttachment]?
var needsLinkAttachmentsUpdate: Bool = false
var isSilenced: Bool = false
Expand Down
3 changes: 3 additions & 0 deletions wire-ios/Tests/Mocks/MockUserType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ class MockUserType: NSObject, UserType, Decodable, EditableUserType {

var teamIdentifier: UUID?
var remoteIdentifier: UUID?
var objectId: Any {
remoteIdentifier ?? UUID()
}

var canLeaveConversation = false
var canCreateConversation = true
Expand Down
7 changes: 7 additions & 0 deletions wire-ios/Tests/Mocks/UserSessionMock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,13 @@ final class UserSessionMock: UserSession {
var contextProvider: any ContextProvider {
coreDataStack ?? MockContextProvider()
}

var performBackgroundTaskReturnValue: NSManagedObjectContext?
func performBackgroundTask(
_ block: @escaping (NSManagedObjectContext) -> Void
) {
block(performBackgroundTaskReturnValue ?? viewContext)
}

}

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading