diff --git a/Session/Conversations/Settings/ThreadDisappearingMessagesSettingsViewModel.swift b/Session/Conversations/Settings/ThreadDisappearingMessagesSettingsViewModel.swift index f18393cc5..0aab4b7e5 100644 --- a/Session/Conversations/Settings/ThreadDisappearingMessagesSettingsViewModel.swift +++ b/Session/Conversations/Settings/ThreadDisappearingMessagesSettingsViewModel.swift @@ -516,8 +516,16 @@ class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel CONVO_EXPIRATION_MODE { + func toLibSession() -> CONVO_EXPIRATION_MODE { switch self { case .unknown: return CONVO_EXPIRATION_NONE case .disappearAfterRead: return CONVO_EXPIRATION_AFTER_READ diff --git a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ExpirationTimers.swift b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ExpirationTimers.swift index ee6b4f061..844062004 100644 --- a/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ExpirationTimers.swift +++ b/SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ExpirationTimers.swift @@ -64,9 +64,16 @@ extension MessageReceiver { .filter(Interaction.Columns.variant == Interaction.Variant.infoDisappearingMessagesUpdate) .deleteAll(db) - // Legacy closed groups need to update the SessionUtil - // TODO: I assume we need to update the contact config here? + // Contacts & legacy closed groups need to update the SessionUtil switch threadVariant { + case .contact: + try SessionUtil + .update( + db, + sessionId: threadId, + disappearingMessagesConfig: remoteConfig + ) + case .legacyGroup: try SessionUtil .update( @@ -152,9 +159,16 @@ extension MessageReceiver { .filter(Interaction.Columns.variant == Interaction.Variant.infoDisappearingMessagesUpdate) .deleteAll(db) - // Legacy closed groups need to update the SessionUtil - // TODO: I assume we need to update the contact config here? + // Contacts & legacy closed groups need to update the SessionUtil switch threadVariant { + case .contact: + try SessionUtil + .update( + db, + sessionId: threadId, + disappearingMessagesConfig: remoteConfig + ) + case .legacyGroup: try SessionUtil .update( diff --git a/SessionMessagingKit/SessionUtil/Config Handling/SessionUtil+Contacts.swift b/SessionMessagingKit/SessionUtil/Config Handling/SessionUtil+Contacts.swift index 570541e40..d35d97397 100644 --- a/SessionMessagingKit/SessionUtil/Config Handling/SessionUtil+Contacts.swift +++ b/SessionMessagingKit/SessionUtil/Config Handling/SessionUtil+Contacts.swift @@ -41,7 +41,7 @@ internal extension SessionUtil { String: ( contact: Contact, profile: Profile, - disappearingMessagesConfig: DisappearingMessagesConfiguration, + config: DisappearingMessagesConfiguration, priority: Int32, created: TimeInterval ) @@ -78,7 +78,7 @@ internal extension SessionUtil { ) ) ) - let disappearingMessagesConfigResult: DisappearingMessagesConfiguration = DisappearingMessagesConfiguration( + let configResult: DisappearingMessagesConfiguration = DisappearingMessagesConfiguration( threadId: contactId, isEnabled: contact.exp_seconds > 0, durationSeconds: TimeInterval(contact.exp_seconds), @@ -89,7 +89,7 @@ internal extension SessionUtil { contactData[contactId] = ( contactResult, profileResult, - disappearingMessagesConfigResult, + configResult, contact.priority, TimeInterval(contact.created) ) @@ -172,20 +172,20 @@ internal extension SessionUtil { } // Update disappearing messages configuration if needed - let localDisappearingMessagesConfig: DisappearingMessagesConfiguration = try DisappearingMessagesConfiguration + let localConfig: DisappearingMessagesConfiguration = try DisappearingMessagesConfiguration .fetchOne(db, id: sessionId) .defaulting(to: DisappearingMessagesConfiguration.defaultWith(sessionId)) if - let remoteLastChangeTimestampMs = data.disappearingMessagesConfig.lastChangeTimestampMs, - let localLastChangeTimestampMs = localDisappearingMessagesConfig.lastChangeTimestampMs, + let remoteLastChangeTimestampMs = data.config.lastChangeTimestampMs, + let localLastChangeTimestampMs = localConfig.lastChangeTimestampMs, remoteLastChangeTimestampMs > localLastChangeTimestampMs { - _ = try localDisappearingMessagesConfig.with( - isEnabled: data.disappearingMessagesConfig.isEnabled, - durationSeconds: data.disappearingMessagesConfig.durationSeconds, - type: data.disappearingMessagesConfig.type, - lastChangeTimestampMs: data.disappearingMessagesConfig.lastChangeTimestampMs + _ = try localConfig.with( + isEnabled: data.config.isEnabled, + durationSeconds: data.config.durationSeconds, + type: data.config.type, + lastChangeTimestampMs: data.config.lastChangeTimestampMs ).save(db) } @@ -384,11 +384,11 @@ internal extension SessionUtil { // Assign all properties to match the updated disappearing messages configuration (if there is one) if - let updatedDisappearingMessageConfig: DisappearingMessagesConfiguration = info.disappearingMessagesConfig, - let exp_mode: CONVO_EXPIRATION_MODE = updatedDisappearingMessageConfig.type?.toSessionUtilType() + let updatedConfig: DisappearingMessagesConfiguration = info.config, + let exp_mode: CONVO_EXPIRATION_MODE = updatedConfig.type?.toLibSession() { contact.exp_mode = exp_mode - contact.exp_seconds = Int32(updatedDisappearingMessageConfig.durationSeconds) + contact.exp_seconds = Int32(updatedConfig.durationSeconds) } // Store the updated contact (can't be sure if we made any changes above) @@ -513,28 +513,6 @@ internal extension SessionUtil { return updated } - - static func updatingDisappearingMessagesConfigs(_ db: Database, _ updated: [T]) throws -> [T] { - guard let updatedDisappearingMessagesConfigs: [DisappearingMessagesConfiguration] = updated as? [DisappearingMessagesConfiguration] else { throw StorageError.generic } - - let userPublicKey: String = getUserHexEncodedPublicKey(db) - guard !updatedDisappearingMessagesConfigs.isEmpty else { return updated } - - try SessionUtil.performAndPushChange( - db, - for: .contacts, - publicKey: userPublicKey - ) { conf in - try SessionUtil - .upsert( - contactData: updatedDisappearingMessagesConfigs - .map { SyncedContactInfo(id: $0.id, disappearingMessagesConfig: $0) }, - in: conf - ) - } - - return updated - } } // MARK: - External Outgoing Changes @@ -576,6 +554,41 @@ public extension SessionUtil { } } } + + static func update( + _ db: Database, + sessionId: String, + disappearingMessagesConfig: DisappearingMessagesConfiguration + ) throws { + let userPublicKey: String = getUserHexEncodedPublicKey(db) + if sessionId == userPublicKey { + try SessionUtil.performAndPushChange( + db, + for: .userProfile, + publicKey: userPublicKey + ) { conf in + try SessionUtil.updateNoteToSelf( + disappearingMessagesConfig: disappearingMessagesConfig, + in: conf + ) + } + } else { + try SessionUtil.performAndPushChange( + db, + for: .contacts, + publicKey: userPublicKey + ) { conf in + try SessionUtil + .upsert( + contactData: [SyncedContactInfo( + id: sessionId, + disappearingMessagesConfig: disappearingMessagesConfig + )], + in: conf + ) + } + } + } } // MARK: - SyncedContactInfo @@ -585,7 +598,7 @@ extension SessionUtil { let id: String let contact: Contact? let profile: Profile? - let disappearingMessagesConfig: DisappearingMessagesConfiguration? + let config: DisappearingMessagesConfiguration? let priority: Int32? init( @@ -598,7 +611,7 @@ extension SessionUtil { self.id = id self.contact = contact self.profile = profile - self.disappearingMessagesConfig = disappearingMessagesConfig + self.config = disappearingMessagesConfig self.priority = priority } } diff --git a/SessionMessagingKit/SessionUtil/Config Handling/SessionUtil+UserProfile.swift b/SessionMessagingKit/SessionUtil/Config Handling/SessionUtil+UserProfile.swift index 920eb3e47..f0db85f84 100644 --- a/SessionMessagingKit/SessionUtil/Config Handling/SessionUtil+UserProfile.swift +++ b/SessionMessagingKit/SessionUtil/Config Handling/SessionUtil+UserProfile.swift @@ -54,6 +54,49 @@ internal extension SessionUtil { calledFromConfigHandling: true ) + // Update the 'Note to Self' disappearing messages configuration + var contact: contacts_contact = contacts_contact() + let contactIterator: UnsafeMutablePointer = contacts_iterator_new(conf) + var config: DisappearingMessagesConfiguration? + while !contacts_iterator_done(contactIterator, &contact) { + let contactId: String = String(cString: withUnsafeBytes(of: contact.session_id) { [UInt8]($0) } + .map { CChar($0) } + .nullTerminated() + ) + + guard contactId == userPublicKey else { continue } + + config = DisappearingMessagesConfiguration( + threadId: contactId, + isEnabled: contact.exp_seconds > 0, + durationSeconds: TimeInterval(contact.exp_seconds), + type: DisappearingMessagesConfiguration.DisappearingMessageType(sessionUtilType: contact.exp_mode), + lastChangeTimestampMs: Int64(latestConfigUpdateSentTimestamp) + ) + + break + } + contacts_iterator_free(contactIterator) // Need to free the iterator + + if let targetConfig: DisappearingMessagesConfiguration = config { + let localConfig: DisappearingMessagesConfiguration = try DisappearingMessagesConfiguration + .fetchOne(db, id: userPublicKey) + .defaulting(to: DisappearingMessagesConfiguration.defaultWith(userPublicKey)) + + if + let remoteLastChangeTimestampMs = targetConfig.lastChangeTimestampMs, + let localLastChangeTimestampMs = localConfig.lastChangeTimestampMs, + remoteLastChangeTimestampMs > localLastChangeTimestampMs + { + _ = try localConfig.with( + isEnabled: targetConfig.isEnabled, + durationSeconds: targetConfig.durationSeconds, + type: targetConfig.type, + lastChangeTimestampMs: targetConfig.lastChangeTimestampMs + ).save(db) + } + } + // Update the 'Note to Self' visibility and priority let threadInfo: PriorityVisibilityInfo? = try? SessionThread .filter(id: userPublicKey) @@ -150,11 +193,30 @@ internal extension SessionUtil { } static func updateNoteToSelf( - priority: Int32, + priority: Int32? = nil, + disappearingMessagesConfig: DisappearingMessagesConfiguration? = nil, in conf: UnsafeMutablePointer? ) throws { guard conf != nil else { throw SessionUtilError.nilConfigObject } - user_profile_set_nts_priority(conf, priority) + if let priority: Int32 = priority { + user_profile_set_nts_priority(conf, priority) + } + + // TODO: Make this into LibSession like user_profile_set_nts_priority() + if + let config: DisappearingMessagesConfiguration = disappearingMessagesConfig, + let exp_mode: CONVO_EXPIRATION_MODE = config.type?.toLibSession() + { + var userPublicKey: String = getUserHexEncodedPublicKey() + var userContact: contacts_contact = contacts_contact() + guard contacts_get_or_construct(conf, &userContact, &userPublicKey) else { + SNLog("Unable to upsert note-to-self to SessionUtil: \(SessionUtil.lastError(conf))") + throw SessionUtilError.getOrConstructFailedUnexpectedly + } + userContact.exp_mode = exp_mode + userContact.exp_seconds = Int32(config.durationSeconds) + contacts_set(conf, &userContact) + } } }